BluetoothManagerService.java revision e957a8a0b4100d001f79c866e7904d2426ac8da0
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 = false; 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().lock(); 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 // We do not honor ON requests when the adapter is already turned ON or in the process of 643 // turning ON. 644 // As a protective mechanism to make sure that the native stack gets cleaned up properly 645 // before turning it back ON we ignore requests while the bluetooth is turning OFF. 646 // Bug: b/28318203 647 if (mState == BluetoothAdapter.STATE_BLE_TURNING_OFF || 648 mState == BluetoothAdapter.STATE_TURNING_OFF || 649 mState == BluetoothAdapter.STATE_ON || 650 mState == BluetoothAdapter.STATE_BLE_ON || 651 mState == BluetoothAdapter.STATE_TURNING_ON || 652 mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { 653 return false; 654 } 655 656 synchronized(mReceiver) { 657 mQuietEnableExternal = false; 658 mEnableExternal = true; 659 // waive WRITE_SECURE_SETTINGS permission check 660 sendEnableMsg(false); 661 } 662 if (DBG) Slog.d(TAG, "enable returning"); 663 return true; 664 } 665 666 public boolean disable(boolean persist) { 667 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 668 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 669 670 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 671 (!checkIfCallerIsForegroundUser())) { 672 Slog.w(TAG,"disable(): not allowed for non-active and non system user"); 673 return false; 674 } 675 676 if (DBG) { 677 Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + 678 " mBinding = " + mBinding); 679 } 680 681 synchronized(mReceiver) { 682 if (persist) { 683 // waive WRITE_SECURE_SETTINGS permission check 684 long callingIdentity = Binder.clearCallingIdentity(); 685 persistBluetoothSetting(BLUETOOTH_OFF); 686 Binder.restoreCallingIdentity(callingIdentity); 687 } 688 mEnableExternal = false; 689 sendDisableMsg(); 690 } 691 return true; 692 } 693 694 public void unbindAndFinish() { 695 if (DBG) { 696 Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + 697 " mBinding = " + mBinding); 698 } 699 700 try { 701 mBluetoothLock.writeLock().lock(); 702 if (mUnbinding) return; 703 mUnbinding = true; 704 if (mBluetooth != null) { 705 //Unregister callback object 706 try { 707 mBluetooth.unregisterCallback(mBluetoothCallback); 708 } catch (RemoteException re) { 709 Slog.e(TAG, "Unable to unregister BluetoothCallback",re); 710 } 711 712 if (DBG) Slog.d(TAG, "Sending unbind request."); 713 mBluetoothBinder = null; 714 mBluetooth = null; 715 //Unbind 716 mContext.unbindService(mConnection); 717 mUnbinding = false; 718 mBinding = false; 719 } else { 720 mUnbinding=false; 721 } 722 mBluetoothGatt = null; 723 } finally { 724 mBluetoothLock.writeLock().unlock(); 725 } 726 } 727 728 public IBluetoothGatt getBluetoothGatt() { 729 // sync protection 730 return mBluetoothGatt; 731 } 732 733 @Override 734 public boolean bindBluetoothProfileService(int bluetoothProfile, 735 IBluetoothProfileServiceConnection proxy) { 736 if (!mEnable) { 737 if (DBG) { 738 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 739 ", while Bluetooth was disabled"); 740 } 741 return false; 742 } 743 synchronized (mProfileServices) { 744 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 745 if (psc == null) { 746 if (DBG) { 747 Slog.d(TAG, "Creating new ProfileServiceConnections object for" 748 + " profile: " + bluetoothProfile); 749 } 750 751 if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 752 753 Intent intent = new Intent(IBluetoothHeadset.class.getName()); 754 psc = new ProfileServiceConnections(intent); 755 if (!psc.bindService()) return false; 756 757 mProfileServices.put(new Integer(bluetoothProfile), psc); 758 } 759 } 760 761 // Introducing a delay to give the client app time to prepare 762 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 763 addProxyMsg.arg1 = bluetoothProfile; 764 addProxyMsg.obj = proxy; 765 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 766 return true; 767 } 768 769 @Override 770 public void unbindBluetoothProfileService(int bluetoothProfile, 771 IBluetoothProfileServiceConnection proxy) { 772 synchronized (mProfileServices) { 773 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 774 if (psc == null) { 775 return; 776 } 777 psc.removeProxy(proxy); 778 } 779 } 780 781 private void unbindAllBluetoothProfileServices() { 782 synchronized (mProfileServices) { 783 for (Integer i : mProfileServices.keySet()) { 784 ProfileServiceConnections psc = mProfileServices.get(i); 785 try { 786 mContext.unbindService(psc); 787 } catch (IllegalArgumentException e) { 788 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 789 } 790 psc.removeAllProxies(); 791 } 792 mProfileServices.clear(); 793 } 794 } 795 796 /** 797 * Send enable message and set adapter name and address. Called when the boot phase becomes 798 * PHASE_SYSTEM_SERVICES_READY. 799 */ 800 public void handleOnBootPhase() { 801 if (DBG) Slog.d(TAG, "Bluetooth boot completed"); 802 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 803 if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); 804 sendEnableMsg(mQuietEnableExternal); 805 } else if (!isNameAndAddressSet()) { 806 if (DBG) Slog.d(TAG, "Getting adapter name and address"); 807 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 808 mHandler.sendMessage(getMsg); 809 } 810 } 811 812 /** 813 * Called when switching to a different foreground user. 814 */ 815 public void handleOnSwitchUser(int userHandle) { 816 if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); 817 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 818 } 819 820 /** 821 * Called when user is unlocked. 822 */ 823 public void handleOnUnlockUser(int userHandle) { 824 if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); 825 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 826 } 827 828 /** 829 * This class manages the clients connected to a given ProfileService 830 * and maintains the connection with that service. 831 */ 832 final private class ProfileServiceConnections implements ServiceConnection, 833 IBinder.DeathRecipient { 834 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 835 new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 836 IBinder mService; 837 ComponentName mClassName; 838 Intent mIntent; 839 boolean mInvokingProxyCallbacks = false; 840 841 ProfileServiceConnections(Intent intent) { 842 mService = null; 843 mClassName = null; 844 mIntent = intent; 845 } 846 847 private boolean bindService() { 848 if (mIntent != null && mService == null && 849 doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 850 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 851 msg.obj = this; 852 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 853 return true; 854 } 855 Slog.w(TAG, "Unable to bind with intent: " + mIntent); 856 return false; 857 } 858 859 private void addProxy(IBluetoothProfileServiceConnection proxy) { 860 mProxies.register(proxy); 861 if (mService != null) { 862 try{ 863 proxy.onServiceConnected(mClassName, mService); 864 } catch (RemoteException e) { 865 Slog.e(TAG, "Unable to connect to proxy", e); 866 } 867 } else { 868 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 869 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 870 msg.obj = this; 871 mHandler.sendMessage(msg); 872 } 873 } 874 } 875 876 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 877 if (proxy != null) { 878 if (mProxies.unregister(proxy)) { 879 try { 880 proxy.onServiceDisconnected(mClassName); 881 } catch (RemoteException e) { 882 Slog.e(TAG, "Unable to disconnect proxy", e); 883 } 884 } 885 } else { 886 Slog.w(TAG, "Trying to remove a null proxy"); 887 } 888 } 889 890 private void removeAllProxies() { 891 onServiceDisconnected(mClassName); 892 mProxies.kill(); 893 } 894 895 @Override 896 public void onServiceConnected(ComponentName className, IBinder service) { 897 // remove timeout message 898 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 899 mService = service; 900 mClassName = className; 901 try { 902 mService.linkToDeath(this, 0); 903 } catch (RemoteException e) { 904 Slog.e(TAG, "Unable to linkToDeath", e); 905 } 906 907 if (mInvokingProxyCallbacks) { 908 Slog.e(TAG, "Proxy callbacks already in progress."); 909 return; 910 } 911 mInvokingProxyCallbacks = true; 912 913 final int n = mProxies.beginBroadcast(); 914 try { 915 for (int i = 0; i < n; i++) { 916 try { 917 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 918 } catch (RemoteException e) { 919 Slog.e(TAG, "Unable to connect to proxy", e); 920 } 921 } 922 } finally { 923 mProxies.finishBroadcast(); 924 mInvokingProxyCallbacks = false; 925 } 926 } 927 928 @Override 929 public void onServiceDisconnected(ComponentName className) { 930 if (mService == null) return; 931 mService.unlinkToDeath(this, 0); 932 mService = null; 933 mClassName = null; 934 935 if (mInvokingProxyCallbacks) { 936 Slog.e(TAG, "Proxy callbacks already in progress."); 937 return; 938 } 939 mInvokingProxyCallbacks = true; 940 941 final int n = mProxies.beginBroadcast(); 942 try { 943 for (int i = 0; i < n; i++) { 944 try { 945 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 946 } catch (RemoteException e) { 947 Slog.e(TAG, "Unable to disconnect from proxy", e); 948 } 949 } 950 } finally { 951 mProxies.finishBroadcast(); 952 mInvokingProxyCallbacks = false; 953 } 954 } 955 956 @Override 957 public void binderDied() { 958 if (DBG) { 959 Slog.w(TAG, "Profile service for profile: " + mClassName 960 + " died."); 961 } 962 onServiceDisconnected(mClassName); 963 // Trigger rebind 964 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 965 msg.obj = this; 966 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 967 } 968 } 969 970 private void sendBluetoothStateCallback(boolean isUp) { 971 try { 972 int n = mStateChangeCallbacks.beginBroadcast(); 973 if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 974 for (int i=0; i <n;i++) { 975 try { 976 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 977 } catch (RemoteException e) { 978 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 979 } 980 } 981 } finally { 982 mStateChangeCallbacks.finishBroadcast(); 983 } 984 } 985 986 /** 987 * Inform BluetoothAdapter instances that Adapter service is up 988 */ 989 private void sendBluetoothServiceUpCallback() { 990 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); 991 try { 992 int n = mCallbacks.beginBroadcast(); 993 Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 994 for (int i=0; i <n;i++) { 995 try { 996 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 997 } catch (RemoteException e) { 998 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 999 } 1000 } 1001 } finally { 1002 mCallbacks.finishBroadcast(); 1003 } 1004 } 1005 /** 1006 * Inform BluetoothAdapter instances that Adapter service is down 1007 */ 1008 private void sendBluetoothServiceDownCallback() { 1009 if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); 1010 try { 1011 int n = mCallbacks.beginBroadcast(); 1012 Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1013 for (int i=0; i <n;i++) { 1014 try { 1015 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1016 } catch (RemoteException e) { 1017 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1018 } 1019 } 1020 } finally { 1021 mCallbacks.finishBroadcast(); 1022 } 1023 } 1024 1025 public String getAddress() { 1026 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1027 "Need BLUETOOTH permission"); 1028 1029 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1030 (!checkIfCallerIsForegroundUser())) { 1031 Slog.w(TAG,"getAddress(): not allowed for non-active and non system user"); 1032 return null; 1033 } 1034 1035 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1036 != PackageManager.PERMISSION_GRANTED) { 1037 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1038 } 1039 1040 try { 1041 mBluetoothLock.readLock().lock(); 1042 if (mBluetooth != null) return mBluetooth.getAddress(); 1043 } catch (RemoteException e) { 1044 Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); 1045 } finally { 1046 mBluetoothLock.readLock().unlock(); 1047 } 1048 1049 // mAddress is accessed from outside. 1050 // It is alright without a lock. Here, bluetooth is off, no other thread is 1051 // changing mAddress 1052 return mAddress; 1053 } 1054 1055 public String getName() { 1056 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1057 "Need BLUETOOTH permission"); 1058 1059 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1060 (!checkIfCallerIsForegroundUser())) { 1061 Slog.w(TAG,"getName(): not allowed for non-active and non system user"); 1062 return null; 1063 } 1064 1065 try { 1066 mBluetoothLock.readLock().lock(); 1067 if (mBluetooth != null) return mBluetooth.getName(); 1068 } catch (RemoteException e) { 1069 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1070 } finally { 1071 mBluetoothLock.readLock().unlock(); 1072 } 1073 1074 // mName is accessed from outside. 1075 // It alright without a lock. Here, bluetooth is off, no other thread is 1076 // changing mName 1077 return mName; 1078 } 1079 1080 private class BluetoothServiceConnection implements ServiceConnection { 1081 public void onServiceConnected(ComponentName className, IBinder service) { 1082 if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 1083 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1084 // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 1085 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1086 msg.arg1 = SERVICE_IBLUETOOTH; 1087 // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 1088 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1089 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1090 } else { 1091 Slog.e(TAG, "Unknown service connected: " + className.getClassName()); 1092 return; 1093 } 1094 msg.obj = service; 1095 mHandler.sendMessage(msg); 1096 } 1097 1098 public void onServiceDisconnected(ComponentName className) { 1099 // Called if we unexpected disconnected. 1100 if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + 1101 className.getClassName()); 1102 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1103 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1104 msg.arg1 = SERVICE_IBLUETOOTH; 1105 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1106 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1107 } else { 1108 Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); 1109 return; 1110 } 1111 mHandler.sendMessage(msg); 1112 } 1113 } 1114 1115 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 1116 1117 private class BluetoothHandler extends Handler { 1118 boolean mGetNameAddressOnly = false; 1119 1120 public BluetoothHandler(Looper looper) { 1121 super(looper); 1122 } 1123 1124 @Override 1125 public void handleMessage(Message msg) { 1126 if (DBG) Slog.d (TAG, "Message: " + msg.what); 1127 switch (msg.what) { 1128 case MESSAGE_GET_NAME_AND_ADDRESS: 1129 if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1130 try { 1131 mBluetoothLock.writeLock().lock(); 1132 if ((mBluetooth == null) && (!mBinding)) { 1133 if (DBG) Slog.d(TAG, "Binding to service to get name and address"); 1134 mGetNameAddressOnly = true; 1135 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1136 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 1137 Intent i = new Intent(IBluetooth.class.getName()); 1138 if (!doBind(i, mConnection, 1139 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1140 UserHandle.CURRENT)) { 1141 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1142 } else { 1143 mBinding = true; 1144 } 1145 } else if (mBluetooth != null) { 1146 try { 1147 storeNameAndAddress(mBluetooth.getName(), 1148 mBluetooth.getAddress()); 1149 } catch (RemoteException re) { 1150 Slog.e(TAG, "Unable to grab names", re); 1151 } 1152 if (mGetNameAddressOnly && !mEnable) { 1153 unbindAndFinish(); 1154 } 1155 mGetNameAddressOnly = false; 1156 } 1157 } finally { 1158 mBluetoothLock.writeLock().unlock(); 1159 } 1160 break; 1161 1162 case MESSAGE_ENABLE: 1163 if (DBG) { 1164 Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 1165 } 1166 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1167 mEnable = true; 1168 handleEnable(msg.arg1 == 1); 1169 break; 1170 1171 case MESSAGE_DISABLE: 1172 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1173 if (mEnable && mBluetooth != null) { 1174 waitForOnOff(true, false); 1175 mEnable = false; 1176 handleDisable(); 1177 waitForOnOff(false, false); 1178 } else { 1179 mEnable = false; 1180 handleDisable(); 1181 } 1182 break; 1183 1184 case MESSAGE_REGISTER_ADAPTER: 1185 { 1186 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1187 boolean added = mCallbacks.register(callback); 1188 Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 1189 } 1190 break; 1191 case MESSAGE_UNREGISTER_ADAPTER: 1192 { 1193 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1194 boolean removed = mCallbacks.unregister(callback); 1195 Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 1196 break; 1197 } 1198 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 1199 { 1200 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1201 if (callback != null) { 1202 mStateChangeCallbacks.register(callback); 1203 } 1204 break; 1205 } 1206 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 1207 { 1208 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1209 if (callback != null) { 1210 mStateChangeCallbacks.unregister(callback); 1211 } 1212 break; 1213 } 1214 case MESSAGE_ADD_PROXY_DELAYED: 1215 { 1216 ProfileServiceConnections psc = mProfileServices.get( 1217 new Integer(msg.arg1)); 1218 if (psc == null) { 1219 break; 1220 } 1221 IBluetoothProfileServiceConnection proxy = 1222 (IBluetoothProfileServiceConnection) msg.obj; 1223 psc.addProxy(proxy); 1224 break; 1225 } 1226 case MESSAGE_BIND_PROFILE_SERVICE: 1227 { 1228 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1229 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1230 if (psc == null) { 1231 break; 1232 } 1233 psc.bindService(); 1234 break; 1235 } 1236 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1237 { 1238 if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 1239 1240 IBinder service = (IBinder) msg.obj; 1241 try { 1242 mBluetoothLock.writeLock().lock(); 1243 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1244 mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1245 onBluetoothGattServiceUp(); 1246 break; 1247 } // else must be SERVICE_IBLUETOOTH 1248 1249 //Remove timeout 1250 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1251 1252 mBinding = false; 1253 mBluetoothBinder = service; 1254 mBluetooth = IBluetooth.Stub.asInterface(service); 1255 1256 if (!isNameAndAddressSet()) { 1257 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1258 mHandler.sendMessage(getMsg); 1259 if (mGetNameAddressOnly) return; 1260 } 1261 1262 try { 1263 boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1264 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1265 if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 1266 Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1267 } 1268 } catch (RemoteException e) { 1269 Slog.e(TAG,"Unable to call configHciSnoopLog", e); 1270 } 1271 1272 //Register callback object 1273 try { 1274 mBluetooth.registerCallback(mBluetoothCallback); 1275 } catch (RemoteException re) { 1276 Slog.e(TAG, "Unable to register BluetoothCallback",re); 1277 } 1278 //Inform BluetoothAdapter instances that service is up 1279 sendBluetoothServiceUpCallback(); 1280 1281 //Do enable request 1282 try { 1283 if (mQuietEnable == false) { 1284 if(!mBluetooth.enable()) { 1285 Slog.e(TAG,"IBluetooth.enable() returned false"); 1286 } 1287 } 1288 else 1289 { 1290 if(!mBluetooth.enableNoAutoConnect()) { 1291 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1292 } 1293 } 1294 } catch (RemoteException e) { 1295 Slog.e(TAG,"Unable to call enable()",e); 1296 } 1297 } finally { 1298 mBluetoothLock.writeLock().unlock(); 1299 } 1300 1301 if (!mEnable) { 1302 waitForOnOff(true, false); 1303 handleDisable(); 1304 waitForOnOff(false, false); 1305 } 1306 break; 1307 } 1308 case MESSAGE_TIMEOUT_BIND: { 1309 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1310 mBluetoothLock.writeLock().lock(); 1311 mBinding = false; 1312 mBluetoothLock.writeLock().unlock(); 1313 1314 break; 1315 } 1316 case MESSAGE_BLUETOOTH_STATE_CHANGE: 1317 { 1318 int prevState = msg.arg1; 1319 int newState = msg.arg2; 1320 if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 1321 mState = newState; 1322 bluetoothStateChangeHandler(prevState, newState); 1323 // handle error state transition case from TURNING_ON to OFF 1324 // unbind and rebind bluetooth service and enable bluetooth 1325 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && 1326 (newState == BluetoothAdapter.STATE_OFF) && 1327 (mBluetooth != null) && mEnable) { 1328 recoverBluetoothServiceFromError(); 1329 } 1330 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1331 (newState == BluetoothAdapter.STATE_BLE_ON) && 1332 (mBluetooth != null) && mEnable) { 1333 recoverBluetoothServiceFromError(); 1334 } 1335 if (newState == BluetoothAdapter.STATE_ON || 1336 newState == BluetoothAdapter.STATE_BLE_ON) { 1337 // bluetooth is working, reset the counter 1338 if (mErrorRecoveryRetryCounter != 0) { 1339 Slog.w(TAG, "bluetooth is recovered from error"); 1340 mErrorRecoveryRetryCounter = 0; 1341 } 1342 } 1343 break; 1344 } 1345 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 1346 { 1347 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 1348 try { 1349 mBluetoothLock.writeLock().lock(); 1350 if (msg.arg1 == SERVICE_IBLUETOOTH) { 1351 // if service is unbinded already, do nothing and return 1352 if (mBluetooth == null) break; 1353 mBluetooth = null; 1354 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1355 mBluetoothGatt = null; 1356 break; 1357 } else { 1358 Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); 1359 break; 1360 } 1361 } finally { 1362 mBluetoothLock.writeLock().unlock(); 1363 } 1364 1365 if (mEnable) { 1366 mEnable = false; 1367 // Send a Bluetooth Restart message 1368 Message restartMsg = mHandler.obtainMessage( 1369 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1370 mHandler.sendMessageDelayed(restartMsg, 1371 SERVICE_RESTART_TIME_MS); 1372 } 1373 1374 sendBluetoothServiceDownCallback(); 1375 1376 // Send BT state broadcast to update 1377 // the BT icon correctly 1378 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1379 (mState == BluetoothAdapter.STATE_ON)) { 1380 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1381 BluetoothAdapter.STATE_TURNING_OFF); 1382 mState = BluetoothAdapter.STATE_TURNING_OFF; 1383 } 1384 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1385 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1386 BluetoothAdapter.STATE_OFF); 1387 } 1388 1389 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1390 mState = BluetoothAdapter.STATE_OFF; 1391 break; 1392 } 1393 case MESSAGE_RESTART_BLUETOOTH_SERVICE: 1394 { 1395 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 1396 +" Restart IBluetooth service"); 1397 /* Enable without persisting the setting as 1398 it doesnt change when IBluetooth 1399 service restarts */ 1400 mEnable = true; 1401 handleEnable(mQuietEnable); 1402 break; 1403 } 1404 1405 case MESSAGE_TIMEOUT_UNBIND: 1406 { 1407 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1408 mBluetoothLock.writeLock().lock(); 1409 mUnbinding = false; 1410 mBluetoothLock.writeLock().unlock(); 1411 break; 1412 } 1413 1414 case MESSAGE_USER_SWITCHED: { 1415 if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 1416 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1417 1418 /* disable and enable BT when detect a user switch */ 1419 if (mEnable && mBluetooth != null) { 1420 try { 1421 mBluetoothLock.readLock().lock(); 1422 if (mBluetooth != null) { 1423 mBluetooth.unregisterCallback(mBluetoothCallback); 1424 } 1425 } catch (RemoteException re) { 1426 Slog.e(TAG, "Unable to unregister", re); 1427 } finally { 1428 mBluetoothLock.readLock().unlock(); 1429 } 1430 1431 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1432 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 1433 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 1434 mState = BluetoothAdapter.STATE_OFF; 1435 } 1436 if (mState == BluetoothAdapter.STATE_OFF) { 1437 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 1438 mState = BluetoothAdapter.STATE_TURNING_ON; 1439 } 1440 1441 waitForOnOff(true, false); 1442 1443 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 1444 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 1445 } 1446 1447 unbindAllBluetoothProfileServices(); 1448 // disable 1449 handleDisable(); 1450 // Pbap service need receive STATE_TURNING_OFF intent to close 1451 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1452 BluetoothAdapter.STATE_TURNING_OFF); 1453 1454 waitForOnOff(false, true); 1455 1456 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1457 BluetoothAdapter.STATE_OFF); 1458 sendBluetoothServiceDownCallback(); 1459 1460 try { 1461 mBluetoothLock.writeLock().lock(); 1462 if (mBluetooth != null) { 1463 mBluetooth = null; 1464 // Unbind 1465 mContext.unbindService(mConnection); 1466 } 1467 mBluetoothGatt = null; 1468 } finally { 1469 mBluetoothLock.writeLock().unlock(); 1470 } 1471 1472 SystemClock.sleep(100); 1473 1474 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1475 mState = BluetoothAdapter.STATE_OFF; 1476 // enable 1477 handleEnable(mQuietEnable); 1478 } else if (mBinding || mBluetooth != null) { 1479 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 1480 userMsg.arg2 = 1 + msg.arg2; 1481 // if user is switched when service is being binding 1482 // delay sending MESSAGE_USER_SWITCHED 1483 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 1484 if (DBG) { 1485 Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 1486 } 1487 } 1488 break; 1489 } 1490 case MESSAGE_USER_UNLOCKED: { 1491 if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1492 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1493 1494 if (mEnable && !mBinding && (mBluetooth == null)) { 1495 // We should be connected, but we gave up for some 1496 // reason; maybe the Bluetooth service wasn't encryption 1497 // aware, so try binding again. 1498 if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1499 handleEnable(mQuietEnable); 1500 } 1501 } 1502 } 1503 } 1504 } 1505 1506 private void handleEnable(boolean quietMode) { 1507 mQuietEnable = quietMode; 1508 1509 try { 1510 mBluetoothLock.writeLock().lock(); 1511 if ((mBluetooth == null) && (!mBinding)) { 1512 //Start bind timeout and bind 1513 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1514 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1515 Intent i = new Intent(IBluetooth.class.getName()); 1516 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1517 UserHandle.CURRENT)) { 1518 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1519 } else { 1520 mBinding = true; 1521 } 1522 } else if (mBluetooth != null) { 1523 //Enable bluetooth 1524 try { 1525 if (!mQuietEnable) { 1526 if(!mBluetooth.enable()) { 1527 Slog.e(TAG,"IBluetooth.enable() returned false"); 1528 } 1529 } 1530 else { 1531 if(!mBluetooth.enableNoAutoConnect()) { 1532 Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1533 } 1534 } 1535 } catch (RemoteException e) { 1536 Slog.e(TAG,"Unable to call enable()",e); 1537 } 1538 } 1539 } finally { 1540 mBluetoothLock.writeLock().unlock(); 1541 } 1542 } 1543 1544 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1545 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1546 intent.setComponent(comp); 1547 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1548 Slog.e(TAG, "Fail to bind to: " + intent); 1549 return false; 1550 } 1551 return true; 1552 } 1553 1554 private void handleDisable() { 1555 try { 1556 mBluetoothLock.readLock().lock(); 1557 if (mBluetooth != null) { 1558 if (DBG) Slog.d(TAG,"Sending off request."); 1559 if (!mBluetooth.disable()) { 1560 Slog.e(TAG,"IBluetooth.disable() returned false"); 1561 } 1562 } 1563 } catch (RemoteException e) { 1564 Slog.e(TAG,"Unable to call disable()",e); 1565 } finally { 1566 mBluetoothLock.readLock().unlock(); 1567 } 1568 } 1569 1570 private boolean checkIfCallerIsForegroundUser() { 1571 int foregroundUser; 1572 int callingUser = UserHandle.getCallingUserId(); 1573 int callingUid = Binder.getCallingUid(); 1574 long callingIdentity = Binder.clearCallingIdentity(); 1575 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1576 UserInfo ui = um.getProfileParent(callingUser); 1577 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 1578 int callingAppId = UserHandle.getAppId(callingUid); 1579 boolean valid = false; 1580 try { 1581 foregroundUser = ActivityManager.getCurrentUser(); 1582 valid = (callingUser == foregroundUser) || 1583 parentUser == foregroundUser || 1584 callingAppId == Process.NFC_UID || 1585 callingAppId == mSystemUiUid; 1586 if (DBG) { 1587 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 1588 + " callingUser=" + callingUser 1589 + " parentUser=" + parentUser 1590 + " foregroundUser=" + foregroundUser); 1591 } 1592 } finally { 1593 Binder.restoreCallingIdentity(callingIdentity); 1594 } 1595 return valid; 1596 } 1597 1598 private void sendBleStateChanged(int prevState, int newState) { 1599 if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); 1600 // Send broadcast message to everyone else 1601 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 1602 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1603 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1604 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1605 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1606 } 1607 1608 private void bluetoothStateChangeHandler(int prevState, int newState) { 1609 boolean isStandardBroadcast = true; 1610 if (prevState != newState) { 1611 //Notify all proxy objects first of adapter state change 1612 if (newState == BluetoothAdapter.STATE_BLE_ON 1613 || newState == BluetoothAdapter.STATE_OFF) { 1614 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 1615 && newState == BluetoothAdapter.STATE_BLE_ON); 1616 1617 if (newState == BluetoothAdapter.STATE_OFF) { 1618 // If Bluetooth is off, send service down event to proxy objects, and unbind 1619 if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); 1620 if (canUnbindBluetoothService()) { 1621 if (DBG) Slog.d(TAG, "Good to unbind!"); 1622 sendBluetoothServiceDownCallback(); 1623 unbindAndFinish(); 1624 sendBleStateChanged(prevState, newState); 1625 // Don't broadcast as it has already been broadcast before 1626 isStandardBroadcast = false; 1627 } 1628 1629 } else if (!intermediate_off) { 1630 // connect to GattService 1631 if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); 1632 if (mBluetoothGatt != null) { 1633 if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); 1634 onBluetoothGattServiceUp(); 1635 } else { 1636 if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); 1637 if (mContext.getPackageManager().hasSystemFeature( 1638 PackageManager.FEATURE_BLUETOOTH_LE)) { 1639 Intent i = new Intent(IBluetoothGatt.class.getName()); 1640 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); 1641 } 1642 } 1643 sendBleStateChanged(prevState, newState); 1644 //Don't broadcase this as std intent 1645 isStandardBroadcast = false; 1646 1647 } else if (intermediate_off){ 1648 if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); 1649 // For LE only mode, broadcast as is 1650 sendBleStateChanged(prevState, newState); 1651 sendBluetoothStateCallback(false); // BT is OFF for general users 1652 // Broadcast as STATE_OFF 1653 newState = BluetoothAdapter.STATE_OFF; 1654 sendBrEdrDownCallback(); 1655 } 1656 } else if (newState == BluetoothAdapter.STATE_ON) { 1657 boolean isUp = (newState==BluetoothAdapter.STATE_ON); 1658 sendBluetoothStateCallback(isUp); 1659 sendBleStateChanged(prevState, newState); 1660 1661 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON 1662 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { 1663 sendBleStateChanged(prevState, newState); 1664 isStandardBroadcast = false; 1665 1666 } else if (newState == BluetoothAdapter.STATE_TURNING_ON 1667 || newState == BluetoothAdapter.STATE_TURNING_OFF) { 1668 sendBleStateChanged(prevState, newState); 1669 } 1670 1671 if (isStandardBroadcast) { 1672 if (prevState == BluetoothAdapter.STATE_BLE_ON) { 1673 // Show prevState of BLE_ON as OFF to standard users 1674 prevState = BluetoothAdapter.STATE_OFF; 1675 } 1676 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1677 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1678 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1679 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1680 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1681 } 1682 } 1683 } 1684 1685 /** 1686 * if on is true, wait for state become ON 1687 * if off is true, wait for state become OFF 1688 * if both on and off are false, wait for state not ON 1689 */ 1690 private boolean waitForOnOff(boolean on, boolean off) { 1691 int i = 0; 1692 while (i < 10) { 1693 try { 1694 mBluetoothLock.readLock().lock(); 1695 if (mBluetooth == null) break; 1696 if (on) { 1697 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1698 } else if (off) { 1699 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1700 } else { 1701 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1702 } 1703 } catch (RemoteException e) { 1704 Slog.e(TAG, "getState()", e); 1705 break; 1706 } finally { 1707 mBluetoothLock.readLock().unlock(); 1708 } 1709 if (on || off) { 1710 SystemClock.sleep(300); 1711 } else { 1712 SystemClock.sleep(50); 1713 } 1714 i++; 1715 } 1716 Slog.e(TAG,"waitForOnOff time out"); 1717 return false; 1718 } 1719 1720 private void sendDisableMsg() { 1721 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1722 } 1723 1724 private void sendEnableMsg(boolean quietMode) { 1725 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1726 quietMode ? 1 : 0, 0)); 1727 } 1728 1729 private boolean canUnbindBluetoothService() { 1730 try { 1731 //Only unbind with mEnable flag not set 1732 //For race condition: disable and enable back-to-back 1733 //Avoid unbind right after enable due to callback from disable 1734 //Only unbind with Bluetooth at OFF state 1735 //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message 1736 mBluetoothLock.readLock().lock(); 1737 if (mEnable || (mBluetooth == null)) return false; 1738 if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; 1739 return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); 1740 } catch (RemoteException e) { 1741 Slog.e(TAG, "getState()", e); 1742 } finally { 1743 mBluetoothLock.readLock().unlock(); 1744 } 1745 return false; 1746 } 1747 1748 private void recoverBluetoothServiceFromError() { 1749 Slog.e(TAG,"recoverBluetoothServiceFromError"); 1750 try { 1751 mBluetoothLock.readLock().lock(); 1752 if (mBluetooth != null) { 1753 //Unregister callback object 1754 mBluetooth.unregisterCallback(mBluetoothCallback); 1755 } 1756 } catch (RemoteException re) { 1757 Slog.e(TAG, "Unable to unregister", re); 1758 } finally { 1759 mBluetoothLock.readLock().unlock(); 1760 } 1761 1762 SystemClock.sleep(500); 1763 1764 // disable 1765 handleDisable(); 1766 1767 waitForOnOff(false, true); 1768 1769 sendBluetoothServiceDownCallback(); 1770 1771 try { 1772 mBluetoothLock.writeLock().lock(); 1773 if (mBluetooth != null) { 1774 mBluetooth = null; 1775 // Unbind 1776 mContext.unbindService(mConnection); 1777 } 1778 mBluetoothGatt = null; 1779 } finally { 1780 mBluetoothLock.writeLock().unlock(); 1781 } 1782 1783 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1784 mState = BluetoothAdapter.STATE_OFF; 1785 1786 mEnable = false; 1787 1788 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1789 // Send a Bluetooth Restart message to reenable bluetooth 1790 Message restartMsg = mHandler.obtainMessage( 1791 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1792 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1793 } else { 1794 // todo: notify user to power down and power up phone to make bluetooth work. 1795 } 1796 } 1797 1798 @Override 1799 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1800 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 1801 String errorMsg = null; 1802 if (mBluetoothBinder == null) { 1803 errorMsg = "Bluetooth Service not connected"; 1804 } else { 1805 try { 1806 mBluetoothBinder.dump(fd, args); 1807 } catch (RemoteException re) { 1808 errorMsg = "RemoteException while calling Bluetooth Service"; 1809 } 1810 } 1811 if (errorMsg != null) { 1812 // Silently return if we are extracting metrics in Protobuf format 1813 if ((args.length > 0) && args[0].startsWith("--proto")) 1814 return; 1815 writer.println(errorMsg); 1816 } 1817 } 1818} 1819