1192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta/* 2192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Copyright (C) 2014 The Android Open Source Project 3192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * 4192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Licensed under the Apache License, Version 2.0 (the "License"); 5192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * you may not use this file except in compliance with the License. 6192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * You may obtain a copy of the License at 7192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * 8192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * http://www.apache.org/licenses/LICENSE-2.0 9192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * 10192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * Unless required by applicable law or agreed to in writing, software 11192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * distributed under the License is distributed on an "AS IS" BASIS, 12192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * See the License for the specific language governing permissions and 14192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta * limitations under the License. 15192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta */ 16192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 17192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptapackage android.bluetooth.client.map; 18192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 19192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Handler; 20192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.os.Process; 21192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport android.util.Log; 22192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 23192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport java.io.IOException; 24192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 25192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport javax.obex.ClientSession; 26192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport javax.obex.HeaderSet; 27192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport javax.obex.ObexTransport; 28192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaimport javax.obex.ResponseCodes; 29192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 30192d793d2586b620027edd5b45ff4c72a86cc7beHemant Guptaclass BluetoothMasObexClientSession { 31192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private static final String TAG = "BluetoothMasObexClientSession"; 32192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 33192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private static final byte[] MAS_TARGET = new byte[] { 34192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta (byte) 0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, (byte) 0xdb, (byte) 0xb0, (byte) 0xde, 35192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66 36192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta }; 37192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 38192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta static final int MSG_OBEX_CONNECTED = 100; 39192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta static final int MSG_OBEX_DISCONNECTED = 101; 40192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta static final int MSG_REQUEST_COMPLETED = 102; 41192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 42192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private final ObexTransport mTransport; 43192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 44192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private final Handler mSessionHandler; 45192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 46192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private ClientThread mClientThread; 47192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 48192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private volatile boolean mInterrupted; 49192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 50192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private class ClientThread extends Thread { 51192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private final ObexTransport mTransport; 52192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 53192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private ClientSession mSession; 54192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 55192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private BluetoothMasRequest mRequest; 56192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 57192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private boolean mConnected; 58192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 59192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public ClientThread(ObexTransport transport) { 60192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta super("MAS ClientThread"); 61192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 62192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mTransport = transport; 63192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mConnected = false; 64192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 65192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 66192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta @Override 67192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public void run() { 68192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 69192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 70192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta connect(); 71192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 72192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mConnected) { 73192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget(); 74192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } else { 75192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget(); 76192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta return; 77192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 78192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 79192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta while (!mInterrupted) { 80192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta synchronized (this) { 81192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mRequest == null) { 82192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 83192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta this.wait(); 84192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (InterruptedException e) { 85192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mInterrupted = true; 86192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 87192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 88192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 89192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 90192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (!mInterrupted && mRequest != null) { 91192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 92192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mRequest.execute(mSession); 93192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (IOException e) { 94192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta // this will "disconnect" to cleanup 95192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mInterrupted = true; 96192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 97192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 98192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta BluetoothMasRequest oldReq = mRequest; 99192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mRequest = null; 100192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 101192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, oldReq).sendToTarget(); 102192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 103192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 104192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 105192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta disconnect(); 106192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 107192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget(); 108192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 109192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 110192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private void connect() { 111192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 112192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSession = new ClientSession(mTransport); 113192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 114192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta HeaderSet headerset = new HeaderSet(); 115192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta headerset.setHeader(HeaderSet.TARGET, MAS_TARGET); 116192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 117192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta headerset = mSession.connect(headerset); 118192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 119192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) { 120192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mConnected = true; 121192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } else { 122192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta disconnect(); 123192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 124192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (IOException e) { 125192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 126192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 127192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 128192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta private void disconnect() { 129192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 130192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSession.disconnect(null); 131192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (IOException e) { 132192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 133192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 134192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 135192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSession.close(); 136192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (IOException e) { 137192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 138192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 139192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mConnected = false; 140192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 141192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 142192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public synchronized boolean schedule(BluetoothMasRequest request) { 143192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mRequest != null) { 144192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta return false; 145192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 146192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 147192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mRequest = request; 148192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta notify(); 149192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 150192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta return true; 151192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 152192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 153192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 154192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) { 155192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mTransport = transport; 156192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mSessionHandler = handler; 157192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 158192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 159192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public void start() { 160192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mClientThread == null) { 161192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mClientThread = new ClientThread(mTransport); 162192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mClientThread.start(); 163192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 164192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 165192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 166192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 167192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public void stop() { 168192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mClientThread != null) { 169192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mClientThread.interrupt(); 170192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 171192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta (new Thread() { 172192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta @Override 173192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public void run() { 174192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta try { 175192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mClientThread.join(); 176192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta mClientThread = null; 177192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } catch (InterruptedException e) { 178192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta Log.w(TAG, "Interrupted while waiting for thread to join"); 179192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 180192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 181192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta }).run(); 182192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 183192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 184192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 185192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta public boolean makeRequest(BluetoothMasRequest request) { 186192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta if (mClientThread == null) { 187192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta return false; 188192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 189192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta 190192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta return mClientThread.schedule(request); 191192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta } 192192d793d2586b620027edd5b45ff4c72a86cc7beHemant Gupta} 193