summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanket Agarwal <sanketa@google.com>2015-06-19 11:34:03 -0700
committerSanket Agarwal <sanketa@google.com>2015-07-14 15:27:50 -0700
commitd1ac8e05b6671626ac702ec57277689b7338bc32 (patch)
tree00467a344de1652f3fc88accef6962007ba251fb
parent4231be1e03b7c5e563fea1fa7c56abfe2a1e61dd (diff)
downloadbluetooth-d1ac8e05b6671626ac702ec57277689b7338bc32.tar.gz
Mas Obex client should use Handler instead of threads.
Using threads has the following issues currently: * Can only handle one enqueue in flight. Makes the client dependent on checking sanity. * Uses interrupts to clean up which can lead to race conditions. Change-Id: Id3b2e2199fea2347dd2b7102ec60004e996fe344
-rw-r--r--src/android/bluetooth/client/map/BluetoothMasObexClientSession.java207
1 files changed, 101 insertions, 106 deletions
diff --git a/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java b/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java
index f949b8d..9bf75d4 100644
--- a/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java
+++ b/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java
@@ -17,10 +17,14 @@
package android.bluetooth.client.map;
import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
import android.os.Process;
import android.util.Log;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import javax.obex.ClientSession;
import javax.obex.HeaderSet;
@@ -35,97 +39,120 @@ class BluetoothMasObexClientSession {
0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66
};
+ private boolean DBG = true;
+
static final int MSG_OBEX_CONNECTED = 100;
static final int MSG_OBEX_DISCONNECTED = 101;
static final int MSG_REQUEST_COMPLETED = 102;
+ private static final int CONNECT = 0;
+ private static final int DISCONNECT = 1;
+ private static final int REQUEST = 2;
+
private final ObexTransport mTransport;
private final Handler mSessionHandler;
- private ClientThread mClientThread;
+ private ClientSession mSession;
- private volatile boolean mInterrupted;
+ private HandlerThread mThread;
+ private Handler mHandler;
- private class ClientThread extends Thread {
- private final ObexTransport mTransport;
+ private boolean mConnected;
- private ClientSession mSession;
+ private static class ObexClientHandler extends Handler {
+ WeakReference<BluetoothMasObexClientSession> mInst;
- private BluetoothMasRequest mRequest;
+ ObexClientHandler(Looper looper, BluetoothMasObexClientSession inst) {
+ super(looper);
+ mInst = new WeakReference<BluetoothMasObexClientSession>(inst);
+ }
- private boolean mConnected;
+ @Override
+ public void handleMessage(Message msg) {
+ BluetoothMasObexClientSession inst = mInst.get();
+ if (!inst.connected() && msg.what != CONNECT) {
+ Log.w(TAG, "Cannot execute " + msg + " when not CONNECTED.");
+ return;
+ }
- public ClientThread(ObexTransport transport) {
- super("MAS ClientThread");
+ switch (msg.what) {
+ case CONNECT:
+ inst.connect();
+ break;
- mTransport = transport;
- mConnected = false;
- }
+ case DISCONNECT:
+ inst.disconnect();
+ break;
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ case REQUEST:
+ inst.executeRequest((BluetoothMasRequest) msg.obj);
+ break;
+ }
+ }
+ }
- connect();
+ public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) {
+ mTransport = transport;
+ mSessionHandler = handler;
+ }
- if (mConnected) {
- mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget();
- } else {
- mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
- return;
- }
+ public void start() {
+ if (DBG) Log.d(TAG, "start called.");
+ if (mConnected) {
+ if (DBG) Log.d(TAG, "Already connected, nothing to do.");
+ return;
+ }
- while (!mInterrupted) {
- synchronized (this) {
- if (mRequest == null) {
- try {
- this.wait();
- } catch (InterruptedException e) {
- mInterrupted = true;
- }
- }
- }
-
- if (!mInterrupted && mRequest != null) {
- try {
- mRequest.execute(mSession);
- } catch (IOException e) {
- // this will "disconnect" to cleanup
- mInterrupted = true;
- }
-
- BluetoothMasRequest oldReq = mRequest;
- mRequest = null;
-
- mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, oldReq).sendToTarget();
- }
- }
+ // Start a thread to handle messages here.
+ mThread = new HandlerThread("BluetoothMasObexClientSessionThread");
+ mThread.start();
+ mHandler = new ObexClientHandler(mThread.getLooper(), this);
- disconnect();
+ // Connect it to the target device via OBEX.
+ mHandler.obtainMessage(CONNECT).sendToTarget();
+ }
- mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
+ public boolean makeRequest(BluetoothMasRequest request) {
+ if (DBG) Log.d(TAG, "makeRequest called with: " + request);
+
+ boolean status = mHandler.sendMessage(mHandler.obtainMessage(REQUEST, request));
+ if (!status) {
+ Log.e(TAG, "Adding messages failed, state: " + mConnected);
+ return false;
}
+ return true;
+ }
- private void connect() {
- try {
- mSession = new ClientSession(mTransport);
+ public void stop() {
+ if (DBG) Log.d(TAG, "stop called...");
- HeaderSet headerset = new HeaderSet();
- headerset.setHeader(HeaderSet.TARGET, MAS_TARGET);
+ mThread.quit();
+ disconnect();
+ }
- headerset = mSession.connect(headerset);
+ private void connect() {
+ try {
+ mSession = new ClientSession(mTransport);
- if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) {
- mConnected = true;
- } else {
- disconnect();
- }
- } catch (IOException e) {
+ HeaderSet headerset = new HeaderSet();
+ headerset.setHeader(HeaderSet.TARGET, MAS_TARGET);
+
+ headerset = mSession.connect(headerset);
+
+ if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) {
+ mConnected = true;
+ mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget();
+ } else {
+ disconnect();
}
+ } catch (IOException e) {
+ disconnect();
}
+ }
- private void disconnect() {
+ private void disconnect() {
+ if (mSession != null) {
try {
mSession.disconnect(null);
} catch (IOException e) {
@@ -135,58 +162,26 @@ class BluetoothMasObexClientSession {
mSession.close();
} catch (IOException e) {
}
-
- mConnected = false;
- }
-
- public synchronized boolean schedule(BluetoothMasRequest request) {
- if (mRequest != null) {
- return false;
- }
-
- mRequest = request;
- notify();
-
- return true;
}
- }
- public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) {
- mTransport = transport;
- mSessionHandler = handler;
+ mConnected = false;
+ mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
}
- public void start() {
- if (mClientThread == null) {
- mClientThread = new ClientThread(mTransport);
- mClientThread.start();
- }
-
- }
+ private void executeRequest(BluetoothMasRequest request) {
+ try {
+ request.execute(mSession);
+ mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, request).sendToTarget();
+ } catch (IOException e) {
+ if (DBG) Log.d(TAG, "Request failed: " + request);
- public void stop() {
- if (mClientThread != null) {
- mClientThread.interrupt();
-
- (new Thread() {
- @Override
- public void run() {
- try {
- mClientThread.join();
- mClientThread = null;
- } catch (InterruptedException e) {
- Log.w(TAG, "Interrupted while waiting for thread to join");
- }
- }
- }).run();
+ // Disconnect to cleanup.
+ disconnect();
}
}
- public boolean makeRequest(BluetoothMasRequest request) {
- if (mClientThread == null) {
- return false;
- }
- return mClientThread.schedule(request);
+ private boolean connected() {
+ return mConnected;
}
}