1b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo/* 2b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Copyright (C) 2016 The Android Open Source Project 3b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 4b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Licensed under the Apache License, Version 2.0 (the "License"); 5b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * you may not use this file except in compliance with the License. 6b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * You may obtain a copy of the License at 7b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 8b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * http://www.apache.org/licenses/LICENSE-2.0 9b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 10b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Unless required by applicable law or agreed to in writing, software 11b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * distributed under the License is distributed on an "AS IS" BASIS, 12b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * See the License for the specific language governing permissions and 14b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * limitations under the License. 15b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo */ 16b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 17b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzopackage com.android.bluetooth.pbapclient; 18b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 19b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.bluetooth.BluetoothAdapter; 20b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.bluetooth.BluetoothDevice; 21b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.bluetooth.BluetoothSocket; 22b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.Handler; 23b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.Handler.Callback; 24b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.HandlerThread; 25b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.Message; 26b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.Process; 27b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.util.Log; 28b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 29b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.io.IOException; 30b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.util.UUID; 31b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 32b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoclass BluetoothPbapSession implements Callback { 33b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo //TODO consider cleaning file organization and naming. 34b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final String TAG = "com.android.bluetooth.pbapclient.BluetoothPbapSession"; 35b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 36b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* local use only */ 37b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final int RFCOMM_CONNECTED = 1; 38b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final int RFCOMM_FAILED = 2; 39b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 40b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* to BluetoothPbapClient */ 41b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int REQUEST_COMPLETED = 3; 42b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int REQUEST_FAILED = 4; 43b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int SESSION_CONNECTING = 5; 44b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int SESSION_CONNECTED = 6; 45b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int SESSION_DISCONNECTED = 7; 46b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int AUTH_REQUESTED = 8; 47b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int AUTH_TIMEOUT = 9; 48b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 49b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int ACTION_LISTING = 14; 50b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int ACTION_VCARD = 15; 51b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public static final int ACTION_PHONEBOOK_SIZE = 16; 52b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 53b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final String PBAP_UUID = 54b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo "0000112f-0000-1000-8000-00805f9b34fb"; 55b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 56b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private final BluetoothAdapter mAdapter; 57b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private final BluetoothDevice mDevice; 58b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 59b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private final Handler mParentHandler; 60b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 61b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private final HandlerThread mHandlerThread; 62b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private final Handler mSessionHandler; 63b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 64b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private RfcommConnectThread mConnectThread; 65b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private BluetoothPbapObexTransport mTransport; 66b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 67b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private BluetoothPbapObexSession mObexSession; 68b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 69b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private BluetoothPbapRequest mPendingRequest = null; 70b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 71b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public BluetoothPbapSession(BluetoothDevice device, Handler handler) { 72b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 73b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mAdapter = BluetoothAdapter.getDefaultAdapter(); 74b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mAdapter == null) { 75b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo throw new NullPointerException("No Bluetooth adapter in the system"); 76b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 77b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 78b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mDevice = device; 79b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler = handler; 80b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread = null; 81b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mTransport = null; 82b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession = null; 83b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 84b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mHandlerThread = new HandlerThread("PBAP session handler", 85b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Process.THREAD_PRIORITY_BACKGROUND); 86b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mHandlerThread.start(); 87b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler = new Handler(mHandlerThread.getLooper(), this); 88b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 89b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 90b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo @Override 91b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public boolean handleMessage(Message msg) { 92b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Handler: msg: " + msg.what); 93b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 94b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo switch (msg.what) { 95b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case RFCOMM_FAILED: 96b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread = null; 97b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 98b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget(); 99b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 100b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mPendingRequest != null) { 101b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget(); 102b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mPendingRequest = null; 103b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 104b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 105b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 106b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case RFCOMM_CONNECTED: 107b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread = null; 108b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mTransport = (BluetoothPbapObexTransport) msg.obj; 109b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo startObexSession(); 110b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 111b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 112b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_FAILED: 113b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo stopObexSession(); 114b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 115b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget(); 116b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 117b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mPendingRequest != null) { 118b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget(); 119b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mPendingRequest = null; 120b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 121b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 122b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 123b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_CONNECTED: 124b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(SESSION_CONNECTED).sendToTarget(); 125b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 126b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mPendingRequest != null) { 127b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession.schedule(mPendingRequest); 128b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mPendingRequest = null; 129b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 130b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 131b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 132b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_DISCONNECTED: 133b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(SESSION_DISCONNECTED).sendToTarget(); 134b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo stopRfcomm(); 135b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 136b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 137b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_REQUEST_COMPLETED: 138b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* send to parent, process there */ 139b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(REQUEST_COMPLETED, msg.obj).sendToTarget(); 140b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 141b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 142b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_REQUEST_FAILED: 143b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* send to parent, process there */ 144b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(REQUEST_FAILED, msg.obj).sendToTarget(); 145b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 146b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 147b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_REQUEST: 148b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* send to parent, process there */ 149b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(AUTH_REQUESTED).sendToTarget(); 150b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 151b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler 152b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo .sendMessageDelayed( 153b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler 154b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo .obtainMessage(BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT), 155b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 30000); 156b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 157b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 158b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo case BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT: 159b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* stop authentication */ 160b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo setAuthResponse(null); 161b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 162b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(AUTH_TIMEOUT).sendToTarget(); 163b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo break; 164b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 165b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo default: 166b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return false; 167b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 168b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 169b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return true; 170b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 171b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 172b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public void start() { 173b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "start"); 174b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 175b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo startRfcomm(); 176b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 177b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 178b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public void stop() { 179b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Stop"); 180b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 181b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo stopObexSession(); 182b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo stopRfcomm(); 183b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 184b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 185b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public void abort() { 186b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "abort"); 187b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 188b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* fail pending request immediately */ 189b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mPendingRequest != null) { 190b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(REQUEST_FAILED, mPendingRequest).sendToTarget(); 191b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mPendingRequest = null; 192b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 193b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 194b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mObexSession != null) { 195b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession.abort(); 196b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 197b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 198b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 199b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public boolean makeRequest(BluetoothPbapRequest request) { 200b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.v(TAG, "makeRequest: " + request.getClass().getSimpleName()); 201b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 202b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mPendingRequest != null) { 203b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.w(TAG, "makeRequest: request already queued, exiting"); 204b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return false; 205b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 206b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 207b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mObexSession == null) { 208b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mPendingRequest = request; 209b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 210b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* 211b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * since there is no pending request and no session it's safe to 212b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * assume that RFCOMM does not exist either and we should start 213b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * connecting it 214b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo */ 215b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo startRfcomm(); 216b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 217b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return true; 218b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 219b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 220b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return mObexSession.schedule(request); 221b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 222b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 223b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public boolean setAuthResponse(String key) { 224b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "setAuthResponse key=" + key); 225b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 226b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler 227b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo .removeMessages(BluetoothPbapObexSession.OBEX_SESSION_AUTHENTICATION_TIMEOUT); 228b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 229b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* does not make sense to set auth response when OBEX session is down */ 230b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mObexSession == null) { 231b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return false; 232b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 233b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 234b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return mObexSession.setAuthReply(key); 235b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 236b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 237b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private void startRfcomm() { 238b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "startRfcomm"); 239b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 240b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mConnectThread == null && mObexSession == null) { 241b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mParentHandler.obtainMessage(SESSION_CONNECTING).sendToTarget(); 242b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 243b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread = new RfcommConnectThread(); 244b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread.start(); 245b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 246b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 247b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo /* 248b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * don't care if mConnectThread is not null - it means RFCOMM is being 249b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * connected anyway 250b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo */ 251b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 252b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 253b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private void stopRfcomm() { 254b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "stopRfcomm"); 255b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 256b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mConnectThread != null) { 257b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 258b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo // Force close the socket in case the thread is stuck doing the connect() 259b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo // call. 260b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread.closeSocket(); 261b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo // TODO: Add timed join if closeSocket does not clean up the state. 262b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread.join(); 263b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (InterruptedException e) { 264b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 265b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 266b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mConnectThread = null; 267b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 268b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 269b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mTransport != null) { 270b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 271b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mTransport.close(); 272b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (IOException e) { 273b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 274b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 275b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mTransport = null; 276b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 277b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 278b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 279b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private void startObexSession() { 280b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "startObexSession"); 281b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 282b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession = new BluetoothPbapObexSession(mTransport); 283b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession.start(mSessionHandler); 284b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 285b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 286b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private void stopObexSession() { 287b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "stopObexSession"); 288b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 289b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mObexSession != null) { 290b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession.stop(); 291b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mObexSession = null; 292b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 293b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 294b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 295b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private class RfcommConnectThread extends Thread { 296b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final String TAG = "RfcommConnectThread"; 297b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 298b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private BluetoothSocket mSocket; 299b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 300b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public RfcommConnectThread() { 301b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo super("RfcommConnectThread"); 302b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 303b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 304b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo @Override 305b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public void run() { 306b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mAdapter.isDiscovering()) { 307b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mAdapter.cancelDiscovery(); 308b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 309b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 310b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 311b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString(PBAP_UUID)); 312b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSocket.connect(); 313b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 314b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo BluetoothPbapObexTransport transport; 315b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo transport = new BluetoothPbapObexTransport(mSocket); 316b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 317b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler.obtainMessage(RFCOMM_CONNECTED, transport).sendToTarget(); 318b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (IOException e) { 319b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo closeSocket(); 320b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSessionHandler.obtainMessage(RFCOMM_FAILED).sendToTarget(); 321b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 322b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 323b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 324b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 325b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo // This method may be called from outside the thread if the connect() call above is stuck. 326b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public void closeSocket() { 327b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 328b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (mSocket != null) { 329b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mSocket.close(); 330b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 331b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (IOException e) { 332b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.e(TAG, "Error when closing socket", e); 333b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 334b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 335b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 336b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo} 337