summaryrefslogtreecommitdiffstats
path: root/src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java')
-rw-r--r--src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java b/src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java
new file mode 100644
index 0000000..f558cc4
--- /dev/null
+++ b/src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.client.pbap;
+
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.IOException;
+
+import javax.obex.ClientSession;
+import javax.obex.HeaderSet;
+import javax.obex.ObexTransport;
+import javax.obex.ResponseCodes;
+
+final class BluetoothPbapObexSession {
+ private static final String TAG = "BluetoothPbapObexSession";
+
+ private static final byte[] PBAP_TARGET = new byte[] {
+ 0x79, 0x61, 0x35, (byte) 0xf0, (byte) 0xf0, (byte) 0xc5, 0x11, (byte) 0xd8, 0x09, 0x66,
+ 0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66
+ };
+
+ final static int OBEX_SESSION_CONNECTED = 100;
+ final static int OBEX_SESSION_FAILED = 101;
+ final static int OBEX_SESSION_DISCONNECTED = 102;
+ final static int OBEX_SESSION_REQUEST_COMPLETED = 103;
+ final static int OBEX_SESSION_REQUEST_FAILED = 104;
+ final static int OBEX_SESSION_AUTHENTICATION_REQUEST = 105;
+ final static int OBEX_SESSION_AUTHENTICATION_TIMEOUT = 106;
+
+ private Handler mSessionHandler;
+ private final ObexTransport mTransport;
+ private ObexClientThread mObexClientThread;
+ private BluetoothPbapObexAuthenticator mAuth = null;
+
+ public BluetoothPbapObexSession(ObexTransport transport) {
+ mTransport = transport;
+ }
+
+ public void start(Handler handler) {
+ Log.d(TAG, "start");
+ mSessionHandler = handler;
+
+ mAuth = new BluetoothPbapObexAuthenticator(mSessionHandler);
+
+ mObexClientThread = new ObexClientThread();
+ mObexClientThread.start();
+ }
+
+ public void stop() {
+ Log.d(TAG, "stop");
+
+ if (mObexClientThread != null) {
+ try {
+ mObexClientThread.interrupt();
+ mObexClientThread.join();
+ mObexClientThread = null;
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ public void abort() {
+ Log.d(TAG, "abort");
+
+ if (mObexClientThread != null && mObexClientThread.mRequest != null) {
+ /*
+ * since abort may block until complete GET is processed inside OBEX
+ * session, let's run it in separate thread so it won't block UI
+ */
+ (new Thread() {
+ @Override
+ public void run() {
+ mObexClientThread.mRequest.abort();
+ }
+ }).run();
+ }
+ }
+
+ public boolean schedule(BluetoothPbapRequest request) {
+ Log.d(TAG, "schedule: " + request.getClass().getSimpleName());
+
+ if (mObexClientThread == null) {
+ Log.e(TAG, "OBEX session not started");
+ return false;
+ }
+
+ return mObexClientThread.schedule(request);
+ }
+
+ public boolean setAuthReply(String key) {
+ Log.d(TAG, "setAuthReply key=" + key);
+
+ if (mAuth == null) {
+ return false;
+ }
+
+ mAuth.setReply(key);
+
+ return true;
+ }
+
+ private class ObexClientThread extends Thread {
+
+ private static final String TAG = "ObexClientThread";
+
+ private ClientSession mClientSession;
+ private BluetoothPbapRequest mRequest;
+
+ private volatile boolean mRunning = true;
+
+ public ObexClientThread() {
+
+ mClientSession = null;
+ mRequest = null;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+
+ if (!connect()) {
+ mSessionHandler.obtainMessage(OBEX_SESSION_FAILED).sendToTarget();
+ return;
+ }
+
+ mSessionHandler.obtainMessage(OBEX_SESSION_CONNECTED).sendToTarget();
+
+ while (mRunning) {
+ synchronized (this) {
+ try {
+ if (mRequest == null) {
+ this.wait();
+ }
+ } catch (InterruptedException e) {
+ mRunning = false;
+ break;
+ }
+ }
+
+ if (mRunning && mRequest != null) {
+ try {
+ mRequest.execute(mClientSession);
+ } catch (IOException e) {
+ // this will "disconnect" for cleanup
+ mRunning = false;
+ }
+
+ if (mRequest.isSuccess()) {
+ mSessionHandler.obtainMessage(OBEX_SESSION_REQUEST_COMPLETED, mRequest)
+ .sendToTarget();
+ } else {
+ mSessionHandler.obtainMessage(OBEX_SESSION_REQUEST_FAILED, mRequest)
+ .sendToTarget();
+ }
+ }
+
+ mRequest = null;
+ }
+
+ disconnect();
+
+ mSessionHandler.obtainMessage(OBEX_SESSION_DISCONNECTED).sendToTarget();
+ }
+
+ public synchronized boolean schedule(BluetoothPbapRequest request) {
+ Log.d(TAG, "schedule: " + request.getClass().getSimpleName());
+
+ if (mRequest != null) {
+ return false;
+ }
+
+ mRequest = request;
+ notify();
+
+ return true;
+ }
+
+ private boolean connect() {
+ Log.d(TAG, "connect");
+
+ try {
+ mClientSession = new ClientSession(mTransport);
+ mClientSession.setAuthenticator(mAuth);
+ } catch (IOException e) {
+ return false;
+ }
+
+ HeaderSet hs = new HeaderSet();
+ hs.setHeader(HeaderSet.TARGET, PBAP_TARGET);
+
+ try {
+ hs = mClientSession.connect(hs);
+
+ if (hs.getResponseCode() != ResponseCodes.OBEX_HTTP_OK) {
+ disconnect();
+ return false;
+ }
+ } catch (IOException e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private void disconnect() {
+ Log.d(TAG, "disconnect");
+
+ if (mClientSession != null) {
+ try {
+ mClientSession.disconnect(null);
+ mClientSession.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+}