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