1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/* 2326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde* Copyright (C) 2014 Samsung System LSI 3fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Licensed under the Apache License, Version 2.0 (the "License"); 4fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* you may not use this file except in compliance with the License. 5fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* You may obtain a copy of the License at 6fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 7fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* http://www.apache.org/licenses/LICENSE-2.0 8fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 9fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Unless required by applicable law or agreed to in writing, software 10fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* distributed under the License is distributed on an "AS IS" BASIS, 11fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* See the License for the specific language governing permissions and 13fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* limitations under the License. 14fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*/ 15fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepackage com.android.bluetooth.map; 16fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 17fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothDevice; 18fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.bluetooth.BluetoothSocket; 19bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpMnsRecord; 20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Handler; 2170bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xuimport android.os.HandlerThread; 22fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Looper; 23fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.Message; 24fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.os.ParcelUuid; 25fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log; 26326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport android.util.SparseBooleanArray; 27fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 28bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.BluetoothObexTransport; 29bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde 30fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.IOException; 31fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.OutputStream; 32fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 33fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport javax.obex.ClientOperation; 34fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport javax.obex.ClientSession; 35fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport javax.obex.HeaderSet; 36fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport javax.obex.ObexTransport; 37fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport javax.obex.ResponseCodes; 38fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 39fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/** 40fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * The Message Notification Service class runs its own message handler thread, 41fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * to avoid executing long operations on the MAP service Thread. 42fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * This handler context is passed to the content observers, 43fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * hence all call-backs (and thereby transmission of data) is executed 44fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * from this thread. 45fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 4670bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xupublic class BluetoothMnsObexClient { 47fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 48fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String TAG = "BluetoothMnsObexClient"; 49326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private static final boolean D = BluetoothMapService.DEBUG; 50326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private static final boolean V = BluetoothMapService.VERBOSE; 51fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 52fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private ObexTransport mTransport; 5370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu public Handler mHandler = null; 54fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private volatile boolean mWaitingForRemote; 55fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private static final String TYPE_EVENT = "x-bt/MAP-event-report"; 56fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private ClientSession mClientSession; 57fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private boolean mConnected = false; 58fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothDevice mRemoteDevice; 59326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private SparseBooleanArray mRegisteredMasIds = new SparseBooleanArray(1); 60326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 61326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private HeaderSet mHsConnect = null; 62c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu private Handler mCallback = null; 63e6564029f132077c8a4877431a95899db201e506Ashwini Munigala private SdpMnsRecord mMnsRecord; 64fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // Used by the MAS to forward notification registrations 65fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public static final int MSG_MNS_NOTIFICATION_REGISTRATION = 1; 66326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public static final int MSG_MNS_SEND_EVENT = 2; 67e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public static final int MSG_MNS_SDP_SEARCH_REGISTRATION = 3; 6870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz 69e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Copy SdpManager.SDP_INTENT_DELAY - The timeout to wait for reply from native. 70e6564029f132077c8a4877431a95899db201e506Ashwini Munigala private final int MNS_SDP_SEARCH_DELAY = 6000; 71e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public MnsSdpSearchInfo mMnsLstRegRqst = null; 72e6564029f132077c8a4877431a95899db201e506Ashwini Munigala private static final int MNS_NOTIFICATION_DELAY = 10; 73326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public static final ParcelUuid BLUETOOTH_UUID_OBEX_MNS = 74fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); 75fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 76fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 77bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde public BluetoothMnsObexClient(BluetoothDevice remoteDevice, 78bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde SdpMnsRecord mnsRecord, Handler callback) { 79fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (remoteDevice == null) { 80fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie throw new NullPointerException("Obex transport is null"); 81fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 82326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mRemoteDevice = remoteDevice; 8370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothMnsObexClient"); 8470bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu thread.start(); 85326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /* This will block until the looper have started, hence it will be safe to use it, 86326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde when the constructor completes */ 8770bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu Looper looper = thread.getLooper(); 8870bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu mHandler = new MnsObexClientHandler(looper); 89c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu mCallback = callback; 90bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde mMnsRecord = mnsRecord; 91fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 92fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 9370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu public Handler getMessageHandler() { 94fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return mHandler; 95fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 96fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 97e6564029f132077c8a4877431a95899db201e506Ashwini Munigala class MnsSdpSearchInfo { 98e6564029f132077c8a4877431a95899db201e506Ashwini Munigala private boolean isSearchInProgress; 99e6564029f132077c8a4877431a95899db201e506Ashwini Munigala int lastMasId; 100e6564029f132077c8a4877431a95899db201e506Ashwini Munigala int lastNotificationStatus; 101e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 102e6564029f132077c8a4877431a95899db201e506Ashwini Munigala MnsSdpSearchInfo (boolean isSearchON, int masId, int notification) { 103e6564029f132077c8a4877431a95899db201e506Ashwini Munigala isSearchInProgress = isSearchON; 104e6564029f132077c8a4877431a95899db201e506Ashwini Munigala lastMasId = masId; 105e6564029f132077c8a4877431a95899db201e506Ashwini Munigala lastNotificationStatus = notification; 106e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 107e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 108e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public boolean isSearchInProgress() { 109e6564029f132077c8a4877431a95899db201e506Ashwini Munigala return isSearchInProgress; 110e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 111e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 112e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public void setIsSearchInProgress(boolean isSearchON) { 113e6564029f132077c8a4877431a95899db201e506Ashwini Munigala isSearchInProgress = isSearchON; 114e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 115e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 116e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 11770bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu private final class MnsObexClientHandler extends Handler { 11870bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu private MnsObexClientHandler(Looper looper) { 11970bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu super(looper); 12070bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu } 121fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 12270bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu @Override 12370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu public void handleMessage(Message msg) { 12470bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu switch (msg.what) { 12570bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu case MSG_MNS_NOTIFICATION_REGISTRATION: 126e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "Reg masId: " + msg.arg1 + " notfStatus: " + msg.arg2); 127e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (isValidMnsRecord()) { 128e6564029f132077c8a4877431a95899db201e506Ashwini Munigala handleRegistration(msg.arg1 /*masId*/, msg.arg2 /*status*/); 129e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } else { 130e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Should not happen 131e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (D) Log.d(TAG, "MNS SDP info not available yet - Cannot Connect."); 132e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 13370bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu break; 134326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde case MSG_MNS_SEND_EVENT: 135326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde sendEventHandler((byte[])msg.obj/*byte[]*/, msg.arg1 /*masId*/); 136326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde break; 137e6564029f132077c8a4877431a95899db201e506Ashwini Munigala case MSG_MNS_SDP_SEARCH_REGISTRATION: 138e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Initiate SDP Search 139e6564029f132077c8a4877431a95899db201e506Ashwini Munigala notifyMnsSdpSearch(); 140e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Save the mns search info 141e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsLstRegRqst = new MnsSdpSearchInfo(true, msg.arg1, msg.arg2); 142e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Handle notification registration. 143e6564029f132077c8a4877431a95899db201e506Ashwini Munigala Message msgReg = 144e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mHandler.obtainMessage(MSG_MNS_NOTIFICATION_REGISTRATION, 145e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.arg1, msg.arg2); 146e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "SearchReg masId: " + msg.arg1 + " notfStatus: " + msg.arg2); 147e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mHandler.sendMessageDelayed(msgReg, MNS_SDP_SEARCH_DELAY); 148e6564029f132077c8a4877431a95899db201e506Ashwini Munigala break; 14970bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu default: 15070bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu break; 151fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 15270bfe3280ce158c39dbb25fe18386f0d10b490d3Zhihai Xu } 153fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 154fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 155fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public boolean isConnected() { 156fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return mConnected; 157fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 158fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 159824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu /** 160824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu * Disconnect the connection to MNS server. 161824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu * Call this when the MAS client requests a de-registration on events. 162824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu */ 1630e7e149687b0b5e340991b20c9d8e5232e8d3e39Hemant Gupta public synchronized void disconnect() { 164fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 165fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (mClientSession != null) { 166fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mClientSession.disconnect(null); 167fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "OBEX session disconnected"); 168fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 169fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 170fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.w(TAG, "OBEX session disconnect error " + e.getMessage()); 171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 172fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (mClientSession != null) { 174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "OBEX session close mClientSession"); 175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mClientSession.close(); 17670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz mClientSession = null; 177fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "OBEX session closed"); 178fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.w(TAG, "OBEX session close error:" + e.getMessage()); 181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 182fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (mTransport != null) { 183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "Close Obex Transport"); 185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mTransport.close(); 18670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz mTransport = null; 18770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz mConnected = false; 188fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "Obex Transport Closed"); 189fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 190fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "mTransport.close error: " + e.getMessage()); 191fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 192fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 193824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu } 194824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu 195824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu /** 196824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu * Shutdown the MNS. 197824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu */ 198189cc4ca1c36018977e7b9ad62b07ddbefc7f2baHemant Gupta public synchronized void shutdown() { 199824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu /* should shutdown handler thread first to make sure 200326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * handleRegistration won't be called when disconnect 201824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu */ 202824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu if (mHandler != null) { 203824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu // Shut down the thread 204824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu mHandler.removeCallbacksAndMessages(null); 205824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu Looper looper = mHandler.getLooper(); 206824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu if (looper != null) { 207824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu looper.quit(); 208824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu } 209824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu mHandler = null; 210824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu } 211824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu 212824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu /* Disconnect if connected */ 213824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu disconnect(); 214824929471ee80476e6d6774eedac9f30c5623eb2Zhihai Xu 215326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mRegisteredMasIds.clear(); 216fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 217fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 218326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /** 219326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * We store a list of registered MasIds only to control connect/disconnect 220326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param masId 221326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param notificationStatus 222326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde */ 223189cc4ca1c36018977e7b9ad62b07ddbefc7f2baHemant Gupta public synchronized void handleRegistration(int masId, int notificationStatus){ 224326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.d(TAG, "handleRegistration( " + masId + ", " + notificationStatus + ")"); 225e6564029f132077c8a4877431a95899db201e506Ashwini Munigala boolean sendObserverRegistration = true; 226e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (notificationStatus == BluetoothMapAppParams.NOTIFICATION_STATUS_NO) { 227326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mRegisteredMasIds.delete(masId); 228e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mMnsLstRegRqst != null && mMnsLstRegRqst.lastMasId == masId) { 229e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Clear last saved MNSSdpSearchInfo , if Disconnect requested for same MasId. 230e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsLstRegRqst = null; 231e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 232e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } else if (notificationStatus == BluetoothMapAppParams.NOTIFICATION_STATUS_YES) { 233fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /* Connect if we do not have a connection, and start the content observers providing 234fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * this thread as Handler. 235fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 236e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (isConnected() == false) { 237326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.d(TAG, "handleRegistration: connect"); 238326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde connect(); 239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 240e6564029f132077c8a4877431a95899db201e506Ashwini Munigala sendObserverRegistration = isConnected(); 241326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mRegisteredMasIds.put(masId, true); // We don't use the value for anything 242e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 243e6564029f132077c8a4877431a95899db201e506Ashwini Munigala // Clear last saved MNSSdpSearchInfo after connect is processed. 244e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsLstRegRqst = null; 245326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 246e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 247e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mRegisteredMasIds.size() == 0) { 248326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde // No more registrations - disconnect 249326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.d(TAG, "handleRegistration: disconnect"); 250326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde disconnect(); 251fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 252e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 253e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Register ContentObserver After connect/disconnect MNS channel. 254e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "Send registerObserver: " + sendObserverRegistration); 255e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mCallback != null && sendObserverRegistration) { 256e6564029f132077c8a4877431a95899db201e506Ashwini Munigala Message msg = Message.obtain(mCallback); 257e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.what = BluetoothMapService.MSG_OBSERVER_REGISTRATION; 258e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.arg1 = masId; 259e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.arg2 = notificationStatus; 260e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.sendToTarget(); 261e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 262e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 263e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 264e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public boolean isValidMnsRecord() { 265e6564029f132077c8a4877431a95899db201e506Ashwini Munigala return (mMnsRecord != null); 266e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 267e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 268e6564029f132077c8a4877431a95899db201e506Ashwini Munigala public void setMnsRecord(SdpMnsRecord mnsRecord) { 269e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "setMNSRecord"); 270e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (isValidMnsRecord()) { 271e6564029f132077c8a4877431a95899db201e506Ashwini Munigala Log.w(TAG,"MNS Record already available. Still update."); 272e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 273e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsRecord = mnsRecord; 274e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mMnsLstRegRqst != null) { 275e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //SDP Search completed. 276e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsLstRegRqst.setIsSearchInProgress(false); 277e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mHandler.hasMessages(MSG_MNS_NOTIFICATION_REGISTRATION)) { 278e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mHandler.removeMessages(MSG_MNS_NOTIFICATION_REGISTRATION); 279e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Search Result obtained within MNS_SDP_SEARCH_DELAY timeout 280e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (!isValidMnsRecord()) { 281e6564029f132077c8a4877431a95899db201e506Ashwini Munigala // SDP info still not available for last trial. 282e6564029f132077c8a4877431a95899db201e506Ashwini Munigala // Clear saved info. 283e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mMnsLstRegRqst = null; 284e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } else { 285e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "Handle registration for last saved request"); 286e6564029f132077c8a4877431a95899db201e506Ashwini Munigala Message msgReg = 287e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mHandler.obtainMessage(MSG_MNS_NOTIFICATION_REGISTRATION); 288e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msgReg.arg1 = mMnsLstRegRqst.lastMasId; 289e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msgReg.arg2 = mMnsLstRegRqst.lastNotificationStatus; 290e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "SearchReg masId: " + msgReg.arg1 291e6564029f132077c8a4877431a95899db201e506Ashwini Munigala + " notfStatus: " + msgReg.arg2); 292e6564029f132077c8a4877431a95899db201e506Ashwini Munigala //Handle notification registration. 293e6564029f132077c8a4877431a95899db201e506Ashwini Munigala mHandler.sendMessageDelayed(msgReg, MNS_NOTIFICATION_DELAY); 294e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 295e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 296e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } else { 297e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (V) Log.v(TAG, "No last saved MNSSDPInfo to handle"); 298e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 299fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 300fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 301fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public void connect() { 302326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 303326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mConnected = true; 304fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 305fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothSocket btSocket = null; 306fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 307bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde // TODO: Do SDP record search again? 308e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (isValidMnsRecord() && mMnsRecord.getL2capPsm() > 0) { 309bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde // Do L2CAP connect 310bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde btSocket = mRemoteDevice.createL2capSocket(mMnsRecord.getL2capPsm()); 311bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde 312e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } else if (isValidMnsRecord() && mMnsRecord.getRfcommChannelNumber() > 0) { 313bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde // Do Rfcomm connect 314bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde btSocket = mRemoteDevice.createRfcommSocket(mMnsRecord.getRfcommChannelNumber()); 315bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde } else { 316bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde // This should not happen... 317bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde Log.e(TAG, "Invalid SDP content - attempt a connect to UUID..."); 318bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde // TODO: Why insecure? - is it because the link is already encrypted? 319bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde btSocket = mRemoteDevice.createInsecureRfcommSocketToServiceRecord( 320bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde BLUETOOTH_UUID_OBEX_MNS.getUuid()); 321bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde } 322fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie btSocket.connect(); 323fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 324fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "BtSocket Connect error " + e.getMessage(), e); 325fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // TODO: do we need to report error somewhere? 326326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mConnected = false; 327fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return; 328fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 329fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 330bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde mTransport = new BluetoothObexTransport(btSocket); 331fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 332fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 333fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mClientSession = new ClientSession(mTransport); 334fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e1) { 335fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "OBEX session create error " + e1.getMessage()); 336326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mConnected = false; 337fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 338fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (mConnected && mClientSession != null) { 339326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde boolean connected = false; 340fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HeaderSet hs = new HeaderSet(); 341fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // bb582b41-420c-11db-b0de-0800200c9a66 342fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie byte[] mnsTarget = { (byte) 0xbb, (byte) 0x58, (byte) 0x2b, (byte) 0x41, 343fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie (byte) 0x42, (byte) 0x0c, (byte) 0x11, (byte) 0xdb, 344fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie (byte) 0xb0, (byte) 0xde, (byte) 0x08, (byte) 0x00, 345fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie (byte) 0x20, (byte) 0x0c, (byte) 0x9a, (byte) 0x66 }; 346fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie hs.setHeader(HeaderSet.TARGET, mnsTarget); 347fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 348fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie synchronized (this) { 349fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mWaitingForRemote = true; 350fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 351fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 352326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mHsConnect = mClientSession.connect(hs); 353fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (D) Log.d(TAG, "OBEX session created"); 354326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde connected = true; 355fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 356fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "OBEX session connect error " + e.getMessage()); 357fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 358326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mConnected = connected; 359fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 3605a60e47497f21f64e6d79420dc4c56c1907df22akschulz synchronized (this) { 361fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mWaitingForRemote = false; 362fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 363fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 364fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 365326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /** 366326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Call this method to queue an event report to be send to the MNS server. 367326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param eventBytes the encoded event data. 368326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param masInstanceId the MasId of the instance sending the event. 369326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde */ 370326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public void sendEvent(byte[] eventBytes, int masInstanceId) { 371326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde // We need to check for null, to handle shutdown. 372326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(mHandler != null) { 373326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde Message msg = mHandler.obtainMessage(MSG_MNS_SEND_EVENT, masInstanceId, 0, eventBytes); 374326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(msg != null) { 375326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde msg.sendToTarget(); 376326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 377326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 378326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde notifyUpdateWakeLock(); 379326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 380326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 381e6564029f132077c8a4877431a95899db201e506Ashwini Munigala private void notifyMnsSdpSearch() { 382e6564029f132077c8a4877431a95899db201e506Ashwini Munigala if (mCallback != null) { 383e6564029f132077c8a4877431a95899db201e506Ashwini Munigala Message msg = Message.obtain(mCallback); 384e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.what = BluetoothMapService.MSG_MNS_SDP_SEARCH; 385e6564029f132077c8a4877431a95899db201e506Ashwini Munigala msg.sendToTarget(); 386e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 387e6564029f132077c8a4877431a95899db201e506Ashwini Munigala } 388e6564029f132077c8a4877431a95899db201e506Ashwini Munigala 389326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private int sendEventHandler(byte[] eventBytes, int masInstanceId) { 390fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 391fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie boolean error = false; 392fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int responseCode = -1; 393fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie HeaderSet request; 394fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int maxChunkSize, bytesToWrite, bytesWritten = 0; 3959679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu ClientSession clientSession = mClientSession; 3969679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu 3979679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu if ((!mConnected) || (clientSession == null)) { 3989679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu Log.w(TAG, "sendEvent after disconnect:" + mConnected); 3999679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu return responseCode; 4009679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } 4019679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu 402fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie request = new HeaderSet(); 403fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothMapAppParams appParams = new BluetoothMapAppParams(); 404fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie appParams.setMasInstanceId(masInstanceId); 405fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 406fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie ClientOperation putOperation = null; 407fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie OutputStream outputStream = null; 408fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 409fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 410fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie request.setHeader(HeaderSet.TYPE, TYPE_EVENT); 411fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie request.setHeader(HeaderSet.APPLICATION_PARAMETER, appParams.EncodeParams()); 412fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 413326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if (mHsConnect.mConnectionID != null) { 4149679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu request.mConnectionID = new byte[4]; 415326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde System.arraycopy(mHsConnect.mConnectionID, 0, request.mConnectionID, 0, 4); 4169679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } else { 4179679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu Log.w(TAG, "sendEvent: no connection ID"); 4189679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } 419fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 420fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie synchronized (this) { 421fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mWaitingForRemote = true; 422fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 423fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // Send the header first and then the body 424fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 425fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.v(TAG, "Send headerset Event "); 4269679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu putOperation = (ClientOperation)clientSession.put(request); 427fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie // TODO - Should this be kept or Removed 428fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 429fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 430fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "Error when put HeaderSet " + e.getMessage()); 431fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie error = true; 432fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 433fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie synchronized (this) { 434fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie mWaitingForRemote = false; 435fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 436fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (!error) { 437fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 438fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.v(TAG, "Send headerset Event "); 439fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie outputStream = putOperation.openOutputStream(); 440fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 441fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "Error when opening OutputStream " + e.getMessage()); 442fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie error = true; 443fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 444fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 445fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 446fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (!error) { 447fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 448fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie maxChunkSize = putOperation.getMaxPacketSize(); 449fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 450fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie while (bytesWritten < eventBytes.length) { 451fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie bytesToWrite = Math.min(maxChunkSize, eventBytes.length - bytesWritten); 452fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie outputStream.write(eventBytes, bytesWritten, bytesToWrite); 453fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie bytesWritten += bytesToWrite; 454fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 455fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 456fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (bytesWritten == eventBytes.length) { 457fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.i(TAG, "SendEvent finished send length" + eventBytes.length); 458fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } else { 459fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie error = true; 460fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie putOperation.abort(); 461fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.i(TAG, "SendEvent interrupted"); 462fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 463fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 464fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 465fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handleSendException(e.toString()); 466fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie error = true; 467fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IndexOutOfBoundsException e) { 468fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie handleSendException(e.toString()); 469fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie error = true; 470fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } finally { 471fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 4729679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu if (outputStream != null) { 4739679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu outputStream.close(); 4749679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } 4759679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } catch (IOException e) { 4769679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu Log.e(TAG, "Error when closing stream after send " + e.getMessage()); 4779679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu } 4789679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu try { 4799679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu if ((!error) && (putOperation != null)) { 480fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie responseCode = putOperation.getResponseCode(); 481fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (responseCode != -1) { 482fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (V) Log.v(TAG, "Put response code " + responseCode); 483fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (responseCode != ResponseCodes.OBEX_HTTP_OK) { 484fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.i(TAG, "Response error code is " + responseCode); 485fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 486fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 487fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 488fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie if (putOperation != null) { 4899679a425747e95082e169b3bd3673ed6b5a27590Zhihai Xu putOperation.close(); 490fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 491fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 492fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "Error when closing stream after send " + e.getMessage()); 493fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 494fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 495fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 496fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return responseCode; 497fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 498fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 499fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie private void handleSendException(String exception) { 500fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie Log.e(TAG, "Error when sending event: " + exception); 501fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 502c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu 503c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu private void notifyUpdateWakeLock() { 504326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(mCallback != null) { 505326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde Message msg = Message.obtain(mCallback); 506326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde msg.what = BluetoothMapService.MSG_ACQUIRE_WAKE_LOCK; 507326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde msg.sendToTarget(); 508326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 509c09b531ba47eee740485b0c6022981fc38ef1587Zhihai Xu } 510fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie} 511