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 17 package com.android.server; 18 19 import android.Manifest; 20 import android.app.ActivityManager; 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothProfile; 23 import android.bluetooth.IBluetooth; 24 import android.bluetooth.IBluetoothCallback; 25 import android.bluetooth.IBluetoothGatt; 26 import android.bluetooth.IBluetoothHeadset; 27 import android.bluetooth.IBluetoothManager; 28 import android.bluetooth.IBluetoothManagerCallback; 29 import android.bluetooth.IBluetoothProfileServiceConnection; 30 import android.bluetooth.IBluetoothStateChangeCallback; 31 import android.content.BroadcastReceiver; 32 import android.content.ComponentName; 33 import android.content.ContentResolver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.ServiceConnection; 38 import android.content.pm.PackageManager; 39 import android.content.pm.UserInfo; 40 import android.database.ContentObserver; 41 import android.os.Binder; 42 import android.os.Handler; 43 import android.os.IBinder; 44 import android.os.Looper; 45 import android.os.Message; 46 import android.os.Process; 47 import android.os.RemoteCallbackList; 48 import android.os.RemoteException; 49 import android.os.SystemClock; 50 import android.os.UserHandle; 51 import android.os.UserManager; 52 import android.provider.Settings; 53 import android.provider.Settings.SettingNotFoundException; 54 import android.util.Slog; 55 import java.util.concurrent.locks.ReentrantReadWriteLock; 56 57 import java.io.FileDescriptor; 58 import java.io.PrintWriter; 59 import java.util.HashMap; 60 import java.util.Map; 61 62 class 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 public int getState() { 429 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 430 (!checkIfCallerIsForegroundUser())) { 431 Slog.w(TAG, "getState(): not allowed for non-active and non system user"); 432 return BluetoothAdapter.STATE_OFF; 433 } 434 435 try { 436 mBluetoothLock.readLock().lock(); 437 if (mBluetooth != null) return mBluetooth.getState(); 438 } catch (RemoteException e) { 439 Slog.e(TAG, "getState()", e); 440 } finally { 441 mBluetoothLock.readLock().unlock(); 442 } 443 return BluetoothAdapter.STATE_OFF; 444 } 445 446 class ClientDeathRecipient implements IBinder.DeathRecipient { 447 public void binderDied() { 448 if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); 449 if (mBleAppCount > 0) --mBleAppCount; 450 451 if (mBleAppCount == 0) { 452 if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); 453 try { 454 mBluetoothLock.readLock().lock(); 455 if (mBluetooth != null) { 456 mBluetooth.onBrEdrDown(); 457 } 458 } catch (RemoteException e) { 459 Slog.e(TAG,"Unable to call onBrEdrDown", e); 460 } finally { 461 mBluetoothLock.readLock().unlock(); 462 } 463 } 464 } 465 } 466 467 /** Internal death rec list */ 468 Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>(); 469 470 @Override 471 public boolean isBleScanAlwaysAvailable() { 472 try { 473 return (Settings.Global.getInt(mContentResolver, 474 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; 475 } catch (SettingNotFoundException e) { 476 } 477 return false; 478 } 479 480 // Monitor change of BLE scan only mode settings. 481 private void registerForBleScanModeChange() { 482 ContentObserver contentObserver = new ContentObserver(null) { 483 @Override 484 public void onChange(boolean selfChange) { 485 if (!isBleScanAlwaysAvailable()) { 486 disableBleScanMode(); 487 clearBleApps(); 488 try { 489 mBluetoothLock.readLock().lock(); 490 if (mBluetooth != null) mBluetooth.onBrEdrDown(); 491 } catch (RemoteException e) { 492 Slog.e(TAG, "error when disabling bluetooth", e); 493 } finally { 494 mBluetoothLock.readLock().unlock(); 495 } 496 } 497 } 498 }; 499 500 mContentResolver.registerContentObserver( 501 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), 502 false, contentObserver); 503 } 504 505 // Disable ble scan only mode. 506 private void disableBleScanMode() { 507 try { 508 mBluetoothLock.writeLock().lock(); 509 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { 510 if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); 511 mEnable = false; 512 } 513 } catch (RemoteException e) { 514 Slog.e(TAG, "getState()", e); 515 } finally { 516 mBluetoothLock.writeLock().unlock(); 517 } 518 } 519 520 public int updateBleAppCount(IBinder token, boolean enable) { 521 if (enable) { 522 ClientDeathRecipient r = mBleApps.get(token); 523 if (r == null) { 524 ClientDeathRecipient deathRec = new ClientDeathRecipient(); 525 try { 526 token.linkToDeath(deathRec, 0); 527 } catch (RemoteException ex) { 528 throw new IllegalArgumentException("Wake lock is already dead."); 529 } 530 mBleApps.put(token, deathRec); 531 synchronized (this) { 532 ++mBleAppCount; 533 } 534 if (DBG) Slog.d(TAG, "Registered for death Notification"); 535 } 536 537 } else { 538 ClientDeathRecipient r = mBleApps.get(token); 539 if (r != null) { 540 // Unregister death recipient as the app goes away. 541 token.unlinkToDeath(r, 0); 542 mBleApps.remove(token); 543 synchronized (this) { 544 if (mBleAppCount > 0) --mBleAppCount; 545 } 546 if (DBG) Slog.d(TAG, "Unregistered for death Notification"); 547 } 548 } 549 if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); 550 if (mBleAppCount == 0 && mEnable) { 551 disableBleScanMode(); 552 } 553 return mBleAppCount; 554 } 555 556 // Clear all apps using BLE scan only mode. 557 private void clearBleApps() { 558 synchronized (this) { 559 mBleApps.clear(); 560 mBleAppCount = 0; 561 } 562 } 563 564 /** @hide*/ 565 public boolean isBleAppPresent() { 566 if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); 567 return (mBleAppCount > 0); 568 } 569 570 /** 571 * Action taken when GattService is turned off 572 */ 573 private void onBluetoothGattServiceUp() { 574 if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); 575 try { 576 mBluetoothLock.readLock().lock(); 577 if (isBleAppPresent() == false && mBluetooth != null 578 && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { 579 mBluetooth.onLeServiceUp(); 580 581 // waive WRITE_SECURE_SETTINGS permission check 582 long callingIdentity = Binder.clearCallingIdentity(); 583 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 584 Binder.restoreCallingIdentity(callingIdentity); 585 } 586 } catch (RemoteException e) { 587 Slog.e(TAG,"Unable to call onServiceUp", e); 588 } finally { 589 mBluetoothLock.readLock().unlock(); 590 } 591 } 592 593 /** 594 * Inform BluetoothAdapter instances that BREDR part is down 595 * and turn off all service and stack if no LE app needs it 596 */ 597 private void sendBrEdrDownCallback() { 598 if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); 599 600 if (mBluetooth == null) { 601 Slog.w(TAG, "Bluetooth handle is null"); 602 return; 603 } 604 605 if (isBleAppPresent() == false) { 606 try { 607 mBluetoothLock.readLock().lock(); 608 if (mBluetooth != null) mBluetooth.onBrEdrDown(); 609 } catch (RemoteException e) { 610 Slog.e(TAG, "Call to onBrEdrDown() failed.", e); 611 } finally { 612 mBluetoothLock.readLock().unlock(); 613 } 614 } else { 615 // Need to stay at BLE ON. Disconnect all Gatt connections 616 try { 617 mBluetoothGatt.unregAll(); 618 } catch (RemoteException e) { 619 Slog.e(TAG, "Unable to disconnect all apps.", e); 620 } 621 } 622 } 623 624 public boolean enableNoAutoConnect() 625 { 626 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 627 "Need BLUETOOTH ADMIN permission"); 628 629 if (DBG) { 630 Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 631 " mBinding = " + mBinding); 632 } 633 int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 634 635 if (callingAppId != Process.NFC_UID) { 636 throw new SecurityException("no permission to enable Bluetooth quietly"); 637 } 638 639 synchronized(mReceiver) { 640 mQuietEnableExternal = true; 641 mEnableExternal = true; 642 sendEnableMsg(true); 643 } 644 return true; 645 } 646 647 public boolean enable() { 648 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 649 (!checkIfCallerIsForegroundUser())) { 650 Slog.w(TAG,"enable(): not allowed for non-active and non system user"); 651 return false; 652 } 653 654 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 655 "Need BLUETOOTH ADMIN permission"); 656 if (DBG) { 657 Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + 658 " mBinding = " + mBinding + " mState = " + mState); 659 } 660 661 synchronized(mReceiver) { 662 mQuietEnableExternal = false; 663 mEnableExternal = true; 664 // waive WRITE_SECURE_SETTINGS permission check 665 sendEnableMsg(false); 666 } 667 if (DBG) Slog.d(TAG, "enable returning"); 668 return true; 669 } 670 671 public boolean disable(boolean persist) { 672 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 673 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 674 675 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 676 (!checkIfCallerIsForegroundUser())) { 677 Slog.w(TAG,"disable(): not allowed for non-active and non system user"); 678 return false; 679 } 680 681 if (DBG) { 682 Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + 683 " mBinding = " + mBinding); 684 } 685 686 synchronized(mReceiver) { 687 if (persist) { 688 // waive WRITE_SECURE_SETTINGS permission check 689 long callingIdentity = Binder.clearCallingIdentity(); 690 persistBluetoothSetting(BLUETOOTH_OFF); 691 Binder.restoreCallingIdentity(callingIdentity); 692 } 693 mEnableExternal = false; 694 sendDisableMsg(); 695 } 696 return true; 697 } 698 699 public void unbindAndFinish() { 700 if (DBG) { 701 Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + 702 " mBinding = " + mBinding); 703 } 704 705 try { 706 mBluetoothLock.writeLock().lock(); 707 if (mUnbinding) return; 708 mUnbinding = true; 709 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 710 if (mBluetooth != null) { 711 //Unregister callback object 712 try { 713 mBluetooth.unregisterCallback(mBluetoothCallback); 714 } catch (RemoteException re) { 715 Slog.e(TAG, "Unable to unregister BluetoothCallback",re); 716 } 717 718 if (DBG) Slog.d(TAG, "Sending unbind request."); 719 mBluetoothBinder = null; 720 mBluetooth = null; 721 //Unbind 722 mContext.unbindService(mConnection); 723 mUnbinding = false; 724 mBinding = false; 725 } else { 726 mUnbinding=false; 727 } 728 mBluetoothGatt = null; 729 } finally { 730 mBluetoothLock.writeLock().unlock(); 731 } 732 } 733 734 public IBluetoothGatt getBluetoothGatt() { 735 // sync protection 736 return mBluetoothGatt; 737 } 738 739 @Override 740 public boolean bindBluetoothProfileService(int bluetoothProfile, 741 IBluetoothProfileServiceConnection proxy) { 742 if (!mEnable) { 743 if (DBG) { 744 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 745 ", while Bluetooth was disabled"); 746 } 747 return false; 748 } 749 synchronized (mProfileServices) { 750 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 751 if (psc == null) { 752 if (DBG) { 753 Slog.d(TAG, "Creating new ProfileServiceConnections object for" 754 + " profile: " + bluetoothProfile); 755 } 756 757 if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 758 759 Intent intent = new Intent(IBluetoothHeadset.class.getName()); 760 psc = new ProfileServiceConnections(intent); 761 if (!psc.bindService()) return false; 762 763 mProfileServices.put(new Integer(bluetoothProfile), psc); 764 } 765 } 766 767 // Introducing a delay to give the client app time to prepare 768 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 769 addProxyMsg.arg1 = bluetoothProfile; 770 addProxyMsg.obj = proxy; 771 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 772 return true; 773 } 774 775 @Override 776 public void unbindBluetoothProfileService(int bluetoothProfile, 777 IBluetoothProfileServiceConnection proxy) { 778 synchronized (mProfileServices) { 779 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 780 if (psc == null) { 781 return; 782 } 783 psc.removeProxy(proxy); 784 } 785 } 786 787 private void unbindAllBluetoothProfileServices() { 788 synchronized (mProfileServices) { 789 for (Integer i : mProfileServices.keySet()) { 790 ProfileServiceConnections psc = mProfileServices.get(i); 791 try { 792 mContext.unbindService(psc); 793 } catch (IllegalArgumentException e) { 794 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 795 } 796 psc.removeAllProxies(); 797 } 798 mProfileServices.clear(); 799 } 800 } 801 802 /** 803 * Send enable message and set adapter name and address. Called when the boot phase becomes 804 * PHASE_SYSTEM_SERVICES_READY. 805 */ 806 public void handleOnBootPhase() { 807 if (DBG) Slog.d(TAG, "Bluetooth boot completed"); 808 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 809 if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); 810 sendEnableMsg(mQuietEnableExternal); 811 } else if (!isNameAndAddressSet()) { 812 if (DBG) Slog.d(TAG, "Getting adapter name and address"); 813 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 814 mHandler.sendMessage(getMsg); 815 } 816 } 817 818 /** 819 * Called when switching to a different foreground user. 820 */ 821 public void handleOnSwitchUser(int userHandle) { 822 if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); 823 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 824 } 825 826 /** 827 * Called when user is unlocked. 828 */ 829 public void handleOnUnlockUser(int userHandle) { 830 if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); 831 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 832 } 833 834 /** 835 * This class manages the clients connected to a given ProfileService 836 * and maintains the connection with that service. 837 */ 838 final private class ProfileServiceConnections implements ServiceConnection, 839 IBinder.DeathRecipient { 840 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 841 new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 842 IBinder mService; 843 ComponentName mClassName; 844 Intent mIntent; 845 boolean mInvokingProxyCallbacks = false; 846 847 ProfileServiceConnections(Intent intent) { 848 mService = null; 849 mClassName = null; 850 mIntent = intent; 851 } 852 853 private boolean bindService() { 854 if (mIntent != null && mService == null && 855 doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 856 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 857 msg.obj = this; 858 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 859 return true; 860 } 861 Slog.w(TAG, "Unable to bind with intent: " + mIntent); 862 return false; 863 } 864 865 private void addProxy(IBluetoothProfileServiceConnection proxy) { 866 mProxies.register(proxy); 867 if (mService != null) { 868 try{ 869 proxy.onServiceConnected(mClassName, mService); 870 } catch (RemoteException e) { 871 Slog.e(TAG, "Unable to connect to proxy", e); 872 } 873 } else { 874 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 875 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 876 msg.obj = this; 877 mHandler.sendMessage(msg); 878 } 879 } 880 } 881 882 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 883 if (proxy != null) { 884 if (mProxies.unregister(proxy)) { 885 try { 886 proxy.onServiceDisconnected(mClassName); 887 } catch (RemoteException e) { 888 Slog.e(TAG, "Unable to disconnect proxy", e); 889 } 890 } 891 } else { 892 Slog.w(TAG, "Trying to remove a null proxy"); 893 } 894 } 895 896 private void removeAllProxies() { 897 onServiceDisconnected(mClassName); 898 mProxies.kill(); 899 } 900 901 @Override 902 public void onServiceConnected(ComponentName className, IBinder service) { 903 // remove timeout message 904 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 905 mService = service; 906 mClassName = className; 907 try { 908 mService.linkToDeath(this, 0); 909 } catch (RemoteException e) { 910 Slog.e(TAG, "Unable to linkToDeath", e); 911 } 912 913 if (mInvokingProxyCallbacks) { 914 Slog.e(TAG, "Proxy callbacks already in progress."); 915 return; 916 } 917 mInvokingProxyCallbacks = true; 918 919 final int n = mProxies.beginBroadcast(); 920 try { 921 for (int i = 0; i < n; i++) { 922 try { 923 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 924 } catch (RemoteException e) { 925 Slog.e(TAG, "Unable to connect to proxy", e); 926 } 927 } 928 } finally { 929 mProxies.finishBroadcast(); 930 mInvokingProxyCallbacks = false; 931 } 932 } 933 934 @Override 935 public void onServiceDisconnected(ComponentName className) { 936 if (mService == null) return; 937 mService.unlinkToDeath(this, 0); 938 mService = null; 939 mClassName = null; 940 941 if (mInvokingProxyCallbacks) { 942 Slog.e(TAG, "Proxy callbacks already in progress."); 943 return; 944 } 945 mInvokingProxyCallbacks = true; 946 947 final int n = mProxies.beginBroadcast(); 948 try { 949 for (int i = 0; i < n; i++) { 950 try { 951 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 952 } catch (RemoteException e) { 953 Slog.e(TAG, "Unable to disconnect from proxy", e); 954 } 955 } 956 } finally { 957 mProxies.finishBroadcast(); 958 mInvokingProxyCallbacks = false; 959 } 960 } 961 962 @Override 963 public void binderDied() { 964 if (DBG) { 965 Slog.w(TAG, "Profile service for profile: " + mClassName 966 + " died."); 967 } 968 onServiceDisconnected(mClassName); 969 // Trigger rebind 970 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 971 msg.obj = this; 972 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 973 } 974 } 975 976 private void sendBluetoothStateCallback(boolean isUp) { 977 try { 978 int n = mStateChangeCallbacks.beginBroadcast(); 979 if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 980 for (int i=0; i <n;i++) { 981 try { 982 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 983 } catch (RemoteException e) { 984 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 985 } 986 } 987 } finally { 988 mStateChangeCallbacks.finishBroadcast(); 989 } 990 } 991 992 /** 993 * Inform BluetoothAdapter instances that Adapter service is up 994 */ 995 private void sendBluetoothServiceUpCallback() { 996 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); 997 try { 998 int n = mCallbacks.beginBroadcast(); 999 Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 1000 for (int i=0; i <n;i++) { 1001 try { 1002 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 1003 } catch (RemoteException e) { 1004 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 1005 } 1006 } 1007 } finally { 1008 mCallbacks.finishBroadcast(); 1009 } 1010 } 1011 /** 1012 * Inform BluetoothAdapter instances that Adapter service is down 1013 */ 1014 private void sendBluetoothServiceDownCallback() { 1015 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); 1016 try { 1017 int n = mCallbacks.beginBroadcast(); 1018 Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1019 for (int i=0; i <n;i++) { 1020 try { 1021 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1022 } catch (RemoteException e) { 1023 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1024 } 1025 } 1026 } finally { 1027 mCallbacks.finishBroadcast(); 1028 } 1029 } 1030 1031 public String getAddress() { 1032 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1033 "Need BLUETOOTH permission"); 1034 1035 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1036 (!checkIfCallerIsForegroundUser())) { 1037 Slog.w(TAG,"getAddress(): not allowed for non-active and non system user"); 1038 return null; 1039 } 1040 1041 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1042 != PackageManager.PERMISSION_GRANTED) { 1043 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1044 } 1045 1046 try { 1047 mBluetoothLock.readLock().lock(); 1048 if (mBluetooth != null) return mBluetooth.getAddress(); 1049 } catch (RemoteException e) { 1050 Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); 1051 } finally { 1052 mBluetoothLock.readLock().unlock(); 1053 } 1054 1055 // mAddress is accessed from outside. 1056 // It is alright without a lock. Here, bluetooth is off, no other thread is 1057 // changing mAddress 1058 return mAddress; 1059 } 1060 1061 public String getName() { 1062 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1063 "Need BLUETOOTH permission"); 1064 1065 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1066 (!checkIfCallerIsForegroundUser())) { 1067 Slog.w(TAG,"getName(): not allowed for non-active and non system user"); 1068 return null; 1069 } 1070 1071 try { 1072 mBluetoothLock.readLock().lock(); 1073 if (mBluetooth != null) return mBluetooth.getName(); 1074 } catch (RemoteException e) { 1075 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1076 } finally { 1077 mBluetoothLock.readLock().unlock(); 1078 } 1079 1080 // mName is accessed from outside. 1081 // It alright without a lock. Here, bluetooth is off, no other thread is 1082 // changing mName 1083 return mName; 1084 } 1085 1086 private class BluetoothServiceConnection implements ServiceConnection { 1087 public void onServiceConnected(ComponentName className, IBinder service) { 1088 if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 1089 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1090 // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 1091 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1092 msg.arg1 = SERVICE_IBLUETOOTH; 1093 // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 1094 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1095 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1096 } else { 1097 Slog.e(TAG, "Unknown service connected: " + className.getClassName()); 1098 return; 1099 } 1100 msg.obj = service; 1101 mHandler.sendMessage(msg); 1102 } 1103 1104 public void onServiceDisconnected(ComponentName className) { 1105 // Called if we unexpected disconnected. 1106 if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + 1107 className.getClassName()); 1108 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1109 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1110 msg.arg1 = SERVICE_IBLUETOOTH; 1111 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1112 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1113 } else { 1114 Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); 1115 return; 1116 } 1117 mHandler.sendMessage(msg); 1118 } 1119 } 1120 1121 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 1122 1123 private class BluetoothHandler extends Handler { 1124 boolean mGetNameAddressOnly = false; 1125 1126 public BluetoothHandler(Looper looper) { 1127 super(looper); 1128 } 1129 1130 @Override 1131 public void handleMessage(Message msg) { 1132 if (DBG) Slog.d (TAG, "Message: " + msg.what); 1133 switch (msg.what) { 1134 case MESSAGE_GET_NAME_AND_ADDRESS: 1135 if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1136 try { 1137 mBluetoothLock.writeLock().lock(); 1138 if ((mBluetooth == null) && (!mBinding)) { 1139 if (DBG) Slog.d(TAG, "Binding to service to get name and address"); 1140 mGetNameAddressOnly = true; 1141 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1142 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 1143 Intent i = new Intent(IBluetooth.class.getName()); 1144 if (!doBind(i, mConnection, 1145 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1146 UserHandle.CURRENT)) { 1147 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1148 } else { 1149 mBinding = true; 1150 } 1151 } else if (mBluetooth != null) { 1152 try { 1153 storeNameAndAddress(mBluetooth.getName(), 1154 mBluetooth.getAddress()); 1155 } catch (RemoteException re) { 1156 Slog.e(TAG, "Unable to grab names", re); 1157 } 1158 if (mGetNameAddressOnly && !mEnable) { 1159 unbindAndFinish(); 1160 } 1161 mGetNameAddressOnly = false; 1162 } 1163 } finally { 1164 mBluetoothLock.writeLock().unlock(); 1165 } 1166 break; 1167 1168 case MESSAGE_ENABLE: 1169 if (DBG) { 1170 Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 1171 } 1172 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1173 mEnable = true; 1174 1175 // Use service interface to get the exact state 1176 try { 1177 mBluetoothLock.readLock().lock(); 1178 if (mBluetooth != null) { 1179 int state = mBluetooth.getState(); 1180 if (state == BluetoothAdapter.STATE_BLE_ON) { 1181 Slog.w(TAG, "BT is in BLE_ON State"); 1182 mBluetooth.onLeServiceUp(); 1183 break; 1184 } 1185 } 1186 } catch (RemoteException e) { 1187 Slog.e(TAG, "", e); 1188 } finally { 1189 mBluetoothLock.readLock().unlock(); 1190 } 1191 1192 mQuietEnable = (msg.arg1 == 1); 1193 if (mBluetooth == null) { 1194 handleEnable(mQuietEnable); 1195 } else { 1196 // 1197 // We need to wait until transitioned to STATE_OFF and 1198 // the previous Bluetooth process has exited. The 1199 // waiting period has three components: 1200 // (a) Wait until the local state is STATE_OFF. This 1201 // is accomplished by "waitForOnOff(false, true)". 1202 // (b) Wait until the STATE_OFF state is updated to 1203 // all components. 1204 // (c) Wait until the Bluetooth process exits, and 1205 // ActivityManager detects it. 1206 // The waiting for (b) and (c) is accomplished by 1207 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 1208 // message. On slower devices, that delay needs to be 1209 // on the order of (2 * SERVICE_RESTART_TIME_MS). 1210 // 1211 waitForOnOff(false, true); 1212 Message restartMsg = mHandler.obtainMessage( 1213 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1214 mHandler.sendMessageDelayed(restartMsg, 1215 2 * SERVICE_RESTART_TIME_MS); 1216 } 1217 break; 1218 1219 case MESSAGE_DISABLE: 1220 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1221 if (mEnable && mBluetooth != null) { 1222 waitForOnOff(true, false); 1223 mEnable = false; 1224 handleDisable(); 1225 waitForOnOff(false, false); 1226 } else { 1227 mEnable = false; 1228 handleDisable(); 1229 } 1230 break; 1231 1232 case MESSAGE_REGISTER_ADAPTER: 1233 { 1234 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1235 boolean added = mCallbacks.register(callback); 1236 Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 1237 } 1238 break; 1239 case MESSAGE_UNREGISTER_ADAPTER: 1240 { 1241 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1242 boolean removed = mCallbacks.unregister(callback); 1243 Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 1244 break; 1245 } 1246 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 1247 { 1248 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1249 if (callback != null) { 1250 mStateChangeCallbacks.register(callback); 1251 } 1252 break; 1253 } 1254 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 1255 { 1256 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1257 if (callback != null) { 1258 mStateChangeCallbacks.unregister(callback); 1259 } 1260 break; 1261 } 1262 case MESSAGE_ADD_PROXY_DELAYED: 1263 { 1264 ProfileServiceConnections psc = mProfileServices.get( 1265 new Integer(msg.arg1)); 1266 if (psc == null) { 1267 break; 1268 } 1269 IBluetoothProfileServiceConnection proxy = 1270 (IBluetoothProfileServiceConnection) msg.obj; 1271 psc.addProxy(proxy); 1272 break; 1273 } 1274 case MESSAGE_BIND_PROFILE_SERVICE: 1275 { 1276 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1277 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1278 if (psc == null) { 1279 break; 1280 } 1281 psc.bindService(); 1282 break; 1283 } 1284 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1285 { 1286 if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 1287 1288 IBinder service = (IBinder) msg.obj; 1289 try { 1290 mBluetoothLock.writeLock().lock(); 1291 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1292 mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1293 onBluetoothGattServiceUp(); 1294 break; 1295 } // else must be SERVICE_IBLUETOOTH 1296 1297 //Remove timeout 1298 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1299 1300 mBinding = false; 1301 mBluetoothBinder = service; 1302 mBluetooth = IBluetooth.Stub.asInterface(service); 1303 1304 if (!isNameAndAddressSet()) { 1305 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1306 mHandler.sendMessage(getMsg); 1307 if (mGetNameAddressOnly) return; 1308 } 1309 1310 try { 1311 boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1312 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1313 if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 1314 Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1315 } 1316 } catch (RemoteException e) { 1317 Slog.e(TAG,"Unable to call configHciSnoopLog", e); 1318 } 1319 1320 //Register callback object 1321 try { 1322 mBluetooth.registerCallback(mBluetoothCallback); 1323 } catch (RemoteException re) { 1324 Slog.e(TAG, "Unable to register BluetoothCallback",re); 1325 } 1326 //Inform BluetoothAdapter instances that service is up 1327 sendBluetoothServiceUpCallback(); 1328 1329 //Do enable request 1330 try { 1331 if (mQuietEnable == false) { 1332 if(!mBluetooth.enable()) { 1333 Slog.e(TAG,"IBluetooth.enable() returned false"); 1334 } 1335 } 1336 else 1337 { 1338 if(!mBluetooth.enableNoAutoConnect()) { 1339 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1340 } 1341 } 1342 } catch (RemoteException e) { 1343 Slog.e(TAG,"Unable to call enable()",e); 1344 } 1345 } finally { 1346 mBluetoothLock.writeLock().unlock(); 1347 } 1348 1349 if (!mEnable) { 1350 waitForOnOff(true, false); 1351 handleDisable(); 1352 waitForOnOff(false, false); 1353 } 1354 break; 1355 } 1356 case MESSAGE_TIMEOUT_BIND: { 1357 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1358 mBluetoothLock.writeLock().lock(); 1359 mBinding = false; 1360 mBluetoothLock.writeLock().unlock(); 1361 1362 break; 1363 } 1364 case MESSAGE_BLUETOOTH_STATE_CHANGE: 1365 { 1366 int prevState = msg.arg1; 1367 int newState = msg.arg2; 1368 if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 1369 mState = newState; 1370 bluetoothStateChangeHandler(prevState, newState); 1371 // handle error state transition case from TURNING_ON to OFF 1372 // unbind and rebind bluetooth service and enable bluetooth 1373 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && 1374 (newState == BluetoothAdapter.STATE_OFF) && 1375 (mBluetooth != null) && mEnable) { 1376 recoverBluetoothServiceFromError(); 1377 } 1378 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1379 (newState == BluetoothAdapter.STATE_BLE_ON) && 1380 (mBluetooth != null) && mEnable) { 1381 recoverBluetoothServiceFromError(); 1382 } 1383 // If we tried to enable BT while BT was in the process of shutting down, 1384 // wait for the BT process to fully tear down and then force a restart 1385 // here. This is a bit of a hack (b/29363429). 1386 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && 1387 (newState == BluetoothAdapter.STATE_OFF)) { 1388 if (mEnable) { 1389 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); 1390 waitForOnOff(false, true); 1391 Message restartMsg = mHandler.obtainMessage( 1392 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1393 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); 1394 } 1395 } 1396 if (newState == BluetoothAdapter.STATE_ON || 1397 newState == BluetoothAdapter.STATE_BLE_ON) { 1398 // bluetooth is working, reset the counter 1399 if (mErrorRecoveryRetryCounter != 0) { 1400 Slog.w(TAG, "bluetooth is recovered from error"); 1401 mErrorRecoveryRetryCounter = 0; 1402 } 1403 } 1404 break; 1405 } 1406 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 1407 { 1408 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 1409 try { 1410 mBluetoothLock.writeLock().lock(); 1411 if (msg.arg1 == SERVICE_IBLUETOOTH) { 1412 // if service is unbinded already, do nothing and return 1413 if (mBluetooth == null) break; 1414 mBluetooth = null; 1415 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1416 mBluetoothGatt = null; 1417 break; 1418 } else { 1419 Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); 1420 break; 1421 } 1422 } finally { 1423 mBluetoothLock.writeLock().unlock(); 1424 } 1425 1426 if (mEnable) { 1427 mEnable = false; 1428 // Send a Bluetooth Restart message 1429 Message restartMsg = mHandler.obtainMessage( 1430 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1431 mHandler.sendMessageDelayed(restartMsg, 1432 SERVICE_RESTART_TIME_MS); 1433 } 1434 1435 sendBluetoothServiceDownCallback(); 1436 1437 // Send BT state broadcast to update 1438 // the BT icon correctly 1439 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1440 (mState == BluetoothAdapter.STATE_ON)) { 1441 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1442 BluetoothAdapter.STATE_TURNING_OFF); 1443 mState = BluetoothAdapter.STATE_TURNING_OFF; 1444 } 1445 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1446 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1447 BluetoothAdapter.STATE_OFF); 1448 } 1449 1450 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1451 mState = BluetoothAdapter.STATE_OFF; 1452 break; 1453 } 1454 case MESSAGE_RESTART_BLUETOOTH_SERVICE: 1455 { 1456 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 1457 +" Restart IBluetooth service"); 1458 /* Enable without persisting the setting as 1459 it doesnt change when IBluetooth 1460 service restarts */ 1461 mEnable = true; 1462 handleEnable(mQuietEnable); 1463 break; 1464 } 1465 1466 case MESSAGE_TIMEOUT_UNBIND: 1467 { 1468 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1469 mBluetoothLock.writeLock().lock(); 1470 mUnbinding = false; 1471 mBluetoothLock.writeLock().unlock(); 1472 break; 1473 } 1474 1475 case MESSAGE_USER_SWITCHED: { 1476 if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 1477 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1478 1479 /* disable and enable BT when detect a user switch */ 1480 if (mEnable && mBluetooth != null) { 1481 try { 1482 mBluetoothLock.readLock().lock(); 1483 if (mBluetooth != null) { 1484 mBluetooth.unregisterCallback(mBluetoothCallback); 1485 } 1486 } catch (RemoteException re) { 1487 Slog.e(TAG, "Unable to unregister", re); 1488 } finally { 1489 mBluetoothLock.readLock().unlock(); 1490 } 1491 1492 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1493 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 1494 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 1495 mState = BluetoothAdapter.STATE_OFF; 1496 } 1497 if (mState == BluetoothAdapter.STATE_OFF) { 1498 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 1499 mState = BluetoothAdapter.STATE_TURNING_ON; 1500 } 1501 1502 waitForOnOff(true, false); 1503 1504 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 1505 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 1506 } 1507 1508 unbindAllBluetoothProfileServices(); 1509 // disable 1510 handleDisable(); 1511 // Pbap service need receive STATE_TURNING_OFF intent to close 1512 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1513 BluetoothAdapter.STATE_TURNING_OFF); 1514 1515 boolean didDisableTimeout = !waitForOnOff(false, true); 1516 1517 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1518 BluetoothAdapter.STATE_OFF); 1519 sendBluetoothServiceDownCallback(); 1520 1521 try { 1522 mBluetoothLock.writeLock().lock(); 1523 if (mBluetooth != null) { 1524 mBluetooth = null; 1525 // Unbind 1526 mContext.unbindService(mConnection); 1527 } 1528 mBluetoothGatt = null; 1529 } finally { 1530 mBluetoothLock.writeLock().unlock(); 1531 } 1532 1533 // 1534 // If disabling Bluetooth times out, wait for an 1535 // additional amount of time to ensure the process is 1536 // shut down completely before attempting to restart. 1537 // 1538 if (didDisableTimeout) { 1539 SystemClock.sleep(3000); 1540 } else { 1541 SystemClock.sleep(100); 1542 } 1543 1544 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1545 mState = BluetoothAdapter.STATE_OFF; 1546 // enable 1547 handleEnable(mQuietEnable); 1548 } else if (mBinding || mBluetooth != null) { 1549 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 1550 userMsg.arg2 = 1 + msg.arg2; 1551 // if user is switched when service is being binding 1552 // delay sending MESSAGE_USER_SWITCHED 1553 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 1554 if (DBG) { 1555 Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 1556 } 1557 } 1558 break; 1559 } 1560 case MESSAGE_USER_UNLOCKED: { 1561 if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1562 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1563 1564 if (mEnable && !mBinding && (mBluetooth == null)) { 1565 // We should be connected, but we gave up for some 1566 // reason; maybe the Bluetooth service wasn't encryption 1567 // aware, so try binding again. 1568 if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1569 handleEnable(mQuietEnable); 1570 } 1571 } 1572 } 1573 } 1574 } 1575 1576 private void handleEnable(boolean quietMode) { 1577 mQuietEnable = quietMode; 1578 1579 try { 1580 mBluetoothLock.writeLock().lock(); 1581 if ((mBluetooth == null) && (!mBinding)) { 1582 //Start bind timeout and bind 1583 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1584 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1585 Intent i = new Intent(IBluetooth.class.getName()); 1586 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1587 UserHandle.CURRENT)) { 1588 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1589 } else { 1590 mBinding = true; 1591 } 1592 } else if (mBluetooth != null) { 1593 //Enable bluetooth 1594 try { 1595 if (!mQuietEnable) { 1596 if(!mBluetooth.enable()) { 1597 Slog.e(TAG,"IBluetooth.enable() returned false"); 1598 } 1599 } 1600 else { 1601 if(!mBluetooth.enableNoAutoConnect()) { 1602 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1603 } 1604 } 1605 } catch (RemoteException e) { 1606 Slog.e(TAG,"Unable to call enable()",e); 1607 } 1608 } 1609 } finally { 1610 mBluetoothLock.writeLock().unlock(); 1611 } 1612 } 1613 1614 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1615 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1616 intent.setComponent(comp); 1617 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1618 Slog.e(TAG, "Fail to bind to: " + intent); 1619 return false; 1620 } 1621 return true; 1622 } 1623 1624 private void handleDisable() { 1625 try { 1626 mBluetoothLock.readLock().lock(); 1627 if (mBluetooth != null) { 1628 if (DBG) Slog.d(TAG,"Sending off request."); 1629 if (!mBluetooth.disable()) { 1630 Slog.e(TAG,"IBluetooth.disable() returned false"); 1631 } 1632 } 1633 } catch (RemoteException e) { 1634 Slog.e(TAG,"Unable to call disable()",e); 1635 } finally { 1636 mBluetoothLock.readLock().unlock(); 1637 } 1638 } 1639 1640 private boolean checkIfCallerIsForegroundUser() { 1641 int foregroundUser; 1642 int callingUser = UserHandle.getCallingUserId(); 1643 int callingUid = Binder.getCallingUid(); 1644 long callingIdentity = Binder.clearCallingIdentity(); 1645 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1646 UserInfo ui = um.getProfileParent(callingUser); 1647 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 1648 int callingAppId = UserHandle.getAppId(callingUid); 1649 boolean valid = false; 1650 try { 1651 foregroundUser = ActivityManager.getCurrentUser(); 1652 valid = (callingUser == foregroundUser) || 1653 parentUser == foregroundUser || 1654 callingAppId == Process.NFC_UID || 1655 callingAppId == mSystemUiUid; 1656 if (DBG) { 1657 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 1658 + " callingUser=" + callingUser 1659 + " parentUser=" + parentUser 1660 + " foregroundUser=" + foregroundUser); 1661 } 1662 } finally { 1663 Binder.restoreCallingIdentity(callingIdentity); 1664 } 1665 return valid; 1666 } 1667 1668 private void sendBleStateChanged(int prevState, int newState) { 1669 if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); 1670 // Send broadcast message to everyone else 1671 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 1672 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1673 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1674 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1675 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1676 } 1677 1678 private void bluetoothStateChangeHandler(int prevState, int newState) { 1679 boolean isStandardBroadcast = true; 1680 if (prevState != newState) { 1681 //Notify all proxy objects first of adapter state change 1682 if (newState == BluetoothAdapter.STATE_BLE_ON || 1683 newState == BluetoothAdapter.STATE_OFF) { 1684 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 1685 && newState == BluetoothAdapter.STATE_BLE_ON); 1686 1687 if (newState == BluetoothAdapter.STATE_OFF) { 1688 // If Bluetooth is off, send service down event to proxy objects, and unbind 1689 if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); 1690 sendBluetoothServiceDownCallback(); 1691 unbindAndFinish(); 1692 sendBleStateChanged(prevState, newState); 1693 // Don't broadcast as it has already been broadcast before 1694 isStandardBroadcast = false; 1695 1696 } else if (!intermediate_off) { 1697 // connect to GattService 1698 if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); 1699 if (mBluetoothGatt != null) { 1700 if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); 1701 onBluetoothGattServiceUp(); 1702 } else { 1703 if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); 1704 if (mContext.getPackageManager().hasSystemFeature( 1705 PackageManager.FEATURE_BLUETOOTH_LE)) { 1706 Intent i = new Intent(IBluetoothGatt.class.getName()); 1707 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); 1708 } 1709 } 1710 sendBleStateChanged(prevState, newState); 1711 //Don't broadcase this as std intent 1712 isStandardBroadcast = false; 1713 1714 } else if (intermediate_off){ 1715 if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); 1716 // For LE only mode, broadcast as is 1717 sendBleStateChanged(prevState, newState); 1718 sendBluetoothStateCallback(false); // BT is OFF for general users 1719 // Broadcast as STATE_OFF 1720 newState = BluetoothAdapter.STATE_OFF; 1721 sendBrEdrDownCallback(); 1722 } 1723 } else if (newState == BluetoothAdapter.STATE_ON) { 1724 boolean isUp = (newState==BluetoothAdapter.STATE_ON); 1725 sendBluetoothStateCallback(isUp); 1726 sendBleStateChanged(prevState, newState); 1727 1728 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || 1729 newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { 1730 sendBleStateChanged(prevState, newState); 1731 isStandardBroadcast = false; 1732 1733 } else if (newState == BluetoothAdapter.STATE_TURNING_ON || 1734 newState == BluetoothAdapter.STATE_TURNING_OFF) { 1735 sendBleStateChanged(prevState, newState); 1736 } 1737 1738 if (isStandardBroadcast) { 1739 if (prevState == BluetoothAdapter.STATE_BLE_ON) { 1740 // Show prevState of BLE_ON as OFF to standard users 1741 prevState = BluetoothAdapter.STATE_OFF; 1742 } 1743 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1744 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1745 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1746 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1747 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1748 } 1749 } 1750 } 1751 1752 /** 1753 * if on is true, wait for state become ON 1754 * if off is true, wait for state become OFF 1755 * if both on and off are false, wait for state not ON 1756 */ 1757 private boolean waitForOnOff(boolean on, boolean off) { 1758 int i = 0; 1759 while (i < 10) { 1760 try { 1761 mBluetoothLock.readLock().lock(); 1762 if (mBluetooth == null) break; 1763 if (on) { 1764 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1765 } else if (off) { 1766 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1767 } else { 1768 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1769 } 1770 } catch (RemoteException e) { 1771 Slog.e(TAG, "getState()", e); 1772 break; 1773 } finally { 1774 mBluetoothLock.readLock().unlock(); 1775 } 1776 if (on || off) { 1777 SystemClock.sleep(300); 1778 } else { 1779 SystemClock.sleep(50); 1780 } 1781 i++; 1782 } 1783 Slog.e(TAG,"waitForOnOff time out"); 1784 return false; 1785 } 1786 1787 private void sendDisableMsg() { 1788 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1789 } 1790 1791 private void sendEnableMsg(boolean quietMode) { 1792 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1793 quietMode ? 1 : 0, 0)); 1794 } 1795 1796 private void recoverBluetoothServiceFromError() { 1797 Slog.e(TAG,"recoverBluetoothServiceFromError"); 1798 try { 1799 mBluetoothLock.readLock().lock(); 1800 if (mBluetooth != null) { 1801 //Unregister callback object 1802 mBluetooth.unregisterCallback(mBluetoothCallback); 1803 } 1804 } catch (RemoteException re) { 1805 Slog.e(TAG, "Unable to unregister", re); 1806 } finally { 1807 mBluetoothLock.readLock().unlock(); 1808 } 1809 1810 SystemClock.sleep(500); 1811 1812 // disable 1813 handleDisable(); 1814 1815 waitForOnOff(false, true); 1816 1817 sendBluetoothServiceDownCallback(); 1818 1819 try { 1820 mBluetoothLock.writeLock().lock(); 1821 if (mBluetooth != null) { 1822 mBluetooth = null; 1823 // Unbind 1824 mContext.unbindService(mConnection); 1825 } 1826 mBluetoothGatt = null; 1827 } finally { 1828 mBluetoothLock.writeLock().unlock(); 1829 } 1830 1831 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1832 mState = BluetoothAdapter.STATE_OFF; 1833 1834 mEnable = false; 1835 1836 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1837 // Send a Bluetooth Restart message to reenable bluetooth 1838 Message restartMsg = mHandler.obtainMessage( 1839 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1840 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1841 } else { 1842 // todo: notify user to power down and power up phone to make bluetooth work. 1843 } 1844 } 1845 1846 @Override 1847 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1848 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 1849 String errorMsg = null; 1850 if (mBluetoothBinder == null) { 1851 errorMsg = "Bluetooth Service not connected"; 1852 } else { 1853 try { 1854 mBluetoothBinder.dump(fd, args); 1855 } catch (RemoteException re) { 1856 errorMsg = "RemoteException while calling Bluetooth Service"; 1857 } 1858 } 1859 if (errorMsg != null) { 1860 // Silently return if we are extracting metrics in Protobuf format 1861 if ((args.length > 0) && args[0].startsWith("--proto")) 1862 return; 1863 writer.println(errorMsg); 1864 } 1865 } 1866 } 1867