BluetoothManagerService.java revision 414011116777e66bb3364fa86b856aa3574edbfa
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import android.Manifest; 20import android.app.ActivityManager; 21import android.bluetooth.BluetoothAdapter; 22import android.bluetooth.BluetoothProfile; 23import android.bluetooth.IBluetooth; 24import android.bluetooth.IBluetoothCallback; 25import android.bluetooth.IBluetoothGatt; 26import android.bluetooth.IBluetoothHeadset; 27import android.bluetooth.IBluetoothManager; 28import android.bluetooth.IBluetoothManagerCallback; 29import android.bluetooth.IBluetoothProfileServiceConnection; 30import android.bluetooth.IBluetoothStateChangeCallback; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.ContentResolver; 34import android.content.Context; 35import android.content.Intent; 36import android.content.IntentFilter; 37import android.content.ServiceConnection; 38import android.content.pm.PackageManager; 39import android.content.pm.UserInfo; 40import android.database.ContentObserver; 41import android.os.Binder; 42import android.os.Handler; 43import android.os.IBinder; 44import android.os.Looper; 45import android.os.Message; 46import android.os.Process; 47import android.os.RemoteCallbackList; 48import android.os.RemoteException; 49import android.os.SystemClock; 50import android.os.UserHandle; 51import android.os.UserManager; 52import android.provider.Settings; 53import android.provider.Settings.SettingNotFoundException; 54import android.util.Slog; 55import java.util.concurrent.locks.ReentrantReadWriteLock; 56 57import java.io.FileDescriptor; 58import java.io.PrintWriter; 59import java.util.HashMap; 60import java.util.Map; 61 62class BluetoothManagerService extends IBluetoothManager.Stub { 63 private static final String TAG = "BluetoothManagerService"; 64 private static final boolean DBG = true; 65 66 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 67 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 68 private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 69 private static final String EXTRA_ACTION="action"; 70 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 71 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 72 private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 73 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 74 private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 75 //Maximum msec to wait for service restart 76 private static final int SERVICE_RESTART_TIME_MS = 200; 77 //Maximum msec to wait for restart due to error 78 private static final int ERROR_RESTART_TIME_MS = 3000; 79 //Maximum msec to delay MESSAGE_USER_SWITCHED 80 private static final int USER_SWITCHED_TIME_MS = 200; 81 // Delay for the addProxy function in msec 82 private static final int ADD_PROXY_DELAY_MS = 100; 83 84 private static final int MESSAGE_ENABLE = 1; 85 private static final int MESSAGE_DISABLE = 2; 86 private static final int MESSAGE_REGISTER_ADAPTER = 20; 87 private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 88 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 89 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 90 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 91 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 92 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 93 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; 94 private static final int MESSAGE_TIMEOUT_BIND = 100; 95 private static final int MESSAGE_TIMEOUT_UNBIND = 101; 96 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; 97 private static final int MESSAGE_USER_SWITCHED = 300; 98 private static final int MESSAGE_USER_UNLOCKED = 301; 99 private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 100 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 101 private static final int MAX_SAVE_RETRIES = 3; 102 private static final int MAX_ERROR_RESTART_RETRIES = 6; 103 104 // Bluetooth persisted setting is off 105 private static final int BLUETOOTH_OFF=0; 106 // Bluetooth persisted setting is on 107 // and Airplane mode won't affect Bluetooth state at start up 108 private static final int BLUETOOTH_ON_BLUETOOTH=1; 109 // Bluetooth persisted setting is on 110 // but Airplane mode will affect Bluetooth state at start up 111 // and Airplane mode will have higher priority. 112 private static final int BLUETOOTH_ON_AIRPLANE=2; 113 114 private static final int SERVICE_IBLUETOOTH = 1; 115 private static final int SERVICE_IBLUETOOTHGATT = 2; 116 117 private final Context mContext; 118 private static int mBleAppCount = 0; 119 120 // Locks are not provided for mName and mAddress. 121 // They are accessed in handler or broadcast receiver, same thread context. 122 private String mAddress; 123 private String mName; 124 private final ContentResolver mContentResolver; 125 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 126 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 127 private IBinder mBluetoothBinder; 128 private IBluetooth mBluetooth; 129 private IBluetoothGatt mBluetoothGatt; 130 private final ReentrantReadWriteLock mBluetoothLock = 131 new ReentrantReadWriteLock(); 132 private boolean mBinding; 133 private boolean mUnbinding; 134 // used inside handler thread 135 private boolean mQuietEnable = false; 136 // configuarion from external IBinder call which is used to 137 // synchronize with broadcast receiver. 138 private boolean mQuietEnableExternal; 139 // configuarion from external IBinder call which is used to 140 // synchronize with broadcast receiver. 141 private boolean mEnableExternal; 142 // used inside handler thread 143 private boolean mEnable; 144 private int mState; 145 private final BluetoothHandler mHandler; 146 private int mErrorRecoveryRetryCounter; 147 private final int mSystemUiUid; 148 149 // Save a ProfileServiceConnections object for each of the bound 150 // bluetooth profile services 151 private final Map <Integer, ProfileServiceConnections> mProfileServices = 152 new HashMap <Integer, ProfileServiceConnections>(); 153 154 private void registerForAirplaneMode(IntentFilter filter) { 155 final ContentResolver resolver = mContext.getContentResolver(); 156 final String airplaneModeRadios = Settings.Global.getString(resolver, 157 Settings.Global.AIRPLANE_MODE_RADIOS); 158 final String toggleableRadios = Settings.Global.getString(resolver, 159 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 160 boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 161 airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 162 if (mIsAirplaneSensitive) { 163 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 164 } 165 } 166 167 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 168 @Override 169 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 170 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 171 mHandler.sendMessage(msg); 172 } 173 }; 174 175 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 176 @Override 177 public void onReceive(Context context, Intent intent) { 178 String action = intent.getAction(); 179 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 180 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 181 if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); 182 if (newName != null) { 183 storeNameAndAddress(newName, null); 184 } 185 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 186 synchronized(mReceiver) { 187 if (isBluetoothPersistedStateOn()) { 188 if (isAirplaneModeOn()) { 189 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 190 } else { 191 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 192 } 193 } 194 195 int st = BluetoothAdapter.STATE_OFF; 196 try { 197 mBluetoothLock.readLock().lock(); 198 if (mBluetooth != null) { 199 st = mBluetooth.getState(); 200 } 201 } catch (RemoteException e) { 202 Slog.e(TAG, "Unable to call getState", e); 203 } finally { 204 mBluetoothLock.readLock().unlock(); 205 } 206 Slog.d(TAG, "state" + st); 207 208 if (isAirplaneModeOn()) { 209 // Clear registered LE apps to force shut-off 210 synchronized (this) { 211 mBleAppCount = 0; 212 mBleApps.clear(); 213 } 214 if (st == BluetoothAdapter.STATE_BLE_ON) { 215 //if state is BLE_ON make sure you trigger disableBLE part 216 try { 217 mBluetoothLock.readLock().lock(); 218 if (mBluetooth != null) { 219 mBluetooth.onBrEdrDown(); 220 mEnableExternal = false; 221 } 222 } catch (RemoteException e) { 223 Slog.e(TAG,"Unable to call onBrEdrDown", e); 224 } finally { 225 mBluetoothLock.readLock().unlock(); 226 } 227 } else if (st == BluetoothAdapter.STATE_ON){ 228 // disable without persisting the setting 229 Slog.d(TAG, "Calling disable"); 230 sendDisableMsg(); 231 } 232 } else if (mEnableExternal) { 233 // enable without persisting the setting 234 Slog.d(TAG, "Calling enable"); 235 sendEnableMsg(mQuietEnableExternal); 236 } 237 } 238 } 239 } 240 }; 241 242 BluetoothManagerService(Context context) { 243 mHandler = new BluetoothHandler(IoThread.get().getLooper()); 244 245 mContext = context; 246 mBluetooth = null; 247 mBluetoothBinder = null; 248 mBluetoothGatt = null; 249 mBinding = false; 250 mUnbinding = false; 251 mEnable = false; 252 mState = BluetoothAdapter.STATE_OFF; 253 mQuietEnableExternal = false; 254 mEnableExternal = false; 255 mAddress = null; 256 mName = null; 257 mErrorRecoveryRetryCounter = 0; 258 mContentResolver = context.getContentResolver(); 259 // Observe BLE scan only mode settings change. 260 registerForBleScanModeChange(); 261 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 262 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 263 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 264 registerForAirplaneMode(filter); 265 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 266 mContext.registerReceiver(mReceiver, filter); 267 loadStoredNameAndAddress(); 268 if (isBluetoothPersistedStateOn()) { 269 mEnableExternal = true; 270 } 271 272 int sysUiUid = -1; 273 try { 274 sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", 275 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); 276 } catch (PackageManager.NameNotFoundException e) { 277 // Some platforms, such as wearables do not have a system ui. 278 Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); 279 } 280 mSystemUiUid = sysUiUid; 281 } 282 283 /** 284 * Returns true if airplane mode is currently on 285 */ 286 private final boolean isAirplaneModeOn() { 287 return Settings.Global.getInt(mContext.getContentResolver(), 288 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 289 } 290 291 /** 292 * Returns true if the Bluetooth saved state is "on" 293 */ 294 private final boolean isBluetoothPersistedStateOn() { 295 return Settings.Global.getInt(mContentResolver, 296 Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; 297 } 298 299 /** 300 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 301 */ 302 private final boolean isBluetoothPersistedStateOnBluetooth() { 303 return Settings.Global.getInt(mContentResolver, 304 Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; 305 } 306 307 /** 308 * Save the Bluetooth on/off state 309 * 310 */ 311 private void persistBluetoothSetting(int value) { 312 Settings.Global.putInt(mContext.getContentResolver(), 313 Settings.Global.BLUETOOTH_ON, 314 value); 315 } 316 317 /** 318 * Returns true if the Bluetooth Adapter's name and address is 319 * locally cached 320 * @return 321 */ 322 private boolean isNameAndAddressSet() { 323 return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 324 } 325 326 /** 327 * Retrieve the Bluetooth Adapter's name and address and save it in 328 * in the local cache 329 */ 330 private void loadStoredNameAndAddress() { 331 if (DBG) Slog.d(TAG, "Loading stored name and address"); 332 if (mContext.getResources().getBoolean 333 (com.android.internal.R.bool.config_bluetooth_address_validation) && 334 Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 335 // if the valid flag is not set, don't load the address and name 336 if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored"); 337 return; 338 } 339 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 340 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 341 if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 342 } 343 344 /** 345 * Save the Bluetooth name and address in the persistent store. 346 * Only non-null values will be saved. 347 * @param name 348 * @param address 349 */ 350 private void storeNameAndAddress(String name, String address) { 351 if (name != null) { 352 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 353 mName = name; 354 if (DBG) Slog.d(TAG,"Stored Bluetooth name: " + 355 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 356 } 357 358 if (address != null) { 359 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 360 mAddress=address; 361 if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " + 362 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 363 } 364 365 if ((name != null) && (address != null)) { 366 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 367 } 368 } 369 370 public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 371 if (callback == null) { 372 Slog.w(TAG, "Callback is null in registerAdapter"); 373 return null; 374 } 375 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 376 msg.obj = callback; 377 mHandler.sendMessage(msg); 378 379 return mBluetooth; 380 } 381 382 public void unregisterAdapter(IBluetoothManagerCallback callback) { 383 if (callback == null) { 384 Slog.w(TAG, "Callback is null in unregisterAdapter"); 385 return; 386 } 387 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 388 "Need BLUETOOTH permission"); 389 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 390 msg.obj = callback; 391 mHandler.sendMessage(msg); 392 } 393 394 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 395 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 396 "Need BLUETOOTH permission"); 397 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 398 msg.obj = callback; 399 mHandler.sendMessage(msg); 400 } 401 402 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 403 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 404 "Need BLUETOOTH permission"); 405 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 406 msg.obj = callback; 407 mHandler.sendMessage(msg); 408 } 409 410 public boolean isEnabled() { 411 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 412 (!checkIfCallerIsForegroundUser())) { 413 Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user"); 414 return false; 415 } 416 417 try { 418 mBluetoothLock.readLock().lock(); 419 if (mBluetooth != null) return mBluetooth.isEnabled(); 420 } catch (RemoteException e) { 421 Slog.e(TAG, "isEnabled()", e); 422 } finally { 423 mBluetoothLock.readLock().unlock(); 424 } 425 return false; 426 } 427 428 class ClientDeathRecipient implements IBinder.DeathRecipient { 429 public void binderDied() { 430 if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); 431 if (mBleAppCount > 0) --mBleAppCount; 432 433 if (mBleAppCount == 0) { 434 if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); 435 try { 436 mBluetoothLock.readLock().lock(); 437 if (mBluetooth != null) { 438 mBluetooth.onBrEdrDown(); 439 } 440 } catch (RemoteException e) { 441 Slog.e(TAG,"Unable to call onBrEdrDown", e); 442 } finally { 443 mBluetoothLock.readLock().unlock(); 444 } 445 } 446 } 447 } 448 449 /** Internal death rec list */ 450 Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>(); 451 452 @Override 453 public boolean isBleScanAlwaysAvailable() { 454 try { 455 return (Settings.Global.getInt(mContentResolver, 456 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; 457 } catch (SettingNotFoundException e) { 458 } 459 return false; 460 } 461 462 // Monitor change of BLE scan only mode settings. 463 private void registerForBleScanModeChange() { 464 ContentObserver contentObserver = new ContentObserver(null) { 465 @Override 466 public void onChange(boolean selfChange) { 467 if (!isBleScanAlwaysAvailable()) { 468 disableBleScanMode(); 469 clearBleApps(); 470 try { 471 mBluetoothLock.readLock().lock(); 472 if (mBluetooth != null) mBluetooth.onBrEdrDown(); 473 } catch (RemoteException e) { 474 Slog.e(TAG, "error when disabling bluetooth", e); 475 } finally { 476 mBluetoothLock.readLock().unlock(); 477 } 478 } 479 } 480 }; 481 482 mContentResolver.registerContentObserver( 483 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), 484 false, contentObserver); 485 } 486 487 // Disable ble scan only mode. 488 private void disableBleScanMode() { 489 try { 490 mBluetoothLock.writeLock().lock(); 491 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { 492 if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); 493 mEnable = false; 494 } 495 } catch (RemoteException e) { 496 Slog.e(TAG, "getState()", e); 497 } finally { 498 mBluetoothLock.writeLock().unlock(); 499 } 500 } 501 502 public int updateBleAppCount(IBinder token, boolean enable) { 503 if (enable) { 504 ClientDeathRecipient r = mBleApps.get(token); 505 if (r == null) { 506 ClientDeathRecipient deathRec = new ClientDeathRecipient(); 507 try { 508 token.linkToDeath(deathRec, 0); 509 } catch (RemoteException ex) { 510 throw new IllegalArgumentException("Wake lock is already dead."); 511 } 512 mBleApps.put(token, deathRec); 513 synchronized (this) { 514 ++mBleAppCount; 515 } 516 if (DBG) Slog.d(TAG, "Registered for death Notification"); 517 } 518 519 } else { 520 ClientDeathRecipient r = mBleApps.get(token); 521 if (r != null) { 522 // Unregister death recipient as the app goes away. 523 token.unlinkToDeath(r, 0); 524 mBleApps.remove(token); 525 synchronized (this) { 526 if (mBleAppCount > 0) --mBleAppCount; 527 } 528 if (DBG) Slog.d(TAG, "Unregistered for death Notification"); 529 } 530 } 531 if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); 532 if (mBleAppCount == 0 && mEnable) { 533 disableBleScanMode(); 534 } 535 return mBleAppCount; 536 } 537 538 // Clear all apps using BLE scan only mode. 539 private void clearBleApps() { 540 synchronized (this) { 541 mBleApps.clear(); 542 mBleAppCount = 0; 543 } 544 } 545 546 /** @hide*/ 547 public boolean isBleAppPresent() { 548 if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); 549 return (mBleAppCount > 0); 550 } 551 552 /** 553 * Action taken when GattService is turned off 554 */ 555 private void onBluetoothGattServiceUp() { 556 if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); 557 try { 558 mBluetoothLock.readLock().lock(); 559 if (isBleAppPresent() == false && mBluetooth != null 560 && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { 561 mBluetooth.onLeServiceUp(); 562 563 // waive WRITE_SECURE_SETTINGS permission check 564 long callingIdentity = Binder.clearCallingIdentity(); 565 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 566 Binder.restoreCallingIdentity(callingIdentity); 567 } 568 } catch (RemoteException e) { 569 Slog.e(TAG,"Unable to call onServiceUp", e); 570 } finally { 571 mBluetoothLock.readLock().unlock(); 572 } 573 } 574 575 /** 576 * Inform BluetoothAdapter instances that BREDR part is down 577 * and turn off all service and stack if no LE app needs it 578 */ 579 private void sendBrEdrDownCallback() { 580 if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); 581 582 if (mBluetooth == null) { 583 Slog.w(TAG, "Bluetooth handle is null"); 584 return; 585 } 586 587 if (isBleAppPresent() == false) { 588 try { 589 mBluetoothLock.readLock().lock(); 590 if (mBluetooth != null) mBluetooth.onBrEdrDown(); 591 } catch (RemoteException e) { 592 Slog.e(TAG, "Call to onBrEdrDown() failed.", e); 593 } finally { 594 mBluetoothLock.readLock().unlock(); 595 } 596 } else { 597 // Need to stay at BLE ON. Disconnect all Gatt connections 598 try { 599 mBluetoothGatt.unregAll(); 600 } catch (RemoteException e) { 601 Slog.e(TAG, "Unable to disconnect all apps.", e); 602 } 603 } 604 } 605 606 public boolean enableNoAutoConnect() 607 { 608 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 609 "Need BLUETOOTH ADMIN permission"); 610 611 if (DBG) { 612 Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 613 " mBinding = " + mBinding); 614 } 615 int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 616 617 if (callingAppId != Process.NFC_UID) { 618 throw new SecurityException("no permission to enable Bluetooth quietly"); 619 } 620 621 synchronized(mReceiver) { 622 mQuietEnableExternal = true; 623 mEnableExternal = true; 624 sendEnableMsg(true); 625 } 626 return true; 627 } 628 629 public boolean enable() { 630 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 631 (!checkIfCallerIsForegroundUser())) { 632 Slog.w(TAG,"enable(): not allowed for non-active and non system user"); 633 return false; 634 } 635 636 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 637 "Need BLUETOOTH ADMIN permission"); 638 if (DBG) { 639 Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + 640 " mBinding = " + mBinding + " mState = " + mState); 641 } 642 643 synchronized(mReceiver) { 644 mQuietEnableExternal = false; 645 mEnableExternal = true; 646 // waive WRITE_SECURE_SETTINGS permission check 647 sendEnableMsg(false); 648 } 649 if (DBG) Slog.d(TAG, "enable returning"); 650 return true; 651 } 652 653 public boolean disable(boolean persist) { 654 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 655 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 656 657 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 658 (!checkIfCallerIsForegroundUser())) { 659 Slog.w(TAG,"disable(): not allowed for non-active and non system user"); 660 return false; 661 } 662 663 if (DBG) { 664 Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + 665 " mBinding = " + mBinding); 666 } 667 668 synchronized(mReceiver) { 669 if (persist) { 670 // waive WRITE_SECURE_SETTINGS permission check 671 long callingIdentity = Binder.clearCallingIdentity(); 672 persistBluetoothSetting(BLUETOOTH_OFF); 673 Binder.restoreCallingIdentity(callingIdentity); 674 } 675 mEnableExternal = false; 676 sendDisableMsg(); 677 } 678 return true; 679 } 680 681 public void unbindAndFinish() { 682 if (DBG) { 683 Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + 684 " mBinding = " + mBinding); 685 } 686 687 try { 688 mBluetoothLock.writeLock().lock(); 689 if (mUnbinding) return; 690 mUnbinding = true; 691 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 692 if (mBluetooth != null) { 693 //Unregister callback object 694 try { 695 mBluetooth.unregisterCallback(mBluetoothCallback); 696 } catch (RemoteException re) { 697 Slog.e(TAG, "Unable to unregister BluetoothCallback",re); 698 } 699 700 if (DBG) Slog.d(TAG, "Sending unbind request."); 701 mBluetoothBinder = null; 702 mBluetooth = null; 703 //Unbind 704 mContext.unbindService(mConnection); 705 mUnbinding = false; 706 mBinding = false; 707 } else { 708 mUnbinding=false; 709 } 710 mBluetoothGatt = null; 711 } finally { 712 mBluetoothLock.writeLock().unlock(); 713 } 714 } 715 716 public IBluetoothGatt getBluetoothGatt() { 717 // sync protection 718 return mBluetoothGatt; 719 } 720 721 @Override 722 public boolean bindBluetoothProfileService(int bluetoothProfile, 723 IBluetoothProfileServiceConnection proxy) { 724 if (!mEnable) { 725 if (DBG) { 726 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 727 ", while Bluetooth was disabled"); 728 } 729 return false; 730 } 731 synchronized (mProfileServices) { 732 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 733 if (psc == null) { 734 if (DBG) { 735 Slog.d(TAG, "Creating new ProfileServiceConnections object for" 736 + " profile: " + bluetoothProfile); 737 } 738 739 if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 740 741 Intent intent = new Intent(IBluetoothHeadset.class.getName()); 742 psc = new ProfileServiceConnections(intent); 743 if (!psc.bindService()) return false; 744 745 mProfileServices.put(new Integer(bluetoothProfile), psc); 746 } 747 } 748 749 // Introducing a delay to give the client app time to prepare 750 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 751 addProxyMsg.arg1 = bluetoothProfile; 752 addProxyMsg.obj = proxy; 753 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 754 return true; 755 } 756 757 @Override 758 public void unbindBluetoothProfileService(int bluetoothProfile, 759 IBluetoothProfileServiceConnection proxy) { 760 synchronized (mProfileServices) { 761 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 762 if (psc == null) { 763 return; 764 } 765 psc.removeProxy(proxy); 766 } 767 } 768 769 private void unbindAllBluetoothProfileServices() { 770 synchronized (mProfileServices) { 771 for (Integer i : mProfileServices.keySet()) { 772 ProfileServiceConnections psc = mProfileServices.get(i); 773 try { 774 mContext.unbindService(psc); 775 } catch (IllegalArgumentException e) { 776 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 777 } 778 psc.removeAllProxies(); 779 } 780 mProfileServices.clear(); 781 } 782 } 783 784 /** 785 * Send enable message and set adapter name and address. Called when the boot phase becomes 786 * PHASE_SYSTEM_SERVICES_READY. 787 */ 788 public void handleOnBootPhase() { 789 if (DBG) Slog.d(TAG, "Bluetooth boot completed"); 790 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 791 if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); 792 sendEnableMsg(mQuietEnableExternal); 793 } else if (!isNameAndAddressSet()) { 794 if (DBG) Slog.d(TAG, "Getting adapter name and address"); 795 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 796 mHandler.sendMessage(getMsg); 797 } 798 } 799 800 /** 801 * Called when switching to a different foreground user. 802 */ 803 public void handleOnSwitchUser(int userHandle) { 804 if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); 805 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 806 } 807 808 /** 809 * Called when user is unlocked. 810 */ 811 public void handleOnUnlockUser(int userHandle) { 812 if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); 813 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 814 } 815 816 /** 817 * This class manages the clients connected to a given ProfileService 818 * and maintains the connection with that service. 819 */ 820 final private class ProfileServiceConnections implements ServiceConnection, 821 IBinder.DeathRecipient { 822 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 823 new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 824 IBinder mService; 825 ComponentName mClassName; 826 Intent mIntent; 827 boolean mInvokingProxyCallbacks = false; 828 829 ProfileServiceConnections(Intent intent) { 830 mService = null; 831 mClassName = null; 832 mIntent = intent; 833 } 834 835 private boolean bindService() { 836 if (mIntent != null && mService == null && 837 doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 838 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 839 msg.obj = this; 840 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 841 return true; 842 } 843 Slog.w(TAG, "Unable to bind with intent: " + mIntent); 844 return false; 845 } 846 847 private void addProxy(IBluetoothProfileServiceConnection proxy) { 848 mProxies.register(proxy); 849 if (mService != null) { 850 try{ 851 proxy.onServiceConnected(mClassName, mService); 852 } catch (RemoteException e) { 853 Slog.e(TAG, "Unable to connect to proxy", e); 854 } 855 } else { 856 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 857 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 858 msg.obj = this; 859 mHandler.sendMessage(msg); 860 } 861 } 862 } 863 864 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 865 if (proxy != null) { 866 if (mProxies.unregister(proxy)) { 867 try { 868 proxy.onServiceDisconnected(mClassName); 869 } catch (RemoteException e) { 870 Slog.e(TAG, "Unable to disconnect proxy", e); 871 } 872 } 873 } else { 874 Slog.w(TAG, "Trying to remove a null proxy"); 875 } 876 } 877 878 private void removeAllProxies() { 879 onServiceDisconnected(mClassName); 880 mProxies.kill(); 881 } 882 883 @Override 884 public void onServiceConnected(ComponentName className, IBinder service) { 885 // remove timeout message 886 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 887 mService = service; 888 mClassName = className; 889 try { 890 mService.linkToDeath(this, 0); 891 } catch (RemoteException e) { 892 Slog.e(TAG, "Unable to linkToDeath", e); 893 } 894 895 if (mInvokingProxyCallbacks) { 896 Slog.e(TAG, "Proxy callbacks already in progress."); 897 return; 898 } 899 mInvokingProxyCallbacks = true; 900 901 final int n = mProxies.beginBroadcast(); 902 try { 903 for (int i = 0; i < n; i++) { 904 try { 905 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 906 } catch (RemoteException e) { 907 Slog.e(TAG, "Unable to connect to proxy", e); 908 } 909 } 910 } finally { 911 mProxies.finishBroadcast(); 912 mInvokingProxyCallbacks = false; 913 } 914 } 915 916 @Override 917 public void onServiceDisconnected(ComponentName className) { 918 if (mService == null) return; 919 mService.unlinkToDeath(this, 0); 920 mService = null; 921 mClassName = null; 922 923 if (mInvokingProxyCallbacks) { 924 Slog.e(TAG, "Proxy callbacks already in progress."); 925 return; 926 } 927 mInvokingProxyCallbacks = true; 928 929 final int n = mProxies.beginBroadcast(); 930 try { 931 for (int i = 0; i < n; i++) { 932 try { 933 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 934 } catch (RemoteException e) { 935 Slog.e(TAG, "Unable to disconnect from proxy", e); 936 } 937 } 938 } finally { 939 mProxies.finishBroadcast(); 940 mInvokingProxyCallbacks = false; 941 } 942 } 943 944 @Override 945 public void binderDied() { 946 if (DBG) { 947 Slog.w(TAG, "Profile service for profile: " + mClassName 948 + " died."); 949 } 950 onServiceDisconnected(mClassName); 951 // Trigger rebind 952 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 953 msg.obj = this; 954 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 955 } 956 } 957 958 private void sendBluetoothStateCallback(boolean isUp) { 959 try { 960 int n = mStateChangeCallbacks.beginBroadcast(); 961 if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 962 for (int i=0; i <n;i++) { 963 try { 964 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 965 } catch (RemoteException e) { 966 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 967 } 968 } 969 } finally { 970 mStateChangeCallbacks.finishBroadcast(); 971 } 972 } 973 974 /** 975 * Inform BluetoothAdapter instances that Adapter service is up 976 */ 977 private void sendBluetoothServiceUpCallback() { 978 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); 979 try { 980 int n = mCallbacks.beginBroadcast(); 981 Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 982 for (int i=0; i <n;i++) { 983 try { 984 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 985 } catch (RemoteException e) { 986 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 987 } 988 } 989 } finally { 990 mCallbacks.finishBroadcast(); 991 } 992 } 993 /** 994 * Inform BluetoothAdapter instances that Adapter service is down 995 */ 996 private void sendBluetoothServiceDownCallback() { 997 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); 998 try { 999 int n = mCallbacks.beginBroadcast(); 1000 Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1001 for (int i=0; i <n;i++) { 1002 try { 1003 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1004 } catch (RemoteException e) { 1005 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1006 } 1007 } 1008 } finally { 1009 mCallbacks.finishBroadcast(); 1010 } 1011 } 1012 1013 public String getAddress() { 1014 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1015 "Need BLUETOOTH permission"); 1016 1017 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1018 (!checkIfCallerIsForegroundUser())) { 1019 Slog.w(TAG,"getAddress(): not allowed for non-active and non system user"); 1020 return null; 1021 } 1022 1023 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1024 != PackageManager.PERMISSION_GRANTED) { 1025 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1026 } 1027 1028 try { 1029 mBluetoothLock.readLock().lock(); 1030 if (mBluetooth != null) return mBluetooth.getAddress(); 1031 } catch (RemoteException e) { 1032 Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); 1033 } finally { 1034 mBluetoothLock.readLock().unlock(); 1035 } 1036 1037 // mAddress is accessed from outside. 1038 // It is alright without a lock. Here, bluetooth is off, no other thread is 1039 // changing mAddress 1040 return mAddress; 1041 } 1042 1043 public String getName() { 1044 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1045 "Need BLUETOOTH permission"); 1046 1047 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1048 (!checkIfCallerIsForegroundUser())) { 1049 Slog.w(TAG,"getName(): not allowed for non-active and non system user"); 1050 return null; 1051 } 1052 1053 try { 1054 mBluetoothLock.readLock().lock(); 1055 if (mBluetooth != null) return mBluetooth.getName(); 1056 } catch (RemoteException e) { 1057 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1058 } finally { 1059 mBluetoothLock.readLock().unlock(); 1060 } 1061 1062 // mName is accessed from outside. 1063 // It alright without a lock. Here, bluetooth is off, no other thread is 1064 // changing mName 1065 return mName; 1066 } 1067 1068 private class BluetoothServiceConnection implements ServiceConnection { 1069 public void onServiceConnected(ComponentName className, IBinder service) { 1070 if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 1071 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1072 // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 1073 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1074 msg.arg1 = SERVICE_IBLUETOOTH; 1075 // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 1076 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1077 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1078 } else { 1079 Slog.e(TAG, "Unknown service connected: " + className.getClassName()); 1080 return; 1081 } 1082 msg.obj = service; 1083 mHandler.sendMessage(msg); 1084 } 1085 1086 public void onServiceDisconnected(ComponentName className) { 1087 // Called if we unexpected disconnected. 1088 if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + 1089 className.getClassName()); 1090 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1091 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1092 msg.arg1 = SERVICE_IBLUETOOTH; 1093 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1094 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1095 } else { 1096 Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); 1097 return; 1098 } 1099 mHandler.sendMessage(msg); 1100 } 1101 } 1102 1103 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 1104 1105 private class BluetoothHandler extends Handler { 1106 boolean mGetNameAddressOnly = false; 1107 1108 public BluetoothHandler(Looper looper) { 1109 super(looper); 1110 } 1111 1112 @Override 1113 public void handleMessage(Message msg) { 1114 if (DBG) Slog.d (TAG, "Message: " + msg.what); 1115 switch (msg.what) { 1116 case MESSAGE_GET_NAME_AND_ADDRESS: 1117 if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1118 try { 1119 mBluetoothLock.writeLock().lock(); 1120 if ((mBluetooth == null) && (!mBinding)) { 1121 if (DBG) Slog.d(TAG, "Binding to service to get name and address"); 1122 mGetNameAddressOnly = true; 1123 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1124 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 1125 Intent i = new Intent(IBluetooth.class.getName()); 1126 if (!doBind(i, mConnection, 1127 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1128 UserHandle.CURRENT)) { 1129 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1130 } else { 1131 mBinding = true; 1132 } 1133 } else if (mBluetooth != null) { 1134 try { 1135 storeNameAndAddress(mBluetooth.getName(), 1136 mBluetooth.getAddress()); 1137 } catch (RemoteException re) { 1138 Slog.e(TAG, "Unable to grab names", re); 1139 } 1140 if (mGetNameAddressOnly && !mEnable) { 1141 unbindAndFinish(); 1142 } 1143 mGetNameAddressOnly = false; 1144 } 1145 } finally { 1146 mBluetoothLock.writeLock().unlock(); 1147 } 1148 break; 1149 1150 case MESSAGE_ENABLE: 1151 if (DBG) { 1152 Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 1153 } 1154 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1155 mEnable = true; 1156 1157 // Use service interface to get the exact state 1158 try { 1159 mBluetoothLock.readLock().lock(); 1160 if (mBluetooth != null) { 1161 int state = mBluetooth.getState(); 1162 if (state == BluetoothAdapter.STATE_BLE_ON) { 1163 Slog.w(TAG, "BT is in BLE_ON State"); 1164 mBluetooth.onLeServiceUp(); 1165 break; 1166 } 1167 } 1168 } catch (RemoteException e) { 1169 Slog.e(TAG, "", e); 1170 } finally { 1171 mBluetoothLock.readLock().unlock(); 1172 } 1173 1174 mQuietEnable = (msg.arg1 == 1); 1175 if (mBluetooth == null) { 1176 handleEnable(mQuietEnable); 1177 } else { 1178 // 1179 // We need to wait until transitioned to STATE_OFF and 1180 // the previous Bluetooth process has exited. The 1181 // waiting period has three components: 1182 // (a) Wait until the local state is STATE_OFF. This 1183 // is accomplished by "waitForOnOff(false, true)". 1184 // (b) Wait until the STATE_OFF state is updated to 1185 // all components. 1186 // (c) Wait until the Bluetooth process exits, and 1187 // ActivityManager detects it. 1188 // The waiting for (b) and (c) is accomplished by 1189 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 1190 // message. On slower devices, that delay needs to be 1191 // on the order of (2 * SERVICE_RESTART_TIME_MS). 1192 // 1193 waitForOnOff(false, true); 1194 Message restartMsg = mHandler.obtainMessage( 1195 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1196 mHandler.sendMessageDelayed(restartMsg, 1197 2 * SERVICE_RESTART_TIME_MS); 1198 } 1199 break; 1200 1201 case MESSAGE_DISABLE: 1202 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1203 if (mEnable && mBluetooth != null) { 1204 waitForOnOff(true, false); 1205 mEnable = false; 1206 handleDisable(); 1207 waitForOnOff(false, false); 1208 } else { 1209 mEnable = false; 1210 handleDisable(); 1211 } 1212 break; 1213 1214 case MESSAGE_REGISTER_ADAPTER: 1215 { 1216 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1217 boolean added = mCallbacks.register(callback); 1218 Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 1219 } 1220 break; 1221 case MESSAGE_UNREGISTER_ADAPTER: 1222 { 1223 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1224 boolean removed = mCallbacks.unregister(callback); 1225 Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 1226 break; 1227 } 1228 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 1229 { 1230 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1231 if (callback != null) { 1232 mStateChangeCallbacks.register(callback); 1233 } 1234 break; 1235 } 1236 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 1237 { 1238 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1239 if (callback != null) { 1240 mStateChangeCallbacks.unregister(callback); 1241 } 1242 break; 1243 } 1244 case MESSAGE_ADD_PROXY_DELAYED: 1245 { 1246 ProfileServiceConnections psc = mProfileServices.get( 1247 new Integer(msg.arg1)); 1248 if (psc == null) { 1249 break; 1250 } 1251 IBluetoothProfileServiceConnection proxy = 1252 (IBluetoothProfileServiceConnection) msg.obj; 1253 psc.addProxy(proxy); 1254 break; 1255 } 1256 case MESSAGE_BIND_PROFILE_SERVICE: 1257 { 1258 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1259 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1260 if (psc == null) { 1261 break; 1262 } 1263 psc.bindService(); 1264 break; 1265 } 1266 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1267 { 1268 if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 1269 1270 IBinder service = (IBinder) msg.obj; 1271 try { 1272 mBluetoothLock.writeLock().lock(); 1273 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1274 mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1275 onBluetoothGattServiceUp(); 1276 break; 1277 } // else must be SERVICE_IBLUETOOTH 1278 1279 //Remove timeout 1280 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1281 1282 mBinding = false; 1283 mBluetoothBinder = service; 1284 mBluetooth = IBluetooth.Stub.asInterface(service); 1285 1286 if (!isNameAndAddressSet()) { 1287 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1288 mHandler.sendMessage(getMsg); 1289 if (mGetNameAddressOnly) return; 1290 } 1291 1292 try { 1293 boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1294 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1295 if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 1296 Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1297 } 1298 } catch (RemoteException e) { 1299 Slog.e(TAG,"Unable to call configHciSnoopLog", e); 1300 } 1301 1302 //Register callback object 1303 try { 1304 mBluetooth.registerCallback(mBluetoothCallback); 1305 } catch (RemoteException re) { 1306 Slog.e(TAG, "Unable to register BluetoothCallback",re); 1307 } 1308 //Inform BluetoothAdapter instances that service is up 1309 sendBluetoothServiceUpCallback(); 1310 1311 //Do enable request 1312 try { 1313 if (mQuietEnable == false) { 1314 if(!mBluetooth.enable()) { 1315 Slog.e(TAG,"IBluetooth.enable() returned false"); 1316 } 1317 } 1318 else 1319 { 1320 if(!mBluetooth.enableNoAutoConnect()) { 1321 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1322 } 1323 } 1324 } catch (RemoteException e) { 1325 Slog.e(TAG,"Unable to call enable()",e); 1326 } 1327 } finally { 1328 mBluetoothLock.writeLock().unlock(); 1329 } 1330 1331 if (!mEnable) { 1332 waitForOnOff(true, false); 1333 handleDisable(); 1334 waitForOnOff(false, false); 1335 } 1336 break; 1337 } 1338 case MESSAGE_TIMEOUT_BIND: { 1339 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1340 mBluetoothLock.writeLock().lock(); 1341 mBinding = false; 1342 mBluetoothLock.writeLock().unlock(); 1343 1344 break; 1345 } 1346 case MESSAGE_BLUETOOTH_STATE_CHANGE: 1347 { 1348 int prevState = msg.arg1; 1349 int newState = msg.arg2; 1350 if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 1351 mState = newState; 1352 bluetoothStateChangeHandler(prevState, newState); 1353 // handle error state transition case from TURNING_ON to OFF 1354 // unbind and rebind bluetooth service and enable bluetooth 1355 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && 1356 (newState == BluetoothAdapter.STATE_OFF) && 1357 (mBluetooth != null) && mEnable) { 1358 recoverBluetoothServiceFromError(); 1359 } 1360 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1361 (newState == BluetoothAdapter.STATE_BLE_ON) && 1362 (mBluetooth != null) && mEnable) { 1363 recoverBluetoothServiceFromError(); 1364 } 1365 // If we tried to enable BT while BT was in the process of shutting down, 1366 // wait for the BT process to fully tear down and then force a restart 1367 // here. This is a bit of a hack (b/29363429). 1368 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && 1369 (newState == BluetoothAdapter.STATE_OFF)) { 1370 if (mEnable) { 1371 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); 1372 waitForOnOff(false, true); 1373 Message restartMsg = mHandler.obtainMessage( 1374 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1375 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); 1376 } 1377 } 1378 if (newState == BluetoothAdapter.STATE_ON || 1379 newState == BluetoothAdapter.STATE_BLE_ON) { 1380 // bluetooth is working, reset the counter 1381 if (mErrorRecoveryRetryCounter != 0) { 1382 Slog.w(TAG, "bluetooth is recovered from error"); 1383 mErrorRecoveryRetryCounter = 0; 1384 } 1385 } 1386 break; 1387 } 1388 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 1389 { 1390 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 1391 try { 1392 mBluetoothLock.writeLock().lock(); 1393 if (msg.arg1 == SERVICE_IBLUETOOTH) { 1394 // if service is unbinded already, do nothing and return 1395 if (mBluetooth == null) break; 1396 mBluetooth = null; 1397 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1398 mBluetoothGatt = null; 1399 break; 1400 } else { 1401 Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); 1402 break; 1403 } 1404 } finally { 1405 mBluetoothLock.writeLock().unlock(); 1406 } 1407 1408 if (mEnable) { 1409 mEnable = false; 1410 // Send a Bluetooth Restart message 1411 Message restartMsg = mHandler.obtainMessage( 1412 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1413 mHandler.sendMessageDelayed(restartMsg, 1414 SERVICE_RESTART_TIME_MS); 1415 } 1416 1417 sendBluetoothServiceDownCallback(); 1418 1419 // Send BT state broadcast to update 1420 // the BT icon correctly 1421 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1422 (mState == BluetoothAdapter.STATE_ON)) { 1423 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1424 BluetoothAdapter.STATE_TURNING_OFF); 1425 mState = BluetoothAdapter.STATE_TURNING_OFF; 1426 } 1427 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1428 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1429 BluetoothAdapter.STATE_OFF); 1430 } 1431 1432 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1433 mState = BluetoothAdapter.STATE_OFF; 1434 break; 1435 } 1436 case MESSAGE_RESTART_BLUETOOTH_SERVICE: 1437 { 1438 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 1439 +" Restart IBluetooth service"); 1440 /* Enable without persisting the setting as 1441 it doesnt change when IBluetooth 1442 service restarts */ 1443 mEnable = true; 1444 handleEnable(mQuietEnable); 1445 break; 1446 } 1447 1448 case MESSAGE_TIMEOUT_UNBIND: 1449 { 1450 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1451 mBluetoothLock.writeLock().lock(); 1452 mUnbinding = false; 1453 mBluetoothLock.writeLock().unlock(); 1454 break; 1455 } 1456 1457 case MESSAGE_USER_SWITCHED: { 1458 if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 1459 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1460 1461 /* disable and enable BT when detect a user switch */ 1462 if (mEnable && mBluetooth != null) { 1463 try { 1464 mBluetoothLock.readLock().lock(); 1465 if (mBluetooth != null) { 1466 mBluetooth.unregisterCallback(mBluetoothCallback); 1467 } 1468 } catch (RemoteException re) { 1469 Slog.e(TAG, "Unable to unregister", re); 1470 } finally { 1471 mBluetoothLock.readLock().unlock(); 1472 } 1473 1474 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1475 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 1476 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 1477 mState = BluetoothAdapter.STATE_OFF; 1478 } 1479 if (mState == BluetoothAdapter.STATE_OFF) { 1480 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 1481 mState = BluetoothAdapter.STATE_TURNING_ON; 1482 } 1483 1484 waitForOnOff(true, false); 1485 1486 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 1487 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 1488 } 1489 1490 unbindAllBluetoothProfileServices(); 1491 // disable 1492 handleDisable(); 1493 // Pbap service need receive STATE_TURNING_OFF intent to close 1494 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1495 BluetoothAdapter.STATE_TURNING_OFF); 1496 1497 boolean didDisableTimeout = !waitForOnOff(false, true); 1498 1499 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1500 BluetoothAdapter.STATE_OFF); 1501 sendBluetoothServiceDownCallback(); 1502 1503 try { 1504 mBluetoothLock.writeLock().lock(); 1505 if (mBluetooth != null) { 1506 mBluetooth = null; 1507 // Unbind 1508 mContext.unbindService(mConnection); 1509 } 1510 mBluetoothGatt = null; 1511 } finally { 1512 mBluetoothLock.writeLock().unlock(); 1513 } 1514 1515 // 1516 // If disabling Bluetooth times out, wait for an 1517 // additional amount of time to ensure the process is 1518 // shut down completely before attempting to restart. 1519 // 1520 if (didDisableTimeout) { 1521 SystemClock.sleep(3000); 1522 } else { 1523 SystemClock.sleep(100); 1524 } 1525 1526 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1527 mState = BluetoothAdapter.STATE_OFF; 1528 // enable 1529 handleEnable(mQuietEnable); 1530 } else if (mBinding || mBluetooth != null) { 1531 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 1532 userMsg.arg2 = 1 + msg.arg2; 1533 // if user is switched when service is being binding 1534 // delay sending MESSAGE_USER_SWITCHED 1535 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 1536 if (DBG) { 1537 Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 1538 } 1539 } 1540 break; 1541 } 1542 case MESSAGE_USER_UNLOCKED: { 1543 if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1544 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1545 1546 if (mEnable && !mBinding && (mBluetooth == null)) { 1547 // We should be connected, but we gave up for some 1548 // reason; maybe the Bluetooth service wasn't encryption 1549 // aware, so try binding again. 1550 if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1551 handleEnable(mQuietEnable); 1552 } 1553 } 1554 } 1555 } 1556 } 1557 1558 private void handleEnable(boolean quietMode) { 1559 mQuietEnable = quietMode; 1560 1561 try { 1562 mBluetoothLock.writeLock().lock(); 1563 if ((mBluetooth == null) && (!mBinding)) { 1564 //Start bind timeout and bind 1565 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1566 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1567 Intent i = new Intent(IBluetooth.class.getName()); 1568 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1569 UserHandle.CURRENT)) { 1570 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1571 } else { 1572 mBinding = true; 1573 } 1574 } else if (mBluetooth != null) { 1575 //Enable bluetooth 1576 try { 1577 if (!mQuietEnable) { 1578 if(!mBluetooth.enable()) { 1579 Slog.e(TAG,"IBluetooth.enable() returned false"); 1580 } 1581 } 1582 else { 1583 if(!mBluetooth.enableNoAutoConnect()) { 1584 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1585 } 1586 } 1587 } catch (RemoteException e) { 1588 Slog.e(TAG,"Unable to call enable()",e); 1589 } 1590 } 1591 } finally { 1592 mBluetoothLock.writeLock().unlock(); 1593 } 1594 } 1595 1596 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1597 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1598 intent.setComponent(comp); 1599 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1600 Slog.e(TAG, "Fail to bind to: " + intent); 1601 return false; 1602 } 1603 return true; 1604 } 1605 1606 private void handleDisable() { 1607 try { 1608 mBluetoothLock.readLock().lock(); 1609 if (mBluetooth != null) { 1610 if (DBG) Slog.d(TAG,"Sending off request."); 1611 if (!mBluetooth.disable()) { 1612 Slog.e(TAG,"IBluetooth.disable() returned false"); 1613 } 1614 } 1615 } catch (RemoteException e) { 1616 Slog.e(TAG,"Unable to call disable()",e); 1617 } finally { 1618 mBluetoothLock.readLock().unlock(); 1619 } 1620 } 1621 1622 private boolean checkIfCallerIsForegroundUser() { 1623 int foregroundUser; 1624 int callingUser = UserHandle.getCallingUserId(); 1625 int callingUid = Binder.getCallingUid(); 1626 long callingIdentity = Binder.clearCallingIdentity(); 1627 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1628 UserInfo ui = um.getProfileParent(callingUser); 1629 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 1630 int callingAppId = UserHandle.getAppId(callingUid); 1631 boolean valid = false; 1632 try { 1633 foregroundUser = ActivityManager.getCurrentUser(); 1634 valid = (callingUser == foregroundUser) || 1635 parentUser == foregroundUser || 1636 callingAppId == Process.NFC_UID || 1637 callingAppId == mSystemUiUid; 1638 if (DBG) { 1639 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 1640 + " callingUser=" + callingUser 1641 + " parentUser=" + parentUser 1642 + " foregroundUser=" + foregroundUser); 1643 } 1644 } finally { 1645 Binder.restoreCallingIdentity(callingIdentity); 1646 } 1647 return valid; 1648 } 1649 1650 private void sendBleStateChanged(int prevState, int newState) { 1651 if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); 1652 // Send broadcast message to everyone else 1653 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 1654 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1655 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1656 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1657 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1658 } 1659 1660 private void bluetoothStateChangeHandler(int prevState, int newState) { 1661 boolean isStandardBroadcast = true; 1662 if (prevState != newState) { 1663 //Notify all proxy objects first of adapter state change 1664 if (newState == BluetoothAdapter.STATE_BLE_ON || 1665 newState == BluetoothAdapter.STATE_OFF) { 1666 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 1667 && newState == BluetoothAdapter.STATE_BLE_ON); 1668 1669 if (newState == BluetoothAdapter.STATE_OFF) { 1670 // If Bluetooth is off, send service down event to proxy objects, and unbind 1671 if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); 1672 sendBluetoothServiceDownCallback(); 1673 unbindAndFinish(); 1674 sendBleStateChanged(prevState, newState); 1675 // Don't broadcast as it has already been broadcast before 1676 isStandardBroadcast = false; 1677 1678 } else if (!intermediate_off) { 1679 // connect to GattService 1680 if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); 1681 if (mBluetoothGatt != null) { 1682 if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); 1683 onBluetoothGattServiceUp(); 1684 } else { 1685 if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); 1686 if (mContext.getPackageManager().hasSystemFeature( 1687 PackageManager.FEATURE_BLUETOOTH_LE)) { 1688 Intent i = new Intent(IBluetoothGatt.class.getName()); 1689 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); 1690 } 1691 } 1692 sendBleStateChanged(prevState, newState); 1693 //Don't broadcase this as std intent 1694 isStandardBroadcast = false; 1695 1696 } else if (intermediate_off){ 1697 if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); 1698 // For LE only mode, broadcast as is 1699 sendBleStateChanged(prevState, newState); 1700 sendBluetoothStateCallback(false); // BT is OFF for general users 1701 // Broadcast as STATE_OFF 1702 newState = BluetoothAdapter.STATE_OFF; 1703 sendBrEdrDownCallback(); 1704 } 1705 } else if (newState == BluetoothAdapter.STATE_ON) { 1706 boolean isUp = (newState==BluetoothAdapter.STATE_ON); 1707 sendBluetoothStateCallback(isUp); 1708 sendBleStateChanged(prevState, newState); 1709 1710 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || 1711 newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { 1712 sendBleStateChanged(prevState, newState); 1713 isStandardBroadcast = false; 1714 1715 } else if (newState == BluetoothAdapter.STATE_TURNING_ON || 1716 newState == BluetoothAdapter.STATE_TURNING_OFF) { 1717 sendBleStateChanged(prevState, newState); 1718 } 1719 1720 if (isStandardBroadcast) { 1721 if (prevState == BluetoothAdapter.STATE_BLE_ON) { 1722 // Show prevState of BLE_ON as OFF to standard users 1723 prevState = BluetoothAdapter.STATE_OFF; 1724 } 1725 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1726 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1727 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1728 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1729 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1730 } 1731 } 1732 } 1733 1734 /** 1735 * if on is true, wait for state become ON 1736 * if off is true, wait for state become OFF 1737 * if both on and off are false, wait for state not ON 1738 */ 1739 private boolean waitForOnOff(boolean on, boolean off) { 1740 int i = 0; 1741 while (i < 10) { 1742 try { 1743 mBluetoothLock.readLock().lock(); 1744 if (mBluetooth == null) break; 1745 if (on) { 1746 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1747 } else if (off) { 1748 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1749 } else { 1750 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1751 } 1752 } catch (RemoteException e) { 1753 Slog.e(TAG, "getState()", e); 1754 break; 1755 } finally { 1756 mBluetoothLock.readLock().unlock(); 1757 } 1758 if (on || off) { 1759 SystemClock.sleep(300); 1760 } else { 1761 SystemClock.sleep(50); 1762 } 1763 i++; 1764 } 1765 Slog.e(TAG,"waitForOnOff time out"); 1766 return false; 1767 } 1768 1769 private void sendDisableMsg() { 1770 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1771 } 1772 1773 private void sendEnableMsg(boolean quietMode) { 1774 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1775 quietMode ? 1 : 0, 0)); 1776 } 1777 1778 private void recoverBluetoothServiceFromError() { 1779 Slog.e(TAG,"recoverBluetoothServiceFromError"); 1780 try { 1781 mBluetoothLock.readLock().lock(); 1782 if (mBluetooth != null) { 1783 //Unregister callback object 1784 mBluetooth.unregisterCallback(mBluetoothCallback); 1785 } 1786 } catch (RemoteException re) { 1787 Slog.e(TAG, "Unable to unregister", re); 1788 } finally { 1789 mBluetoothLock.readLock().unlock(); 1790 } 1791 1792 SystemClock.sleep(500); 1793 1794 // disable 1795 handleDisable(); 1796 1797 waitForOnOff(false, true); 1798 1799 sendBluetoothServiceDownCallback(); 1800 1801 try { 1802 mBluetoothLock.writeLock().lock(); 1803 if (mBluetooth != null) { 1804 mBluetooth = null; 1805 // Unbind 1806 mContext.unbindService(mConnection); 1807 } 1808 mBluetoothGatt = null; 1809 } finally { 1810 mBluetoothLock.writeLock().unlock(); 1811 } 1812 1813 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1814 mState = BluetoothAdapter.STATE_OFF; 1815 1816 mEnable = false; 1817 1818 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1819 // Send a Bluetooth Restart message to reenable bluetooth 1820 Message restartMsg = mHandler.obtainMessage( 1821 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1822 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1823 } else { 1824 // todo: notify user to power down and power up phone to make bluetooth work. 1825 } 1826 } 1827 1828 @Override 1829 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1830 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 1831 String errorMsg = null; 1832 if (mBluetoothBinder == null) { 1833 errorMsg = "Bluetooth Service not connected"; 1834 } else { 1835 try { 1836 mBluetoothBinder.dump(fd, args); 1837 } catch (RemoteException re) { 1838 errorMsg = "RemoteException while calling Bluetooth Service"; 1839 } 1840 } 1841 if (errorMsg != null) { 1842 // Silently return if we are extracting metrics in Protobuf format 1843 if ((args.length > 0) && args[0].startsWith("--proto")) 1844 return; 1845 writer.println(errorMsg); 1846 } 1847 } 1848} 1849