BluetoothService.java revision 738ed80262aa26128924c51f59ffd49e1163eb8d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Move this to 19bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * java/services/com/android/server/BluetoothService.java 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and make the contructor package private again. 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 28dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 3124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.bluetooth.BluetoothSocket; 3210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid; 33bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 3416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport android.bluetooth.IBluetoothCallback; 35aef439e6f825c0cb99a2ac08c8207f48b7a9fe10Nick Pellyimport android.os.ParcelUuid; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 4224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pellyimport android.os.IBinder; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 46105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemService; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 51d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganeshimport com.android.internal.app.IBatteryStats; 52d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 5916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pellyimport java.util.Iterator; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 62bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub { 63bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private static final String TAG = "BluetoothService"; 64db7ae10d6b8e86ff5311512de45afa65a1b0a738Nick Pelly private static final boolean DBG = false; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeData; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BluetoothEventLoop mEventLoop; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IntentFilter mIntentFilter; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsAirplaneSensitive; 70105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private int mBluetoothState; 71997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private boolean mRestart = false; // need to call enable() after disable() 72bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private boolean mIsDiscovering; 73997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 74bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private BluetoothAdapter mAdapter; // constant after init() 75997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly private final BondState mBondState = new BondState(); // local cache of bondings 76105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private final IBatteryStats mBatteryStats; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; 83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final int MESSAGE_FINISH_DISABLE = 2; 841caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int MESSAGE_UUID_INTENT = 3; 8512835478ee687a493d1b5882e67b6725bd539c26Nick Pelly private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; 861caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 871caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // The timeout used to sent the UUIDs Intent 881caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // This timeout should be greater than the page timeout 891caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private static final int UUID_INTENT_DELAY = 6000; 90105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 9116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** Always retrieve RFCOMM channel for these SDP UUIDs */ 9216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static final ParcelUuid[] RFCOMM_UUIDS = { 9316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.Handsfree, 9416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.HSP, 9516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly BluetoothUuid.ObexObjectPush }; 9616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 9716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 98bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly private final Map<String, String> mAdapterProperties; 9916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<String, String>> mDeviceProperties; 100d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 10116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache; 10216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final ArrayList<String> mUuidIntentTracker; 10316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker; 1041caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 10524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private final HashMap<Integer, Integer> mServiceRecordToPid; 10624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 10716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly private static class RemoteService { 10816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public String address; 10916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public ParcelUuid uuid; 11016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public RemoteService(String address, ParcelUuid uuid) { 11116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.address = address; 11216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly this.uuid = uuid; 11316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 11416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly @Override 11516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public boolean equals(Object o) { 11616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (o instanceof RemoteService) { 11716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = (RemoteService)o; 11816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return address.equals(service.address) && uuid.equals(service.uuid); 11916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 12116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 12316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project classInitNative(); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 128bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothService(Context context) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 130105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 131105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Need to do this in place of: 132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // mBatteryStats = BatteryStatsService.getService(); 133105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Since we can not import BatteryStatsService from here. This class really needs to be 134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // moved to java/services/com/android/server/ 135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initializeNativeDataNative(); 138ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 139ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isEnabledNative() == 1) { 140ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.w(TAG, "Bluetooth daemons already running - runtime restart? "); 141ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project disableNative(); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 143ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 144de893f550301a60274e87aa8168225e7a7a42184Nick Pelly mBluetoothState = BluetoothAdapter.STATE_OFF; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 146bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties = new HashMap<String, String>(); 147bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties = new HashMap<String, Map<String,String>>(); 14810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 14910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>(); 1501caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker = new ArrayList<String>(); 15116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>(); 15224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid = new HashMap<Integer, Integer>(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project registerForAirplaneMode(); 154bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly } 155bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 156bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public synchronized void initAfterRegistration() { 157f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 158bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.unregisterReceiver(mReceiver); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupNativeDataNative(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled() { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 175de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return mBluetoothState == BluetoothAdapter.STATE_ON; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 178105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public int getBluetoothState() { 179105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 180105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mBluetoothState; 181105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth and disable BT in settings. Returns true on success. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean disable() { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return disable(true); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bring down bluetooth. Returns true on success. 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 194e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly * @param saveSetting If true, persist the new setting 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean disable(boolean saveSetting) { 197e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch (mBluetoothState) { 200de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 201105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 202de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 203105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 204105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project default: 205105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 206105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 210de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); 211bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.removeMessages(MESSAGE_REGISTER_SDP_RECORDS); 212105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 213105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Allow 3 seconds for profiles to gracefully disconnect 214105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // TODO: Introduce a callback mechanism so that each profile can notify 215bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly // BluetoothService when it is done shutting down 216105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.sendMessageDelayed( 217105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); 218105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return true; 219105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 220105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 221105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 222105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void finishDisable(boolean saveSetting) { 223de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { 224105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEventLoop.stop(); 227d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh tearDownNativeDataNative(); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disableNative(); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mark in progress bondings as cancelled 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) { 232005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // update mode 237de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 238de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 241105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mIsDiscovering = false; 242bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 24324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.clear(); 244105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (saveSetting) { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(false); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 248105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 249de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_OFF); 250105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 251105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth off to battery stats. 252105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 253105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 254105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOff(); 255105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 256105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 257105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 258105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 259997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 260997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (mRestart) { 261997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 262997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly enable(); 263997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 266105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** Bring up BT and persist BT on in settings */ 267105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean enable() { 268105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return enable(true); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enable this Bluetooth device, asynchronously. 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This turns on/off the underlying hardware. 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 275105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @param saveSetting If true, persist the new state of BT in settings 276105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return True on success (so far) 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 278105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public synchronized boolean enable(boolean saveSetting) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Airplane mode can prevent Bluetooth radio from being turned on. 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive && isAirplaneModeOn()) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 286de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_OFF) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnableThread != null && mEnableThread.isAlive()) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 292de893f550301a60274e87aa8168225e7a7a42184Nick Pelly setBluetoothState(BluetoothAdapter.STATE_TURNING_ON); 293105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = new EnableThread(saveSetting); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnableThread.start(); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 298997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /** Forcibly restart Bluetooth if it is on */ 299997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly /* package */ synchronized void restart() { 300de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_ON) { 301997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly return; 302997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 303997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = true; 304997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly if (!disable(false)) { 305997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly mRestart = false; 306997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly } 307d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 308997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly 309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private synchronized void setBluetoothState(int state) { 310105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (state == mBluetoothState) { 311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); 315105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 316de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 317de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState); 318de893f550301a60274e87aa8168225e7a7a42184Nick Pelly intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 321105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBluetoothState = state; 322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 323105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 324105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 325105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler = new Handler() { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 330105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_REGISTER_SDP_RECORDS: 331bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly if (!isEnabled()) { 332bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly return; 333bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly } 334bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // SystemService.start() forks sdptool to register service 335bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records. It can fail to register some records if it is 336bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // forked multiple times in a row, probably because there is 337bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // some race in sdptool or bluez when operated in parallel. 338bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // As a workaround, delay 500ms between each fork of sdptool. 339bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // TODO: Don't fork sdptool in order to regsiter service 340bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly // records, use a DBUS call instead. 341bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly switch (msg.arg1) { 342bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 1: 343bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering hsag record"); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemService.start("hsag"); 345bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 346bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500); 347bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 348bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 2: 349bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering hfag record"); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemService.start("hfag"); 351bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 352bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); 353bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 354bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 3: 355bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering opush record"); 35603c707ab6fc97e99b1603b8d6edc604dbea3cd6fNick Pelly SystemService.start("opush"); 357bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 358bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); 359bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 360bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly case 4: 361bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly Log.d(TAG, "Registering pbap record"); 36267542964876aa7e4216e8f69f21dda68e7463b9aJaikumar Ganesh SystemService.start("pbap"); 363bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly break; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 365105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case MESSAGE_FINISH_DISABLE: 367105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project finishDisable(msg.arg1 != 0); 368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 3691caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh case MESSAGE_UUID_INTENT: 3701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String address = (String)msg.obj; 37116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (address != null) { 3721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh sendUuidIntent(address); 37316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly makeServiceChannelCallbacks(address); 37416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 3751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh break; 37612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly case MESSAGE_DISCOVERABLE_TIMEOUT: 37712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly int mode = msg.arg1; 37812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (isEnabled()) { 37912835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // TODO: Switch back to the previous scan mode 38012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // This is ok for now, because we only use 38112835478ee687a493d1b5882e67b6725bd539c26Nick Pelly // CONNECTABLE and CONNECTABLE_DISCOVERABLE 38212835478ee687a493d1b5882e67b6725bd539c26Nick Pelly setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, -1); 38312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly } 38412835478ee687a493d1b5882e67b6725bd539c26Nick Pelly break; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private EnableThread mEnableThread; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class EnableThread extends Thread { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mSaveSetting; 393105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public EnableThread(boolean saveSetting) { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSaveSetting = saveSetting; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean res = (enableNative() == 0); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 399b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int retryCount = 2; 400b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project boolean running = false; 401b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((retryCount-- > 0) && !running) { 402b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mEventLoop.start(); 403105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // it may take a momement for the other thread to do its 404b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // thing. Check periodically for a while. 405b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project int pollCount = 5; 406b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project while ((pollCount-- > 0) && !running) { 407b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (mEventLoop.isEventLoopRunning()) { 408b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project running = true; 409b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 410b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 411b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project try { 412b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Thread.sleep(100); 413b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } catch (InterruptedException e) {} 414b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 415b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 416b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (!running) { 417b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project log("bt EnableThread giving up"); 418b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project res = false; 419b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project disableNative(); 420b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res) { 425d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!setupNativeDataNative()) { 426d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 427d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSaveSetting) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project persistBluetoothOnSetting(true); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDiscovering = false; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.loadBondState(); 433bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.sendMessageDelayed( 434bc1fc05c1b3e8c407fa07b25777bf577d5285f49Nick Pelly mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 436105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Log bluetooth on to battery stats. 437105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long ident = Binder.clearCallingIdentity(); 438105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project try { 439105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBatteryStats.noteBluetoothOn(); 440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } catch (RemoteException e) { 441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } finally { 442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Binder.restoreCallingIdentity(ident); 443105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mEnableThread = null; 447105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 448105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project setBluetoothState(res ? 449de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_ON : 450de893f550301a60274e87aa8168225e7a7a42184Nick Pelly BluetoothAdapter.STATE_OFF); 451105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 452b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (res) { 453105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Update mode 454d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String[] propVal = {"Pairable", getProperty("Pairable")}; 455d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mEventLoop.onPropertyChanged(propVal); 456b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 457b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 4585c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa if (mIsAirplaneSensitive && isAirplaneModeOn()) { 4595c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa disable(false); 4605c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa } 4615c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void persistBluetoothOnSetting(boolean bluetoothOn) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long origCallerIdentityToken = Binder.clearCallingIdentity(); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bluetoothOn ? 1 : 0); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(origCallerIdentityToken); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ BondState getBondState() { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** local cache of bonding state. 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* we keep our own state to track the intermediate state BONDING, which 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* bluez does not track. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * All addreses must be passed in upper case. 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class BondState { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>(); 485105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // List of all the vendor_id prefix of Bluetooth addresses for 486105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // which auto pairing is not attempted. 487105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // The following companies are included in the list below: 488105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi), 489105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Parrot, Zhongshan General K-mate Electronics, Great Well 490105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi, 491105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura), 49221d0dca33e0c16c7de5c42bbcdf5a98ec67ead5dJaikumar Ganesh // Continental Automotive, Harman/Becker, Panasonic/Kyushu Ten, 49321d0dca33e0c16c7de5c42bbcdf5a98ec67ead5dJaikumar Ganesh // BMW (Motorola PCS) 494482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh private final ArrayList<String> mAutoPairingAddressBlacklist = 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new ArrayList<String>(Arrays.asList( 496105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F", 497105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8", 498105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04", 499105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59", 50021d0dca33e0c16c7de5c42bbcdf5a98ec67ead5dJaikumar Ganesh "00:0A:30", "00:1E:AE", "00:1C:D7", "00:80:F0", "00:12:8A" 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project )); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 503482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh // List of names of Bluetooth devices for which auto pairing should be 504482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh // disabled. 505738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh private final ArrayList<String> mAutoPairingExactNameBlacklist = 506482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh new ArrayList<String>(Arrays.asList( 507738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh "Motorola IHF1000", "i.TechBlueBAND", "X5 Stereo v1.3")); 508738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh 509738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh private final ArrayList<String> mAutoPairingPartialNameBlacklist = 510738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh new ArrayList<String>(Arrays.asList( 511738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh "BMW", "Audi")); 512482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 5132092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If this is an outgoing connection, store the address. 5142092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // There can be only 1 pending outgoing connection at a time, 5152092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private String mPendingOutgoingBonding; 5162092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 5172092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh private synchronized void setPendingOutgoingBonding(String address) { 5182092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = address; 5192092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 5202092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 5212092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh public synchronized String getPendingOutgoingBonding() { 5222092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh return mPendingOutgoingBonding; 5232092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 5242092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void loadBondState() { 526de893f550301a60274e87aa8168225e7a7a42184Nick Pelly if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 529d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String []bonds = null; 530d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String val = getProperty("Devices"); 531d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val != null) { 532d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh bonds = val.split(","); 533d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bonds == null) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.clear(); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log("found " + bonds.length + " bonded devices"); 539d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh for (String device : bonds) { 540d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mState.put(getAddressFromObjectPath(device).toUpperCase(), 541d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh BluetoothDevice.BOND_BONDED); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state) { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setBondState(address, state, 0); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** reason is ignored unless state == BOND_NOT_BONDED */ 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setBondState(String address, int state, int reason) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldState = getBondState(address); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldState == state) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5552092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 5562092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // Check if this was an pending outgoing bonding. 5572092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh // If yes, reset the state. 5582092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (oldState == BluetoothDevice.BOND_BONDING) { 5592092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (address.equals(mPendingOutgoingBonding)) { 5602092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mPendingOutgoingBonding = null; 5612092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 5622092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh } 5632092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" + 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason + ")"); 566005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 567005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 568005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state); 569005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState); 570005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (state == BluetoothDevice.BOND_NONE) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reason <= 0) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setBondState() called to unbond device, but reason code is " + 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "invalid. Overriding reason code with BOND_RESULT_REMOVED"); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reason = BluetoothDevice.UNBOND_REASON_REMOVED; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 576005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly intent.putExtra(BluetoothDevice.EXTRA_REASON, reason); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.remove(address); 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.put(address, state); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent, BLUETOOTH_PERM); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isAutoPairingBlacklisted(String address) { 586482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh for (String blacklistAddress : mAutoPairingAddressBlacklist) { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (address.startsWith(blacklistAddress)) return true; 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 589482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh 590482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh String name = getRemoteName(address); 591482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh if (name != null) { 592738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh for (String blacklistName : mAutoPairingExactNameBlacklist) { 593738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh if (name.equals(blacklistName)) return true; 594738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh } 595738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh 596738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh for (String blacklistName : mAutoPairingPartialNameBlacklist) { 597738ed80262aa26128924c51f59ffd49e1163eb8dJaikumar Ganesh if (name.startsWith(blacklistName)) return true; 598482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 599482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer state = mState.get(address); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 606005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly return BluetoothDevice.BOND_NONE; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return state.intValue(); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 611e5d93b7ed983f98855555d560faf060836f1a52fJaikumar Ganesh /*package*/ synchronized String[] listInState(int state) { 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<String> result = new ArrayList<String>(mState.size()); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, Integer> e : mState.entrySet()) { 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (e.getValue().intValue() == state) { 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result.add(e.getKey()); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result.toArray(new String[result.size()]); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void addAutoPairingFailure(String address) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAutoPairingFailures.contains(address)) { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAutoPairingFailures.add(address); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean isAutoPairingAttemptsInProgress(String address) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getAttempt(address) != 0; 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void clearPinAttempts(String address) { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.remove(address); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean hasAutoPairingFailed(String address) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAutoPairingFailures.contains(address); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getAttempt(String address) { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return attempt.intValue(); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void attempt(String address) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer attempt = mPinAttempt.get(address); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newAttempt; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attempt == null) { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = 1; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newAttempt = attempt.intValue() + 1; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPinAttempt.put(address, new Integer(newAttempt)); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toBondStateString(int bondState) { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (bondState) { 662005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly case BluetoothDevice.BOND_NONE: 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "not bonded"; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDING: 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonding"; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BluetoothDevice.BOND_BONDED: 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "bonded"; 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "??????"; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh /*package*/ synchronized boolean isAdapterPropertiesEmpty() { 6749519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh return mAdapterProperties.isEmpty(); 6759519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh } 6769519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh 677d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/synchronized void getAllProperties() { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 679bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.clear(); 680d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 681d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String properties[] = (String [])getAdapterPropertiesNative(); 682d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The String Array consists of key-value pairs. 683d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties == null) { 684d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "*Error*: GetAdapterProperties returned NULL"); 685d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return; 686d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 687d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 6888bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 6898bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 690efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 6918bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 6928bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 6938bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error:Adapter Property at index" + i + "is null"); 6948bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 6958bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 6968bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name.equals("Devices")) { 697efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 6988bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 6998bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 700efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 701efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 702efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 703efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 704efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 7058bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 7068bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } else { 7078bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 7088bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 709bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, newValue); 710d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 711d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 712d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Add adapter object path property. 713d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String adapterPath = getAdapterPathNative(); 714d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterPath != null) 715bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put("ObjectPath", adapterPath + "/dev_"); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 718d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setProperty(String name, String value) { 719bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mAdapterProperties.put(name, value); 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setName(String name) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 728d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyString("Name", name); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 731d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean 732d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Either have a single property function with Object as the parameter 733d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or have a function for each property and then obfuscate in the JNI layer. 734d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The following looks dirty. 735d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyString(String key, String value) { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 737d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyStringNative(key, value); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 740d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyInteger(String key, int value) { 741d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 742d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyIntegerNative(key, value); 743d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 745d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private boolean setPropertyBoolean(String key, boolean value) { 746d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 747d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setAdapterPropertyBooleanNative(key, value ? 1 : 0); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 750d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /** 751d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Set the discoverability window for the device. A timeout of zero 752d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * makes the device permanently discoverable (if the device is 753d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * discoverable). Setting the timeout to a nonzero value does not make 754d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * a device discoverable; you need to call setMode() to make the device 755d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * explicitly discoverable. 756d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 757d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param timeout_s The discoverable timeout in seconds. 758d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh */ 759d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean setDiscoverableTimeout(int timeout) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 762d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return setPropertyInteger("DiscoverableTimeout", timeout); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 76512835478ee687a493d1b5882e67b6725bd539c26Nick Pelly public synchronized boolean setScanMode(int mode, int duration) { 76618b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 76718b1e79a123b979d25bfa5d0b0ee5d0382dbd64bNick Pelly "Need WRITE_SECURE_SETTINGS permission"); 768de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean pairable = false; 769de893f550301a60274e87aa8168225e7a7a42184Nick Pelly boolean discoverable = false; 77012835478ee687a493d1b5882e67b6725bd539c26Nick Pelly 771de893f550301a60274e87aa8168225e7a7a42184Nick Pelly switch (mode) { 772de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 77312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 774d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = false; 775d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 776de893f550301a60274e87aa8168225e7a7a42184Nick Pelly break; 777de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 77812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 779d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 780d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = false; 781005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 782de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 78312835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.removeMessages(MESSAGE_DISCOVERABLE_TIMEOUT); 784d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh pairable = true; 785d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh discoverable = true; 78612835478ee687a493d1b5882e67b6725bd539c26Nick Pelly Message msg = mHandler.obtainMessage(MESSAGE_DISCOVERABLE_TIMEOUT); 78712835478ee687a493d1b5882e67b6725bd539c26Nick Pelly mHandler.sendMessageDelayed(msg, duration * 1000); 78812835478ee687a493d1b5882e67b6725bd539c26Nick Pelly if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds"); 789005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly break; 790de893f550301a60274e87aa8168225e7a7a42184Nick Pelly default: 791de893f550301a60274e87aa8168225e7a7a42184Nick Pelly Log.w(TAG, "Requested invalid scan mode " + mode); 792de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return false; 793d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 794d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Pairable", pairable); 795d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh setPropertyBoolean("Discoverable", discoverable); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 797d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return true; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 800d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ synchronized String getProperty (String name) { 801bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly if (!mAdapterProperties.isEmpty()) 802bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 803d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh getAllProperties(); 804bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mAdapterProperties.get(name); 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 807d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getAddress() { 808d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 809d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Address"); 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 812d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getName() { 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 814d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getProperty("Name"); 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 818d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Returns the user-friendly name of a remote device. This value is 819d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * returned from our local cache, which is updated when onPropertyChange 820d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * event is received. 821d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Do not expect to retrieve the updated remote name immediately after 822d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * changing the name on the remote device. 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 824d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Bluetooth address of remote device. 825d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * 826d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return The user-friendly name of the specified remote device. 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 828d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized String getRemoteName(String address) { 829d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 830005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 831d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 832d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 83355929a958bf0e482c8e4d7df3dd75957f1e9d871Jaikumar Ganesh return getRemoteDeviceProperty(address, "Name"); 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the discoverability window for the device. A timeout of zero 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * means that the device is permanently discoverable (if the device is 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the discoverable mode). 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The discoverability window of the device, in seconds. A negative 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value indicates an error. 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getDiscoverableTimeout() { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 846d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String timeout = getProperty("DiscoverableTimeout"); 847d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (timeout != null) 848d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(timeout); 849d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 850d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return -1; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getScanMode() { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 855d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!isEnabled()) 856de893f550301a60274e87aa8168225e7a7a42184Nick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 857d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 858d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean pairable = getProperty("Pairable").equals("true"); 859d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh boolean discoverable = getProperty("Discoverable").equals("true"); 860d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return bluezStringToScanMode (pairable, discoverable); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 863d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean startDiscovery() { 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 866d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!isEnabled()) { 867d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return false; 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return startDiscoveryNative(); 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 872d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean cancelDiscovery() { 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 875d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return stopDiscoveryNative(); 876d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 877d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 878d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh public synchronized boolean isDiscovering() { 879d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 880d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return mIsDiscovering; 881d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 883d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void setIsDiscovering(boolean isDiscovering) { 884d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh mIsDiscovering = isDiscovering; 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean createBond(String address) { 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 890005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8952092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh if (mBondState.getPendingOutgoingBonding() != null) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): another device is bonding"); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a different device is currently bonding, fail 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check for bond state only if we are not performing auto 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pairing exponential back-off attempts. 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mBondState.isAutoPairingAttemptsInProgress(address) && 904005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) { 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project log("Ignoring createBond(): this device is already bonding or bonded"); 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!createPairedDeviceNative(address, 60000 /* 1 minute */)) { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9132092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh mBondState.setPendingOutgoingBonding(address); 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); 9152092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean cancelBondProcess(String address) { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 922005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 930005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 932d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh cancelDeviceCreationNative(address); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean removeBond(String address) { 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 939005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 942d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return removeDeviceNative(getObjectPathFromAddress(address)); 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized String[] listBonds() { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.listInState(BluetoothDevice.BOND_BONDED); 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getBondState(String address) { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 952005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 953b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBondState.getBondState(address.toUpperCase()); 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9589488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ boolean isRemoteDeviceInCache(String address) { 959bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return (mDeviceProperties.get(address) != null); 9609488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 9619488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 9629488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh /*package*/ String[] getRemoteDeviceProperties(String address) { 9639488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh String objectPath = getObjectPathFromAddress(address); 9649488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh return (String [])getDevicePropertiesNative(objectPath); 9659488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh } 9669488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh 967d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ synchronized String getRemoteDeviceProperty(String address, String property) { 968bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> properties = mDeviceProperties.get(address); 969d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (properties != null) { 970d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return properties.get(property); 971d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 972d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // Query for remote device properties, again. 973d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // We will need to reload the cache when we switch Bluetooth on / off 974d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // or if we crash. 97510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (updateRemoteDevicePropertiesCache(address)) 976d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return getRemoteDeviceProperty(address, property); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 978d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getRemoteDeviceProperty: " + property + "not present:" + address); 979d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh /* package */ synchronized boolean updateRemoteDevicePropertiesCache(String address) { 98310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh String[] propValues = getRemoteDeviceProperties(address); 98410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (propValues != null) { 98510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh addRemoteDeviceProperties(address, propValues); 98610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return true; 98710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 98810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return false; 98910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 99010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 991d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void addRemoteDeviceProperties(String address, String[] properties) { 992395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh /* 993395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * We get a DeviceFound signal every time RSSI changes or name changes. 994395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh * Don't create a new Map object every time */ 995bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map<String, String> propertyValues = mDeviceProperties.get(address); 996efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (propertyValues == null) { 997395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh propertyValues = new HashMap<String, String>(); 998395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh } 999395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh 10008bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int i = 0; i < properties.length; i++) { 10018bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh String name = properties[i]; 1002efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh String newValue = null; 10038bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh int len; 10048bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name == null) { 10058bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh Log.e(TAG, "Error: Remote Device Property at index" + i + "is null"); 10068bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh continue; 10078bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 10088bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh if (name.equals("UUIDs") || name.equals("Nodes")) { 1009efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh StringBuilder str = new StringBuilder(); 10108bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh len = Integer.valueOf(properties[++i]); 10118bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh for (int j = 0; j < len; j++) { 1012efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(properties[++i]); 1013efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh str.append(","); 1014efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh } 1015efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh if (len > 0) { 1016efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh newValue = str.toString(); 10178bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh } 1018d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 10198bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh newValue = properties[++i]; 1020d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1021efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh 10228bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh propertyValues.put(name, newValue); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1024bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propertyValues); 102510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 102610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We have added a new remote device or updated its properties. 102710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Also update the serviceChannel cache. 102810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh updateDeviceServiceChannelCache(address); 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1031d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ void removeRemoteDeviceProperties(String address) { 1032bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.remove(address); 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1035d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ synchronized void setRemoteDeviceProperty(String address, String name, 1036d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value) { 1037bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly Map <String, String> propVal = mDeviceProperties.get(address); 1038d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (propVal != null) { 1039d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh propVal.put(name, value); 1040bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mDeviceProperties.put(address, propVal); 1041d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } else { 1042d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address); 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1047efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Sets the remote device trust state. 1048efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1049efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate operation success or fail 1050efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1051efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean setTrust(String address, boolean value) { 1052005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1053e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1054e6ee3be1c254404dad842298f6f56c11cc6c7ac8Nick Pelly "Need BLUETOOTH_ADMIN permission"); 1055efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1056efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1057efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1058efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return setDevicePropertyBooleanNative(getObjectPathFromAddress(address), "Trusted", 1059efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue value ? 1 : 0); 1060efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1061efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1062efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1063efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Gets the remote device trust state as boolean. 1064efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * Note: this value may be 1065efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * retrieved from cache if we retrieved the data before * 1066efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * 1067efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue * @return boolean to indicate trust or untrust state 1068efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue */ 1069efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue public synchronized boolean getTrustState(String address) { 1070005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1071efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1072efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1073efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1074efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1075efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue String val = getRemoteDeviceProperty(address, "Trusted"); 1076efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue if (val == null) { 1077efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return false; 1078efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } else { 1079efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue return val.equals("true") ? true : false; 1080efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1081efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue } 1082efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue 1083efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue /** 1084d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the remote major, minor classes encoded as a 32-bit 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * integer. 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: this value is retrieved from cache, because we get it during 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remote-device discovery. 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 32-bit integer encoding the remote major, minor, and service 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes. 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized int getRemoteClass(String address) { 1094005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1095ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1096ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly return BluetoothClass.ERROR; 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1098d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String val = getRemoteDeviceProperty(address, "Class"); 1099d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (val == null) 1100d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return BluetoothClass.ERROR; 1101d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else { 1102d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return Integer.valueOf(val); 1103d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1105d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1108dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * Gets the UUIDs supported by the remote device 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1110dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @return array of 128bit ParcelUuids 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1112dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public synchronized ParcelUuid[] getRemoteUuids(String address) { 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1114005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11171caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return getUuidFromCache(address); 11181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11191caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11201caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private ParcelUuid[] getUuidFromCache(String address) { 1121d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getRemoteDeviceProperty(address, "UUIDs"); 1122dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh if (value == null) return null; 1123dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1124dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh String[] uuidStrings = null; 1125d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh // The UUIDs are stored as a "," separated string. 1126dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuidStrings = value.split(","); 1127dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; 1128dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh 1129dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh for (int i = 0; i < uuidStrings.length; i++) { 1130dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh uuids[i] = ParcelUuid.fromString(uuidStrings[i]); 1131dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh } 1132d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return uuids; 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 113516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /** 113616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Connect and fetch new UUID's using SDP. 113716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * The UUID's found are broadcast as intents. 113816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Optionally takes a uuid and callback to fetch the RFCOMM channel for the 113916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * a given uuid. 114016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success 114116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for 114216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * callback and broadcast intents. 114316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly */ 114416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid, 114516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback) { 11461caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 11471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (!BluetoothAdapter.checkBluetoothAddress(address)) { 11481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return false; 11491caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11501caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 115116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = new RemoteService(address, uuid); 115216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null && mUuidCallbackTracker.get(service) != null) { 115316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // An SDP query for this address & uuid is already in progress 115416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Do not add this callback for the uuid 115516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly return false; 115616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 115716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 11581caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (mUuidIntentTracker.contains(address)) { 11591caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // An SDP query for this address is already in progress 116016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Add this uuid onto the in-progress SDP query 116116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 116216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 116316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 11641caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return true; 11651caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11661caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11671caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh boolean ret; 11681caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (getBondState(address) == BluetoothDevice.BOND_BONDED) { 11691caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh String path = getObjectPathFromAddress(address); 11701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh if (path == null) return false; 11711caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh // Use an empty string for the UUID pattern 11731caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = discoverServicesNative(path, ""); 11741caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } else { 11751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh ret = createDeviceNative(address); 11761caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11771caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11781caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.add(address); 117916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (uuid != null) { 118016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mUuidCallbackTracker.put(new RemoteService(address, uuid), callback); 118116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 11821caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11831caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 11841caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh message.obj = address; 11851caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 11861caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh return ret; 11871caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 11881caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1190d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * Gets the rfcomm channel associated with the UUID. 119116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly * Pulls records from the cache only. 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1193d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @param address Address of the remote device 1194dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh * @param uuid ParcelUuid of the service attribute 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1196d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh * @return rfcomm channel associated with the service attribute 119710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh * -1 on error 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1199dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh public int getRemoteServiceChannel(String address, ParcelUuid uuid) { 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1201005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 1202b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly return BluetoothDevice.ERROR; 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 120410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // Check if we are recovering from a crash. 120510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (mDeviceProperties.isEmpty()) { 120610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (!updateRemoteDevicePropertiesCache(address)) 120710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 120810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 120910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 121010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address); 121110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (value != null && value.containsKey(uuid)) 121210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return value.get(uuid); 121310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh return -1; 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized boolean setPin(String address, byte[] pin) { 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pin == null || pin.length <= 0 || pin.length > 16 || 1220005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly !BluetoothAdapter.checkBluetoothAddress(address)) { 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setPin(" + address + ") called but no native data available, " + 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " or by bluez.\n"); 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bluez API wants pin as a string 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pinString; 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinString = new String(pin, "UTF8"); 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException uee) { 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "UTF8 not supported?!?"); 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return setPinNative(address, pinString, data.intValue()); 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1242b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPasskey(String address, int passkey) { 1243b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1244b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1245005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) { 1246b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1247b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1248b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1249b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1250b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1251b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1252b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1253b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1254b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1255b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1256b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPasskeyNative(address, passkey, data.intValue()); 1257b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1258b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1259b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean setPairingConfirmation(String address, boolean confirm) { 1260b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1261b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "Need BLUETOOTH_ADMIN permission"); 1262b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh address = address.toUpperCase(); 1263b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 1264b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh if (data == null) { 1265b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " + 1266b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" + 1267b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh " or by bluez.\n"); 1268b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return false; 1269b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1270b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return setPairingConfirmationNative(address, confirm, data.intValue()); 1271b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh } 1272b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh 1273b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh public synchronized boolean cancelPairingUserInput(String address) { 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Need BLUETOOTH_ADMIN permission"); 1276005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly if (!BluetoothAdapter.checkBluetoothAddress(address)) { 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly mBondState.setBondState(address, BluetoothDevice.BOND_NONE, 1280397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project address = address.toUpperCase(); 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data == null) { 1284b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " + 1285b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " + 1286b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh "by the remote or by bluez.\n"); 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh return cancelPairingUserInputNative(address, data.intValue()); 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 129210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh public void updateDeviceServiceChannelCache(String address) { 129310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh ParcelUuid[] deviceUuids = getRemoteUuids(address); 129410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // We are storing the rfcomm channel numbers only for the uuids 129510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh // we are interested in. 129610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh int channel; 129716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("updateDeviceServiceChannelCache(" + address + ")"); 129816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 129916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly ArrayList<ParcelUuid> applicationUuids = new ArrayList(); 130016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 130116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 130216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 130316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 130416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly applicationUuids.add(service.uuid); 130516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 130616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 130716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 130810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 130910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh Map <ParcelUuid, Integer> value = new HashMap<ParcelUuid, Integer>(); 131016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 131116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for default uuids 131216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : RFCOMM_UUIDS) { 131310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 131416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 131516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 131616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(system): " + uuid + " " + channel); 131710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh value.put(uuid, channel); 131810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 131910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 132016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Retrieve RFCOMM channel for application requested uuids 132116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (ParcelUuid uuid : applicationUuids) { 132216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) { 132316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = getDeviceServiceChannelNative(getObjectPathFromAddress(address), 132416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly uuid.toString(), 0x0004); 132516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("\tuuid(application): " + uuid + " " + channel); 132616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly value.put(uuid, channel); 132716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 132816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 132916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 133016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly synchronized (this) { 133116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Make application callbacks 133216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 133316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 133416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 133516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 133616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = -1; 133716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (value.get(service.uuid) != null) { 133816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel = value.get(service.uuid); 133916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 134016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (channel != -1) { 134116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Making callback for " + service.uuid + " with result " + 134216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly channel); 134316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 134416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 134516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 134616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(channel); 134716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 134816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 134916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 135016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 135116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 135216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 135316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 135416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 135516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly // Update cache 135616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly mDeviceServiceChannelCache.put(address, value); 135716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 135810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh } 135910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 136024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly /** 136124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * b is a handle to a Binder instance, so that this service can be notified 136224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * for Applications that terminate unexpectedly, to clean there service 136324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly * records 136424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly */ 136524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid, 136624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int channel, IBinder b) { 136724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 136824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 136924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (serviceName == null || uuid == null || channel < 1 || 137024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) { 137124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 137224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 137324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) { 137424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Log.w(TAG, "Attempted to register a reserved UUID: " + uuid); 137524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 137624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 137724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle = addRfcommServiceRecordNative(serviceName, 137824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(), 137924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly (short)channel); 138024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("new handle " + Integer.toHexString(handle)); 138124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (handle == -1) { 138224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return -1; 138324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 138424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 138524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid = Binder.getCallingPid(); 138624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.put(new Integer(handle), new Integer(pid)); 138724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly try { 138824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly b.linkToDeath(new Reaper(handle, pid), 0); 138924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } catch (RemoteException e) {} 139024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly return handle; 139124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 139224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 139324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void removeServiceRecord(int handle) { 139424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 139524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly "Need BLUETOOTH permission"); 139624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, Binder.getCallingPid()); 139724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 139824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 139924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private synchronized void checkAndRemoveRecord(int handle, int pid) { 140024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer handleInt = new Integer(handle); 140124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer owner = mServiceRecordToPid.get(handleInt); 140224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (owner != null && pid == owner.intValue()) { 140324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Removing service record " + Integer.toHexString(handle) + " for pid " + 140424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pid); 140524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly mServiceRecordToPid.remove(handleInt); 140624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly removeServiceRecordNative(handle); 140724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 140824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 140924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 141024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private class Reaper implements IBinder.DeathRecipient { 141124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int pid; 141224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int handle; 141324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Reaper(int handle, int pid) { 141424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.pid = pid; 141524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly this.handle = handle; 141624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 141724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly public void binderDied() { 141824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly synchronized (BluetoothService.this) { 141924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (DBG) log("Tracked app " + pid + " died"); 142024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly checkAndRemoveRecord(handle, pid); 142124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 142224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 142324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 142424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Query the airplane mode from Settings.System just to make sure that 14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some random app is not sending this intent and disabling bluetooth 14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean enabled = !isAirplaneModeOn(); 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If bluetooth is currently expected to be on, then enable or disable bluetooth 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 1437105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project enable(false); 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disable(false); 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void registerForAirplaneMode() { 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(), 14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_RADIOS); 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsAirplaneSensitive = airplaneModeRadios == null 14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsAirplaneSensitive) { 14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIntentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); 14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mReceiver, mIntentFilter); 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Returns true if airplane mode is currently on */ 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean isAirplaneModeOn() { 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Settings.System.getInt(mContext.getContentResolver(), 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.System.AIRPLANE_MODE_ON, 0) == 1; 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /* Broadcast the Uuid intent */ 14641caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh /*package*/ synchronized void sendUuidIntent(String address) { 14656179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh ParcelUuid[] uuid = getUuidFromCache(address); 14666179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 14672d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address)); 14686179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); 14696179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); 14701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14716179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh if (mUuidIntentTracker.contains(address)) 14721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh mUuidIntentTracker.remove(address); 147316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 147416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 147516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 147616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ synchronized void makeServiceChannelCallbacks(String address) { 147716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator(); 147816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.hasNext();) { 147916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly RemoteService service = iter.next(); 148016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 148116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (DBG) log("Cleaning up failed UUID channel lookup: " + service.address + 148216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly " " + service.uuid); 148316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly IBluetoothCallback callback = mUuidCallbackTracker.get(service); 148416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (callback != null) { 148516fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly try { 148616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly callback.onRfcommChannelFound(-1); 148716fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } catch (RemoteException e) {Log.e(TAG, "", e);} 148816fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 148916fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly 149016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly iter.remove(); 149116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 149216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 14931caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh } 14941caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1497105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch(mBluetoothState) { 1498de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_OFF: 149924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth OFF\n"); 1500105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1501de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_ON: 150224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING ON\n"); 1503105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1504de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_TURNING_OFF: 150524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth TURNING OFF\n"); 1506105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return; 1507de893f550301a60274e87aa8168225e7a7a42184Nick Pelly case BluetoothAdapter.STATE_ON: 150824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Bluetooth ON\n"); 1509105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1510105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 151124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive); 151224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 151324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local address = " + getAddress()); 151424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("Local name = " + getName()); 151524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("isDiscovering() = " + isDiscovering()); 1516105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1517105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BluetoothHeadset headset = new BluetoothHeadset(mContext, null); 1518105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1519105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Known devices--"); 1520bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly for (String address : mDeviceProperties.keySet()) { 15211eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly int bondState = mBondState.getBondState(address); 1522105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.printf("%s %10s (%d) %s\n", address, 15231eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly toBondStateString(bondState), 1524105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mBondState.getAttempt(address), 1525105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project getRemoteName(address)); 152624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly 152724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address); 152824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (uuidChannels == null) { 152924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tuuids = null"); 153024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 153124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (ParcelUuid uuid : uuidChannels.keySet()) { 153224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer channel = uuidChannels.get(uuid); 153324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (channel == null) { 153424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid); 153524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } else { 153624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\t" + uuid + " RFCOMM channel = " + channel); 15371eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 15381eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 15391eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly } 154016fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly for (RemoteService service : mUuidCallbackTracker.keySet()) { 154116fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly if (service.address.equals(address)) { 154216fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly pw.println("\tPENDING CALLBACK: " + service.uuid); 154316fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 154416fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly } 1545105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1546105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1547d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String value = getProperty("Devices"); 15481eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly String[] devicesObjectPath = null; 1549d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (value != null) { 1550d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh devicesObjectPath = value.split(","); 1551d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1552105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--ACL connected devices--"); 155324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly if (devicesObjectPath != null) { 155424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (String device : devicesObjectPath) { 155524bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println(getAddressFromObjectPath(device)); 155624bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 1557105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1558105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1559105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Rather not do this from here, but no-where else and I need this 1560105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // dump 1561105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("\n--Headset Service--"); 1562105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project switch (headset.getState()) { 1563105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_DISCONNECTED: 1564105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_DISCONNECTED"); 1565105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1566105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTING: 1567105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTING"); 1568105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1569105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_CONNECTED: 1570105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_CONNECTED"); 1571105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1572105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project case BluetoothHeadset.STATE_ERROR: 1573105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project pw.println("getState() = STATE_ERROR"); 1574105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project break; 1575105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 15766c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 157724bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\ngetCurrentHeadset() = " + headset.getCurrentHeadset()); 157824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint()); 1579105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project headset.close(); 158024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\n--Application Service Records--"); 158124bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly for (Integer handle : mServiceRecordToPid.keySet()) { 158224bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly Integer pid = mServiceRecordToPid.get(handle); 158324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle)); 158424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly } 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1587d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) { 1588d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (pairable && discoverable) 1589bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1590d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else if (pairable && !discoverable) 1591bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1592d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh else 1593bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return BluetoothAdapter.SCAN_MODE_NONE; 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static String scanModeToBluezString(int mode) { 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mode) { 1598bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_NONE: 15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "off"; 1600bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connectable"; 1602bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "discoverable"; 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1608d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getAddressFromObjectPath(String objectPath) { 1609d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String adapterObjectPath = getProperty("ObjectPath"); 1610d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (adapterObjectPath == null || objectPath == null) { 1611d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 1612d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " or deviceObjectPath:" + objectPath + " is null"); 1613d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1614d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1615d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (!objectPath.startsWith(adapterObjectPath)) { 1616d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath + 1617d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh " is not a prefix of deviceObjectPath:" + objectPath + 1618d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh "bluetoothd crashed ?"); 1619d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1620d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1621d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String address = objectPath.substring(adapterObjectPath.length()); 1622d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (address != null) return address.replace('_', ':'); 1623d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1624d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "getAddressFromObjectPath: Address being returned is null"); 1625d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1626d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1627d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1628d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh /*package*/ String getObjectPathFromAddress(String address) { 1629d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh String path = getProperty("ObjectPath"); 1630d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh if (path == null) { 1631d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh Log.e(TAG, "Error: Object Path is null"); 1632d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return null; 1633d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1634d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh path = path + address.replace(":", "_"); 1635d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh return path; 1636d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh } 1637d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void log(String msg) { 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, msg); 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1641d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1642d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native static void classInitNative(); 1643d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void initializeNativeDataNative(); 1644d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setupNativeDataNative(); 1645d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean tearDownNativeDataNative(); 1646d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native void cleanupNativeDataNative(); 1647d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native String getAdapterPathNative(); 1648d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1649d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int isEnabledNative(); 1650d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int enableNative(); 1651d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int disableNative(); 1652d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1653d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getAdapterPropertiesNative(); 1654d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native Object[] getDevicePropertiesNative(String objectPath); 1655d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyStringNative(String key, String value); 1656d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyIntegerNative(String key, int value); 1657d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setAdapterPropertyBooleanNative(String key, int value); 1658d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1659d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean startDiscoveryNative(); 1660d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean stopDiscoveryNative(); 1661d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1662d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean createPairedDeviceNative(String address, int timeout_ms); 1663d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean cancelDeviceCreationNative(String address); 1664d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean removeDeviceNative(String objectPath); 1665d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native int getDeviceServiceChannelNative(String objectPath, String uuid, 1666d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh int attributeId); 1667d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh 1668b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean cancelPairingUserInputNative(String address, int nativeData); 1669d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh private native boolean setPinNative(String address, String pin, int nativeData); 1670b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPasskeyNative(String address, int passkey, int nativeData); 1671b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh private native boolean setPairingConfirmationNative(String address, boolean confirm, 1672b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh int nativeData); 167324bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean setDevicePropertyBooleanNative(String objectPath, String key, 167424bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly int value); 16751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh private native boolean createDeviceNative(String address); 167616fb88a673c41b93c5d57ccb28c2697e7d87701aNick Pelly /*package*/ native boolean discoverServicesNative(String objectPath, String pattern); 167710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh 167824bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb, 167924bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly short channel); 168024bb9b8af4ff691538fe9e517e8156016b0da6cdNick Pelly private native boolean removeServiceRecordNative(int handle); 16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1682