BluetoothConnectionFacade.java revision 42ef337b1976d1cbd7b71d531d8cc4365df29471
19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 29f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Copyright (C) 2016 Google Inc. 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 49f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Licensed under the Apache License, Version 2.0 (the "License"); you may not 59f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * use this file except in compliance with the License. You may obtain a copy of 69f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * the License at 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 89f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * http://www.apache.org/licenses/LICENSE-2.0 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * License for the specific language governing permissions and limitations under 149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * the License. 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage com.googlecode.android_scripting.facade.bluetooth; 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.ArrayList; 2075dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzoimport java.util.Arrays; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Collections; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.HashMap; 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.List; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Map; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.app.Service; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothA2dp; 287b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwalimport android.bluetooth.BluetoothA2dpSink; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothAdapter; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothDevice; 3155b68b3c0456f5e96edf37845785efb4d9a9848ctturneyimport android.bluetooth.BluetoothManager; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothHeadset; 337b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwalimport android.bluetooth.BluetoothHeadsetClient; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothInputDevice; 3575dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzoimport android.bluetooth.BluetoothMapClient; 3648e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwalimport android.bluetooth.BluetoothPbapClient; 3748e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwalimport android.bluetooth.BluetoothProfile; 38f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwalimport android.bluetooth.BluetoothPan; 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.bluetooth.BluetoothUuid; 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.BroadcastReceiver; 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Context; 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Intent; 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.IntentFilter; 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.Bundle; 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.ParcelUuid; 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.Log; 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.facade.EventFacade; 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.facade.FacadeManager; 5081c9640b1c3fa42892c2de6a18cc65aec8de2c4etturneyimport com.googlecode.android_scripting.facade.bluetooth.BluetoothPairingHelper; 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.jsonrpc.RpcReceiver; 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.rpc.Rpc; 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.rpc.RpcParameter; 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 55d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadiimport org.json.JSONArray; 56d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadiimport org.json.JSONException; 57d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class BluetoothConnectionFacade extends RpcReceiver { 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Service mService; 6155b68b3c0456f5e96edf37845785efb4d9a9848ctturney private final Context mContext; 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final BluetoothAdapter mBluetoothAdapter; 6355b68b3c0456f5e96edf37845785efb4d9a9848ctturney private final BluetoothManager mBluetoothManager; 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final BluetoothPairingHelper mPairingHelper; 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Map<String, BroadcastReceiver> listeningDevices; 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final EventFacade mEventFacade; 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mDiscoverConnectFilter; 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mPairingFilter; 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mBondFilter; 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mA2dpStateChangeFilter; 727b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal private final IntentFilter mA2dpSinkStateChangeFilter; 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mHidStateChangeFilter; 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final IntentFilter mHspStateChangeFilter; 757b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal private final IntentFilter mHfpClientStateChangeFilter; 7648e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal private final IntentFilter mPbapClientStateChangeFilter; 77f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal private final IntentFilter mPanStateChangeFilter; 7875dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo private final IntentFilter mMapClientStateChangeFilter; 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Bundle mGoodNews; 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Bundle mBadNews; 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private BluetoothA2dpFacade mA2dpProfile; 847b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal private BluetoothA2dpSinkFacade mA2dpSinkProfile; 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private BluetoothHidFacade mHidProfile; 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private BluetoothHspFacade mHspProfile; 877b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal private BluetoothHfpClientFacade mHfpClientProfile; 8848e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal private BluetoothPbapClientFacade mPbapClientProfile; 89f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal private BluetoothPanFacade mPanProfile; 9075dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo private BluetoothMapClientFacade mMapClientProfile; 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public BluetoothConnectionFacade(FacadeManager manager) { 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(manager); 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService = manager.getService(); 9555b68b3c0456f5e96edf37845785efb4d9a9848ctturney mContext = mService.getApplicationContext(); 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 9755b68b3c0456f5e96edf37845785efb4d9a9848ctturney mBluetoothManager = (BluetoothManager) mContext.getSystemService( 9855b68b3c0456f5e96edf37845785efb4d9a9848ctturney Service.BLUETOOTH_SERVICE); 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Use a synchronized map to avoid racing problems 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li listeningDevices = Collections.synchronizedMap(new HashMap<String, BroadcastReceiver>()); 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade = manager.getReceiver(EventFacade.class); 10381c9640b1c3fa42892c2de6a18cc65aec8de2c4etturney mPairingHelper = new BluetoothPairingHelper(mEventFacade); 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mA2dpProfile = manager.getReceiver(BluetoothA2dpFacade.class); 1057b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mA2dpSinkProfile = manager.getReceiver(BluetoothA2dpSinkFacade.class); 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mHidProfile = manager.getReceiver(BluetoothHidFacade.class); 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mHspProfile = manager.getReceiver(BluetoothHspFacade.class); 1087b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHfpClientProfile = manager.getReceiver(BluetoothHfpClientFacade.class); 10948e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal mPbapClientProfile = manager.getReceiver(BluetoothPbapClientFacade.class); 110f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal mPanProfile = manager.getReceiver(BluetoothPanFacade.class); 11175dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo mMapClientProfile = manager.getReceiver(BluetoothMapClientFacade.class); 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDiscoverConnectFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDiscoverConnectFilter.addAction(BluetoothDevice.ACTION_UUID); 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDiscoverConnectFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPairingFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST); 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPairingFilter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST); 11942ef337b1976d1cbd7b71d531d8cc4365df29471tturney mPairingFilter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPairingFilter.setPriority(999); 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBondFilter.addAction(BluetoothDevice.ACTION_FOUND); 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBondFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mA2dpStateChangeFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); 1277b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mA2dpSinkStateChangeFilter = 1287b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal new IntentFilter(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); 1297b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHidStateChangeFilter = 1307b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal new IntentFilter(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mHspStateChangeFilter = new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 1327b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHfpClientStateChangeFilter = 1337b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal new IntentFilter(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); 13448e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal mPbapClientStateChangeFilter = 13548e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal new IntentFilter(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); 136f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal mPanStateChangeFilter = 137f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal new IntentFilter(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); 13875dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo mMapClientStateChangeFilter = 13975dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo new IntentFilter(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mGoodNews = new Bundle(); 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mGoodNews.putBoolean("Status", true); 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBadNews = new Bundle(); 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBadNews.putBoolean("Status", false); 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void unregisterCachedListener(String listenerId) { 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BroadcastReceiver listener = listeningDevices.remove(listenerId); 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (listener != null) { 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(listener); 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Connect to a specific device upon its discovery 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public class DiscoverConnectReceiver extends BroadcastReceiver { 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final String mDeviceID; 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private BluetoothDevice mDevice; 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Constructor 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param deviceID Either the device alias name or mac address. 165d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param bond If true, bond the device only. 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public DiscoverConnectReceiver(String deviceID) { 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(); 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDeviceID = deviceID; 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onReceive(Context context, Intent intent) { 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String action = intent.getAction(); 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // The specified device is found. 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (action.equals(BluetoothDevice.ACTION_FOUND)) { 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceMatch(device, mDeviceID)) { 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Found device " + device.getAliasName() + " for connection."); 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBluetoothAdapter.cancelDiscovery(); 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDevice = device; 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 183d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi // After discovery stops. 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDevice == null) { 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Device " + mDeviceID + " not discovered."); 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("Bond" + mDeviceID, mBadNews); 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean status = mDevice.fetchUuidsWithSdp(); 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Initiated ACL connection: " + status); 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (action.equals(BluetoothDevice.ACTION_UUID)) { 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceMatch(device, mDeviceID)) { 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Initiating connections."); 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li connectProfile(device, mDeviceID); 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(listeningDevices.remove("Connect" + mDeviceID)); 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Connect to a specific device upon its discovery 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public class DiscoverBondReceiver extends BroadcastReceiver { 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final String mDeviceID; 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private BluetoothDevice mDevice = null; 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean started = false; 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Constructor 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param deviceID Either the device alias name or Mac address. 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public DiscoverBondReceiver(String deviceID) { 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(); 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDeviceID = deviceID; 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onReceive(Context context, Intent intent) { 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String action = intent.getAction(); 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // The specified device is found. 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (action.equals(BluetoothDevice.ACTION_FOUND)) { 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceMatch(device, mDeviceID)) { 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Found device " + device.getAliasName() + " for connection."); 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBluetoothAdapter.cancelDiscovery(); 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDevice = device; 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 232d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi // After discovery stops. 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDevice == null) { 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Device " + mDeviceID + " was not discovered."); 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("Bond", mBadNews); 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Attempt to initiate bonding. 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!started) { 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Bond with " + mDevice.getAliasName()); 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDevice.createBond()) { 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li started = true; 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Bonding started."); 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Failed to bond with " + mDevice.getAliasName()); 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("Bond", mBadNews); 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(listeningDevices.remove("Bond" + mDeviceID)); 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Bond state changing."); 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceMatch(device, mDeviceID)) { 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1); 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("New state is " + state); 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (state == BluetoothDevice.BOND_BONDED) { 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Bonding with " + mDeviceID + " successful."); 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("Bond" + mDeviceID, mGoodNews); 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(listeningDevices.remove("Bond" + mDeviceID)); 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public class ConnectStateChangeReceiver extends BroadcastReceiver { 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final String mDeviceID; 2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public ConnectStateChangeReceiver(String deviceID) { 2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDeviceID = deviceID; 2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onReceive(Context context, Intent intent) { 2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li String action = intent.getAction(); 2775ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal Log.d("Action received: " + action); 2785ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal 2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Check if received the specified device 2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!BluetoothFacade.deviceMatch(device, mDeviceID)) { 2825ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal Log.e("Action devices does match act: " + device + " exp " + mDeviceID); 2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 285d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi // Find the state. 286d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 287d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (state == -1) { 288d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Log.e("Action does not have a state."); 289d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi return; 290d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 291d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 292d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String connState = ""; 293d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (state == BluetoothProfile.STATE_CONNECTED) { 294d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi connState = "Connecting"; 295d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else if (state == BluetoothProfile.STATE_DISCONNECTED) { 296d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi connState = "Disconnecting"; 297d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 2985ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal 2995ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal int profile = -1; 3005ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal String listener = ""; 3015ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal switch (action) { 3025ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: 3035ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.A2DP; 304d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "A2dp" + connState + mDeviceID; 3055ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3065ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED: 3075ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.INPUT_DEVICE; 308d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "Hid" + connState + mDeviceID; 3095ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3105ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: 3115ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.HEADSET; 312d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "Hsp" + connState + mDeviceID; 3135ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3145ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED: 3155ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.PAN; 316d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "Pan" + connState + mDeviceID; 3175ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3185ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: 3195ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.HEADSET_CLIENT; 320d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "HfpClient" + connState + mDeviceID; 3215ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3225ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED: 3235ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.A2DP_SINK; 324d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "A2dpSink" + connState + mDeviceID; 3255ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 3265ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED: 3275ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal profile = BluetoothProfile.PBAP_CLIENT; 328d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listener = "PbapClient" + connState + mDeviceID; 3295ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal break; 33075dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED: 33175dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo profile = BluetoothProfile.MAP_CLIENT; 33275dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo listener = "MapClient" + connState + mDeviceID; 33375dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo break; 3345ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal } 3355ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal 3365ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal if (profile == -1) { 3375ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal Log.e("Action does not match any given profiles " + action); 3385ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal return; 3395ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal } 3405ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal 3415ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal 3425ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal // Post an event to Facade. 343d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if ((state == BluetoothProfile.STATE_CONNECTED) || (state 344d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi == BluetoothProfile.STATE_DISCONNECTED)) { 3455ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal Bundle news = new Bundle(); 3465ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal news.putInt("profile", profile); 3475ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal news.putInt("state", state); 3485ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal news.putString("addr", device.getAddress()); 3495ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal mEventFacade.postEvent("BluetoothProfileConnectionStateChanged", news); 3505ecdad6eafb5085b4527e56a4916d624cbeb84f0Sanket Agarwal unregisterCachedListener(listener); 3519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 355d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 356d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Converts a given JSONArray to an ArrayList of Integers 357d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 358d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param jsonArray the JSONArray to be converted 359d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @return <code>List<Integer></></code> the converted list of Integers 360d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 361d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi private List<Integer> jsonArrayToIntegerList(JSONArray jsonArray) throws JSONException { 362d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (jsonArray == null) { 363d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi return null; 364d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 365d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi List<Integer> intArray = new ArrayList<Integer>(); 366d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi for (int i = 0; i < jsonArray.length(); i++) { 367d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi intArray.add(jsonArray.getInt(i)); 368d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 369d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi return intArray; 370d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 371d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 372d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 373d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 374d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Helper function used by{@link connectProfile} & {@link disconnectProfiles} to handle a 375d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * successful return from a profile connect/disconnect call 376d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 377d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param deviceID The device id string 378d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param profile String representation of the profile - used to create keys in the 379d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * <code>listeningDevices</code> hashMap. 380d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param connState String that denotes if this is called after a connect or disconnect 381d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * call. Helps to share code between connect & disconnect 382d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param profileFilter The <code>IntentFilter</code> for this profile that we want to listen 383d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * on. 384d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 385d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi private void handleConnectionStateChanged(String deviceID, String profile, String connState, 386d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi IntentFilter profileFilter) { 387d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Log.d(connState + " " + profile); 388d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi ConnectStateChangeReceiver receiver = new ConnectStateChangeReceiver(deviceID); 389d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mService.registerReceiver(receiver, profileFilter); 390d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi listeningDevices.put(profile + connState + deviceID, receiver); 391d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 392d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 393d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 394d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Helper function used by{@link connectProfile} & {@link disconnectProfiles} to handle a 395d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * unsuccessful return from a profile connect/disconnect call 396d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 397d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param profile String representation of the profile - used to post an Event on the 398d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * <code>mEventFacade</code> 399d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param connState String that denotes if this is called after a connect or disconnect call. 400d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Helps to share code between connect & disconnect 401d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 402d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi private void handleConnectionStateChangeFailed(String profile, String connState) { 403d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Log.d("Failed Starting " + profile + " " + connState); 404d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Bundle badNews = (Bundle) mBadNews.clone(); 405d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi badNews.putString("Type", profile); 406d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mEventFacade.postEvent(connState, badNews); 407d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 408d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 409d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 410d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Connect on all the profiles to the given Bluetooth device 411d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 412d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param device The <code>BluetoothDevice</code> to connect to 413d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param deviceID Name (String) of the device to connect to 414d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 4159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void connectProfile(BluetoothDevice device, String deviceID) { 4169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.registerReceiver(mPairingHelper, mPairingFilter); 4179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ParcelUuid[] deviceUuids = device.getUuids(); 41875dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo Log.d("Device uuid is " + Arrays.toString(deviceUuids)); 4199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (deviceUuids == null) { 4207b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mEventFacade.postEvent("BluetoothProfileConnectionEvent", mBadNews); 4219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4227b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal Log.d("Connecting to " + device.getAliasName()); 4239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothUuid.containsAnyUuid(BluetoothA2dpFacade.SINK_UUIDS, deviceUuids)) { 4249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean status = mA2dpProfile.a2dpConnect(device); 4259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (status) { 426d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "A2dp", "Connecting", mA2dpStateChangeFilter); 4279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 428d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("a2dp", "Connect"); 4299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4317b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal if (BluetoothUuid.containsAnyUuid(BluetoothA2dpSinkFacade.SOURCE_UUIDS, deviceUuids)) { 4327b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal boolean status = mA2dpSinkProfile.a2dpSinkConnect(device); 4337b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal if (status) { 434d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "A2dpSink", "Connecting", 435d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mA2dpSinkStateChangeFilter); 4367b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } else { 437d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("a2dpsink", "Connect"); 4387b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 4397b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 4409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothUuid.containsAnyUuid(BluetoothHidFacade.UUIDS, deviceUuids)) { 4419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean status = mHidProfile.hidConnect(device); 4429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (status) { 443d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "Hid", "Connecting", mHidStateChangeFilter); 4449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 445d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("Hid", "Connect"); 4469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothUuid.containsAnyUuid(BluetoothHspFacade.UUIDS, deviceUuids)) { 4499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li boolean status = mHspProfile.hspConnect(device); 4509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (status) { 451d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "Hsp", "Connecting", mHspStateChangeFilter); 4529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 453d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("Hsp", "Connect"); 4549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4567b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal if (BluetoothUuid.containsAnyUuid(BluetoothHfpClientFacade.UUIDS, deviceUuids)) { 4577b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal boolean status = mHfpClientProfile.hfpClientConnect(device); 4587b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal if (status) { 459d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "HfpClient", "Connecting", 460d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mHfpClientStateChangeFilter); 4617b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } else { 462d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("HfpClient", "Connect"); 4637b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 4647b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 46502e949859dc20c9ab6d0a79688eff87beae68d61tturney if (BluetoothUuid.containsAnyUuid(BluetoothPanFacade.UUIDS, deviceUuids)) { 46602e949859dc20c9ab6d0a79688eff87beae68d61tturney boolean status = mPanProfile.panConnect(device); 46702e949859dc20c9ab6d0a79688eff87beae68d61tturney if (status) { 468d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "Pan", "Connecting", 4699a632371bf1ace747eb6fde291eb0f8a0c28c215Ram Periathiruvadi mPanStateChangeFilter); 47002e949859dc20c9ab6d0a79688eff87beae68d61tturney } else { 471d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("Pan", "Connect"); 472bb50bfa1e057c027dda0027a08372c91b529177eSanket Agarwal } 473bb50bfa1e057c027dda0027a08372c91b529177eSanket Agarwal } 47448e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal if (BluetoothUuid.containsAnyUuid(BluetoothPbapClientFacade.UUIDS, deviceUuids)) { 47548e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal boolean status = mPbapClientProfile.pbapClientConnect(device); 47648e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal if (status) { 477d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "PbapClient", "Connecting", 478d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mPbapClientStateChangeFilter); 47948e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal } else { 480d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("PbapClient", "Connect"); 48102e949859dc20c9ab6d0a79688eff87beae68d61tturney } 48202e949859dc20c9ab6d0a79688eff87beae68d61tturney } 48375dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo if (BluetoothUuid.containsAnyUuid(BluetoothMapClientFacade.MAP_UUIDS, deviceUuids)) { 48475dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo boolean status = mMapClientProfile.mapClientConnect(device); 48575dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo if (status) { 48675dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo handleConnectionStateChanged(deviceID, "MapClient", "Connecting", 48775dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo mMapClientStateChangeFilter); 48875dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo } else { 48975dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo handleConnectionStateChangeFailed("MapClient", "Connect"); 49075dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo } 49175dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo } 4929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(mPairingHelper); 4939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 4949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 495d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 496d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Disconnect on all available profiles from the given device 497d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 498d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param device The <code>BluetoothDevice</code> to disconnect from 499d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param deviceID Name (String) of the device to disconnect from 500d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 5017b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal private void disconnectProfiles(BluetoothDevice device, String deviceID) { 5027b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal Log.d("Disconnecting device " + device); 5037b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal // Blindly disconnect all profiles. We may not have some of them connected so that will be a 5047b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal // null op. 5057b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mA2dpProfile.a2dpDisconnect(device); 5067b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mA2dpSinkProfile.a2dpSinkDisconnect(device); 5077b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHidProfile.hidDisconnect(device); 5087b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHspProfile.hspDisconnect(device); 5097b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal mHfpClientProfile.hfpClientDisconnect(device); 51048e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal mPbapClientProfile.pbapClientDisconnect(device); 511f855841b2fe6ed4a5835bc7c7cb7e79bbccfec71Sanket Agarwal mPanProfile.panDisconnect(device); 51275dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo mMapClientProfile.mapClientDisconnect(device); 5137b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 5147b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal 515d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi /** 516d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * Disconnect from specific profiles provided in the given List of profiles. 517d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * 518d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param device The {@link BluetoothDevice} to disconnect from 519d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param deviceID Name/BDADDR (String) of the device to disconnect from 520d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi * @param profileIds The list of profiles we want to disconnect on. 521d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi */ 522d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi private void disconnectProfiles(BluetoothDevice device, String deviceID, 523d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi List<Integer> profileIds) { 524d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi boolean result; 525d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi for (int profileId : profileIds) { 526d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi switch (profileId) { 527d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.A2DP_SINK: 528d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mA2dpSinkProfile.a2dpSinkDisconnect(device); 529d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 530d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "A2dpSink", "Disconnecting", 531d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mA2dpSinkStateChangeFilter); 532d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 533d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("a2dpsink", "Disconnect"); 534d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 535d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 536d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.A2DP: 537d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mA2dpProfile.a2dpDisconnect(device); 538d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 539d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "A2dp", "Disconnecting", 540d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mA2dpStateChangeFilter); 541d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 542d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("a2dp", "Disconnect"); 543d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 544d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 545d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.INPUT_DEVICE: 546d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mHidProfile.hidDisconnect(device); 547d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 548d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "Hid", "Disconnecting", 549d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mHidStateChangeFilter); 550d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 551d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("Hid", "Disconnect"); 552d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 553d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 554d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.HEADSET: 555d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mHspProfile.hspDisconnect(device); 556d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 557d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "Hsp", "Disconnecting", 558d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mHspStateChangeFilter); 559d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 560d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("Hsp", "Disconnect"); 561d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 562d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 563d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.HEADSET_CLIENT: 564d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mHfpClientProfile.hfpClientDisconnect(device); 565d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 566d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "HfpClient", "Disconnecting", 567d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mHfpClientStateChangeFilter); 568d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 569d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("HfpClient", "Disconnect"); 570d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 571d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 572d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi case BluetoothProfile.PBAP_CLIENT: 573d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi result = mPbapClientProfile.pbapClientDisconnect(device); 574d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi if (result) { 575d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChanged(deviceID, "PbapClient", "Disconnecting", 576d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mPbapClientStateChangeFilter); 577d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } else { 578d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi handleConnectionStateChangeFailed("PbapClient", "Disconnect"); 579d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 580d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi break; 58175dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo case BluetoothProfile.MAP_CLIENT: 58275dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo result = mMapClientProfile.mapDisconnect(device); 58375dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo if (result) { 58475dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo handleConnectionStateChanged(deviceID, "MapClient", "Disconnecting", 58575dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo mMapClientStateChangeFilter); 58675dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo } else { 58775dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo handleConnectionStateChangeFailed("MapClient", "Disconnect"); 58875dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo } 58975dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo break; 590d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi default: 591d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Log.d("Unknown Profile Id to disconnect from. Quitting"); 592d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi return; // returns on the first unknown profile it encounters. 593d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 594d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 595d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 596d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 5979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Start intercepting all bluetooth connection pop-ups.") 5989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void bluetoothStartPairingHelper() { 5999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.registerReceiver(mPairingHelper, mPairingFilter); 6009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Return a list of devices connected through bluetooth") 6039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public List<BluetoothDevice> bluetoothGetConnectedDevices() { 6049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ArrayList<BluetoothDevice> results = new ArrayList<BluetoothDevice>(); 6059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (BluetoothDevice bd : mBluetoothAdapter.getBondedDevices()) { 6069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (bd.isConnected()) { 6079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li results.add(bd); 6089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return results; 6119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 61355b68b3c0456f5e96edf37845785efb4d9a9848ctturney @Rpc(description = "Return a list of devices connected through bluetooth LE") 61455b68b3c0456f5e96edf37845785efb4d9a9848ctturney public List<BluetoothDevice> bluetoothGetConnectedLeDevices(Integer profile) { 61555b68b3c0456f5e96edf37845785efb4d9a9848ctturney return mBluetoothManager.getConnectedDevices(profile); 61655b68b3c0456f5e96edf37845785efb4d9a9848ctturney } 61755b68b3c0456f5e96edf37845785efb4d9a9848ctturney 6189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Return true if a bluetooth device is connected.") 6199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Boolean bluetoothIsDeviceConnected(String deviceID) { 6209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (BluetoothDevice bd : mBluetoothAdapter.getBondedDevices()) { 6219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceMatch(bd, deviceID)) { 6229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return bd.isConnected(); 6239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return false; 6269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 62848e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal @Rpc(description = "Return list of connected bluetooth devices over a profile", 629d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi returns = "List of devices connected over the profile") 63048e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal public List<BluetoothDevice> bluetoothGetConnectedDevicesOnProfile( 63148e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal @RpcParameter(name = "profileId", 632d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "profileId same as BluetoothProfile") 633d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Integer profileId) { 63448e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal BluetoothProfile profile = null; 63548e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal switch (profileId) { 63648e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal case BluetoothProfile.A2DP_SINK: 63748e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal return mA2dpSinkProfile.bluetoothA2dpSinkGetConnectedDevices(); 63848e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal case BluetoothProfile.HEADSET_CLIENT: 63948e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal return mHfpClientProfile.bluetoothHfpClientGetConnectedDevices(); 64048e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal case BluetoothProfile.PBAP_CLIENT: 64148e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal return mPbapClientProfile.bluetoothPbapClientGetConnectedDevices(); 64275dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo case BluetoothProfile.MAP_CLIENT: 64375dc79a06c15dae01b07f09cfda374c828b45b4bJoseph Pirozzo return mMapClientProfile.bluetoothMapClientGetConnectedDevices(); 64448e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal default: 64548e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal Log.w("Profile id " + profileId + " is not yet supported."); 64648e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal return new ArrayList<BluetoothDevice>(); 64748e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal } 64848e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal } 64948e46479b58eff2b6cf67b459f68f918375b5567Sanket Agarwal 6509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Connect to a specified device once it's discovered.", 651d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi returns = "Whether discovery started successfully.") 6529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Boolean bluetoothDiscoverAndConnect( 6539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "deviceID", 654d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 655d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID) { 6569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBluetoothAdapter.cancelDiscovery(); 6579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (listeningDevices.containsKey(deviceID)) { 6589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("This device is already in the process of discovery and connecting."); 6599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 6609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li DiscoverConnectReceiver receiver = new DiscoverConnectReceiver(deviceID); 6629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li listeningDevices.put("Connect" + deviceID, receiver); 6639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.registerReceiver(receiver, mDiscoverConnectFilter); 6649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mBluetoothAdapter.startDiscovery(); 6659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Bond to a specified device once it's discovered.", 668d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi returns = "Whether discovery started successfully. ") 6699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Boolean bluetoothDiscoverAndBond( 6709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "deviceID", 671d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 672d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID) { 6739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mBluetoothAdapter.cancelDiscovery(); 6749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (listeningDevices.containsKey(deviceID)) { 6759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("This device is already in the process of discovery and bonding."); 6769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 6779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (BluetoothFacade.deviceExists(mBluetoothAdapter.getBondedDevices(), deviceID)) { 6799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Device " + deviceID + " is already bonded."); 6809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mEventFacade.postEvent("Bond" + deviceID, mGoodNews); 6819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return true; 6829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li DiscoverBondReceiver receiver = new DiscoverBondReceiver(deviceID); 6849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (listeningDevices.containsKey("Bond" + deviceID)) { 6859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.unregisterReceiver(listeningDevices.remove("Bond" + deviceID)); 6869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li listeningDevices.put("Bond" + deviceID, receiver); 6889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.registerReceiver(receiver, mBondFilter); 6899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.d("Start discovery for bonding."); 6909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mBluetoothAdapter.startDiscovery(); 6919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 6929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 6939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Unbond a device.", 694d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi returns = "Whether the device was successfully unbonded.") 6959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Boolean bluetoothUnbond( 6969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "deviceID", 697d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 698d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID) throws Exception { 6999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 7009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li deviceID); 7019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mDevice.removeBond(); 7029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Rpc(description = "Connect to a device that is already bonded.") 7059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void bluetoothConnectBonded( 7069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @RpcParameter(name = "deviceID", 707d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 708d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID) throws Exception { 7099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 7109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li deviceID); 7119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li connectProfile(mDevice, deviceID); 7129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 7147b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal @Rpc(description = "Disconnect from a device that is already connected.") 7157b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal public void bluetoothDisconnectConnected( 7167b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal @RpcParameter(name = "deviceID", 717d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 718d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID) throws Exception { 7197b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 7207b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal deviceID); 7217b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal disconnectProfiles(mDevice, deviceID); 7227b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal } 7237b8c49f4f5af2182a25f866a279270ccd72f080fSanket Agarwal 724d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi @Rpc(description = "Disconnect on a profile from a device that is already connected.") 725d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi public void bluetoothDisconnectConnectedProfile( 726d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi @RpcParameter(name = "deviceID", 727d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 728d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID, 729d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi @RpcParameter(name = "profileSet", 730d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "List of profiles to disconnect from.") 731d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi JSONArray profileSet 732d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi ) throws Exception { 733d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 734d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi deviceID); 735d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi disconnectProfiles(mDevice, deviceID, jsonArrayToIntegerList(profileSet)); 736d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 737d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi 73802cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo @Rpc(description = "Change permissions for a profile.") 73902cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo public void bluetoothChangeProfileAccessPermission( 74002cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo @RpcParameter(name = "deviceID", 741d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Name or MAC address of a bluetooth device.") 742d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi String deviceID, 74302cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo @RpcParameter(name = "profileID", 744d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Number of Profile to change access permission") 745d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Integer profileID, 74602cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo @RpcParameter(name = "access", 747d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi description = "Access level 0 = Unknown, 1 = Allowed, 2 = Rejected") 748d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Integer access 749d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi ) throws Exception { 75002cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo if (access < 0 || access > 2) { 75102cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo Log.w("Unsupported access level."); 75202cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo return; 75302cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo } 75402cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 75502cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo deviceID); 756d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi switch (profileID) { 75702cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo case BluetoothProfile.PBAP: 75802cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo mDevice.setPhonebookAccessPermission(access); 75902cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo break; 76002cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo default: 76102cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo Log.w("Unsupported profile access change."); 76202cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo } 76302cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo } 76402cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo 76502cd37e8066812cd73abe71f060e39cfac74f9a7Joseph Pirozzo 7669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 7679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void shutdown() { 768d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi for (BroadcastReceiver receiver : listeningDevices.values()) { 769d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi try { 770d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi mService.unregisterReceiver(receiver); 771d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } catch (IllegalArgumentException ex) { 772d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi Log.e("Failed to unregister " + ex); 773d9a81edc88a6ffdecebaa306279557bc18b71c7dRam Periathiruvadi } 7749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li listeningDevices.clear(); 77602e949859dc20c9ab6d0a79688eff87beae68d61tturney mService.unregisterReceiver(mPairingHelper); 7779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 7789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 779