package andraus.bluetoothhidemu.sock; import java.io.IOException; import andraus.bluetoothhidemu.BluetoothHidEmuActivity; import andraus.bluetoothhidemu.sock.payload.HidPayload; import andraus.bluetoothhidemu.spoof.BluetoothAdapterSpoofer; import andraus.bluetoothhidemu.util.DoLog; import andraus.bluetoothhidemu.view.BluetoothDeviceView; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; /** * Singleton * */ public class SocketManager { private String TAG = BluetoothHidEmuActivity.TAG; private static SocketManager mInstance = null; public static final int STATE_NONE = BluetoothSocketThread.STATE_NONE; public static final int STATE_WAITING = BluetoothSocketThread.STATE_WAITING; public static final int STATE_ACCEPTED = BluetoothSocketThread.STATE_ACCEPTED; public static final int STATE_DROPPING = BluetoothSocketThread.STATE_DROPPING; public static final int STATE_DROPPED = BluetoothSocketThread.STATE_DROPPED; private BluetoothAdapterSpoofer mSpoofer = null; private BluetoothSocketThread mCtrlThread = null; private BluetoothSocketThread mIntrThread = null; /** * * @param bluetoothAdapter * @param connHelper */ private SocketManager(BluetoothAdapterSpoofer connHelper) { mSpoofer = connHelper; } /** * * @param connHelper * @return */ public static SocketManager getInstance(BluetoothAdapterSpoofer connHelper) { if (mInstance == null) { mInstance = new SocketManager(connHelper); } return mInstance; } /** * */ public void destroyThreads() { mCtrlThread = null; mIntrThread = null; } /** * * @param hidPayload */ public void sendPayload(HidPayload hidPayload) { if (mIntrThread != null && mIntrThread.isAlive()) { mIntrThread.sendBytes(hidPayload.getPayload()); } } /** * * @param thread * @param name * @param hostDevice * @param socketPort * @return */ private BluetoothSocketThread initThread(BluetoothSocketThread thread, String name, BluetoothDevice hostDevice, int socketPort) { BluetoothSocket socket; try { socket = mSpoofer.connectL2capSocket(hostDevice, socketPort, true, true); } catch (IOException e) { DoLog.e(TAG, String.format("Cannot acquire %sSocket", name), e); throw new RuntimeException(e); } if (socket != null) { DoLog.d(TAG, String.format("%s socket successfully created: %s", name, socket)); } return new BluetoothSocketThread(socket, name); } /** * Init sockets and threads * * @param adapter * @param device */ public void startSockets(BluetoothAdapter adapter, BluetoothDeviceView deviceView) { BluetoothDevice device = deviceView.getBluetoothDevice(); if (device == null) { DoLog.w(TAG, "no hosts not found"); return; } else { DoLog.d(TAG, "host selected: " + device); } // discovery is a heavy process. Apps must always cancel it when connecting. adapter.cancelDiscovery(); mCtrlThread = initThread(mCtrlThread, "ctrl", device, 0x11); mIntrThread = initThread(mIntrThread, "intr", device, 0x13); mCtrlThread.start(); mIntrThread.start(); } /** * Stop L2CAP "control" and "interrupt" channel threads */ public void stopSockets() { DoLog.d(TAG, "stop bluetooth connections"); if (mIntrThread != null) { mIntrThread.sendBytes(HidPayload.disconnectReq()); mIntrThread.stopGracefully(); mIntrThread = null; } if (mCtrlThread != null) { mCtrlThread.stopGracefully(); mCtrlThread = null; } } public boolean checkState(int state) { return mCtrlThread != null && (mCtrlThread.getConnectionState() == state || mIntrThread.getConnectionState() == state); } }