package android.app;
import java.util.List;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.IBinder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class FaketoothService extends Service {
private final String TAG = "FaketoothService";
private boolean mReceiverRegistered;
private String mBluetoothProfile;
private Context mContext;
private AudioManager mAudioManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothHeadset mBluetoothHeadset;
private FaketoothA2DPThread mA2DPThread;
private FaketoothSCOThread mSCOThread;
private FaketoothSCOMicThread mSCOMicThread;
private final BroadcastReceiver mSCOAudioStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
mSCOThread = new FaketoothSCOThread();
if (mSCOThread != null) {
mSCOThread.start();
while (mSCOThread.threadHandler == null)
;
mSCOThread.threadHandler.sendEmptyMessage(0);
}
mSCOMicThread = new FaketoothSCOMicThread();
if (mSCOMicThread != null) {
mSCOMicThread.start();
while (mSCOMicThread.threadHandler == null)
;
mSCOMicThread.threadHandler.sendEmptyMessage(0);
}
}
}
};
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
List<BluetoothDevice> pairedDevices = mBluetoothHeadset.getConnectedDevices();
if (pairedDevices.size() > 0) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
mContext.registerReceiver(mSCOAudioStateReceiver, intentFilter);
mReceiverRegistered = true;
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
}
}
}
@Override
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
}
};
@Override
public void onCreate() {
super.onCreate();
mContext = this;
mReceiverRegistered = false;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mBluetoothProfile = intent.getExtras().getString("BluetoothProfile");
if (mBluetoothProfile.equals("A2DP")) {
mA2DPThread = new FaketoothA2DPThread();
if (mA2DPThread != null) {
mA2DPThread.start();
while (mA2DPThread.threadHandler == null)
;
mA2DPThread.threadHandler.sendEmptyMessage(0);
}
} else if (mBluetoothProfile.equals("SCO")) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET);
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mA2DPThread != null)
mA2DPThread.flag = false;
if (mSCOThread != null)
mSCOThread.flag = false;
if (mSCOMicThread != null)
mSCOMicThread.flag = false;
if (mAudioManager != null) {
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
}
if (mReceiverRegistered)
unregisterReceiver(mSCOAudioStateReceiver);
if (mBluetoothAdapter != null && mBluetoothHeadset != null)
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
class FaketoothA2DPThread extends Thread {
public Handler threadHandler;
public boolean flag = true;
public void run() {
Looper.prepare();
threadHandler = new Handler() {
public void handleMessage(Message msg) {
while (flag) {
while (flag && nativeFaketoothA2DPInit() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothA2DPEnable() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothA2DPDo() == 0) {
}
nativeFaketoothA2DPDisable();
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
}
};
Looper.loop();
}
}
class FaketoothSCOThread extends Thread {
public Handler threadHandler;
public boolean flag = true;
public void run() {
Looper.prepare();
threadHandler = new Handler() {
public void handleMessage(Message msg) {
while (flag) {
while (flag && nativeFaketoothSCOInit() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothSCOEnable() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothSCODo() == 0) {
}
nativeFaketoothSCODisable();
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
}
};
Looper.loop();
}
}
class FaketoothSCOMicThread extends Thread {
public Handler threadHandler;
public boolean flag = true;
public void run() {
Looper.prepare();
threadHandler = new Handler() {
public void handleMessage(Message msg) {
while (flag) {
while (flag && nativeFaketoothSCOMicInit() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothSCOMicEnable() < 0) {
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
while (flag && nativeFaketoothSCOMicDo() == 0) {
}
nativeFaketoothSCOMicDisable();
try { Thread.sleep(100); }
catch (InterruptedException e) {}
}
}
};
Looper.loop();
}
}
static {
System.loadLibrary("faketooth");
}
private native int nativeFaketoothA2DPInit();
private native int nativeFaketoothA2DPEnable();
private native int nativeFaketoothA2DPDo();
private native int nativeFaketoothA2DPDisable();
private native int nativeFaketoothSCOInit();
private native int nativeFaketoothSCOEnable();
private native int nativeFaketoothSCODo();
private native int nativeFaketoothSCODisable();
private native int nativeFaketoothSCOMicInit();
private native int nativeFaketoothSCOMicEnable();
private native int nativeFaketoothSCOMicDo();
private native int nativeFaketoothSCOMicDisable();
}