diff options
Diffstat (limited to 'src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java')
-rw-r--r-- | src/android/bluetooth/client/pbap/BluetoothPbapObexSession.java | 232 |
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) { + } + } + } + } +} |