1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.Manifest; 20 import android.app.ActivityManager; 21 import android.app.AppGlobals; 22 import android.bluetooth.BluetoothAdapter; 23 import android.bluetooth.BluetoothProfile; 24 import android.bluetooth.BluetoothProtoEnums; 25 import android.bluetooth.IBluetooth; 26 import android.bluetooth.IBluetoothCallback; 27 import android.bluetooth.IBluetoothGatt; 28 import android.bluetooth.IBluetoothHeadset; 29 import android.bluetooth.IBluetoothManager; 30 import android.bluetooth.IBluetoothManagerCallback; 31 import android.bluetooth.IBluetoothProfileServiceConnection; 32 import android.bluetooth.IBluetoothStateChangeCallback; 33 import android.content.ActivityNotFoundException; 34 import android.content.BroadcastReceiver; 35 import android.content.ComponentName; 36 import android.content.ContentResolver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.content.ServiceConnection; 41 import android.content.pm.ApplicationInfo; 42 import android.content.pm.IPackageManager; 43 import android.content.pm.PackageManager; 44 import android.content.pm.UserInfo; 45 import android.database.ContentObserver; 46 import android.os.Binder; 47 import android.os.Bundle; 48 import android.os.Handler; 49 import android.os.IBinder; 50 import android.os.Looper; 51 import android.os.Message; 52 import android.os.Process; 53 import android.os.RemoteCallbackList; 54 import android.os.RemoteException; 55 import android.os.SystemClock; 56 import android.os.UserHandle; 57 import android.os.UserManager; 58 import android.os.UserManagerInternal; 59 import android.os.UserManagerInternal.UserRestrictionsListener; 60 import android.provider.Settings; 61 import android.provider.Settings.SettingNotFoundException; 62 import android.util.Slog; 63 import android.util.StatsLog; 64 65 import com.android.internal.R; 66 import com.android.internal.util.DumpUtils; 67 import com.android.server.pm.UserRestrictionsUtils; 68 69 import java.io.FileDescriptor; 70 import java.io.PrintWriter; 71 import java.util.HashMap; 72 import java.util.LinkedList; 73 import java.util.Locale; 74 import java.util.Map; 75 import java.util.concurrent.ConcurrentHashMap; 76 import java.util.concurrent.locks.ReentrantReadWriteLock; 77 78 79 class BluetoothManagerService extends IBluetoothManager.Stub { 80 private static final String TAG = "BluetoothManagerService"; 81 private static final boolean DBG = true; 82 83 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 84 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 85 86 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; 87 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address"; 88 private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name"; 89 90 private static final int ACTIVE_LOG_MAX_SIZE = 20; 91 private static final int CRASH_LOG_MAX_SIZE = 100; 92 93 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 94 //Maximum msec to wait for service restart 95 private static final int SERVICE_RESTART_TIME_MS = 200; 96 //Maximum msec to wait for restart due to error 97 private static final int ERROR_RESTART_TIME_MS = 3000; 98 //Maximum msec to delay MESSAGE_USER_SWITCHED 99 private static final int USER_SWITCHED_TIME_MS = 200; 100 // Delay for the addProxy function in msec 101 private static final int ADD_PROXY_DELAY_MS = 100; 102 103 private static final int MESSAGE_ENABLE = 1; 104 private static final int MESSAGE_DISABLE = 2; 105 private static final int MESSAGE_REGISTER_ADAPTER = 20; 106 private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 107 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 108 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 109 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 110 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 111 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 112 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; 113 private static final int MESSAGE_TIMEOUT_BIND = 100; 114 private static final int MESSAGE_TIMEOUT_UNBIND = 101; 115 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; 116 private static final int MESSAGE_USER_SWITCHED = 300; 117 private static final int MESSAGE_USER_UNLOCKED = 301; 118 private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 119 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 120 private static final int MESSAGE_RESTORE_USER_SETTING = 500; 121 122 private static final int RESTORE_SETTING_TO_ON = 1; 123 private static final int RESTORE_SETTING_TO_OFF = 0; 124 125 private static final int MAX_ERROR_RESTART_RETRIES = 6; 126 127 // Bluetooth persisted setting is off 128 private static final int BLUETOOTH_OFF = 0; 129 // Bluetooth persisted setting is on 130 // and Airplane mode won't affect Bluetooth state at start up 131 private static final int BLUETOOTH_ON_BLUETOOTH = 1; 132 // Bluetooth persisted setting is on 133 // but Airplane mode will affect Bluetooth state at start up 134 // and Airplane mode will have higher priority. 135 private static final int BLUETOOTH_ON_AIRPLANE = 2; 136 137 private static final int SERVICE_IBLUETOOTH = 1; 138 private static final int SERVICE_IBLUETOOTHGATT = 2; 139 140 private final Context mContext; 141 142 // Locks are not provided for mName and mAddress. 143 // They are accessed in handler or broadcast receiver, same thread context. 144 private String mAddress; 145 private String mName; 146 private final ContentResolver mContentResolver; 147 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 148 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 149 private IBinder mBluetoothBinder; 150 private IBluetooth mBluetooth; 151 private IBluetoothGatt mBluetoothGatt; 152 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); 153 private boolean mBinding; 154 private boolean mUnbinding; 155 156 // used inside handler thread 157 private boolean mQuietEnable = false; 158 private boolean mEnable; 159 timeToLog(long timestamp)160 private static CharSequence timeToLog(long timestamp) { 161 return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp); 162 } 163 164 /** 165 * Used for tracking apps that enabled / disabled Bluetooth. 166 */ 167 private class ActiveLog { 168 private int mReason; 169 private String mPackageName; 170 private boolean mEnable; 171 private long mTimestamp; 172 ActiveLog(int reason, String packageName, boolean enable, long timestamp)173 ActiveLog(int reason, String packageName, boolean enable, long timestamp) { 174 mReason = reason; 175 mPackageName = packageName; 176 mEnable = enable; 177 mTimestamp = timestamp; 178 } 179 toString()180 public String toString() { 181 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") 182 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName; 183 } 184 185 } 186 187 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>(); 188 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>(); 189 private int mCrashes; 190 private long mLastEnabledTime; 191 192 // configuration from external IBinder call which is used to 193 // synchronize with broadcast receiver. 194 private boolean mQuietEnableExternal; 195 private boolean mEnableExternal; 196 197 // Map of apps registered to keep BLE scanning on. 198 private Map<IBinder, ClientDeathRecipient> mBleApps = 199 new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); 200 201 private int mState; 202 private final BluetoothHandler mHandler; 203 private int mErrorRecoveryRetryCounter; 204 private final int mSystemUiUid; 205 206 // Save a ProfileServiceConnections object for each of the bound 207 // bluetooth profile services 208 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>(); 209 210 private final boolean mPermissionReviewRequired; 211 212 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 213 @Override 214 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 215 Message msg = 216 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState); 217 mHandler.sendMessage(msg); 218 } 219 }; 220 221 private final UserRestrictionsListener mUserRestrictionsListener = 222 new UserRestrictionsListener() { 223 @Override 224 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, 225 Bundle prevRestrictions) { 226 227 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, 228 UserManager.DISALLOW_BLUETOOTH_SHARING)) { 229 updateOppLauncherComponentState(userId, 230 newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING)); 231 } 232 233 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. 234 if (userId == UserHandle.USER_SYSTEM 235 && UserRestrictionsUtils.restrictionsChanged(prevRestrictions, 236 newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { 237 if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( 238 UserManager.DISALLOW_BLUETOOTH)) { 239 updateOppLauncherComponentState(userId, true); // Sharing disallowed 240 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, 241 mContext.getPackageName()); 242 } else { 243 updateOppLauncherComponentState(userId, newRestrictions.getBoolean( 244 UserManager.DISALLOW_BLUETOOTH_SHARING)); 245 } 246 } 247 } 248 }; 249 250 private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { 251 @Override 252 public void onChange(boolean unused) { 253 synchronized (this) { 254 if (isBluetoothPersistedStateOn()) { 255 if (isAirplaneModeOn()) { 256 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 257 } else { 258 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 259 } 260 } 261 262 int st = BluetoothAdapter.STATE_OFF; 263 try { 264 mBluetoothLock.readLock().lock(); 265 if (mBluetooth != null) { 266 st = mBluetooth.getState(); 267 } 268 } catch (RemoteException e) { 269 Slog.e(TAG, "Unable to call getState", e); 270 return; 271 } finally { 272 mBluetoothLock.readLock().unlock(); 273 } 274 275 Slog.d(TAG, 276 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( 277 st)); 278 279 if (isAirplaneModeOn()) { 280 // Clear registered LE apps to force shut-off 281 clearBleApps(); 282 283 // If state is BLE_ON make sure we trigger disableBLE 284 if (st == BluetoothAdapter.STATE_BLE_ON) { 285 try { 286 mBluetoothLock.readLock().lock(); 287 if (mBluetooth != null) { 288 addActiveLog( 289 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 290 mContext.getPackageName(), false); 291 mBluetooth.onBrEdrDown(); 292 mEnable = false; 293 mEnableExternal = false; 294 } 295 } catch (RemoteException e) { 296 Slog.e(TAG, "Unable to call onBrEdrDown", e); 297 } finally { 298 mBluetoothLock.readLock().unlock(); 299 } 300 } else if (st == BluetoothAdapter.STATE_ON) { 301 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 302 mContext.getPackageName()); 303 } 304 } else if (mEnableExternal) { 305 sendEnableMsg(mQuietEnableExternal, 306 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 307 mContext.getPackageName()); 308 } 309 } 310 } 311 }; 312 313 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 314 @Override 315 public void onReceive(Context context, Intent intent) { 316 String action = intent.getAction(); 317 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 318 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 319 if (DBG) { 320 Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); 321 } 322 if (newName != null) { 323 storeNameAndAddress(newName, null); 324 } 325 } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) { 326 String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS); 327 if (newAddress != null) { 328 if (DBG) { 329 Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress); 330 } 331 storeNameAndAddress(null, newAddress); 332 } else { 333 if (DBG) { 334 Slog.e(TAG, "No Bluetooth Adapter address parameter found"); 335 } 336 } 337 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { 338 final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 339 if (Settings.Global.BLUETOOTH_ON.equals(name)) { 340 // The Bluetooth On state may be changed during system restore. 341 final String prevValue = 342 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE); 343 final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); 344 345 if (DBG) { 346 Slog.d(TAG, 347 "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue 348 + ", newValue=" + newValue); 349 } 350 351 if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) { 352 Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING, 353 newValue.equals("0") ? RESTORE_SETTING_TO_OFF 354 : RESTORE_SETTING_TO_ON, 0); 355 mHandler.sendMessage(msg); 356 } 357 } 358 } 359 } 360 }; 361 BluetoothManagerService(Context context)362 BluetoothManagerService(Context context) { 363 mHandler = new BluetoothHandler(IoThread.get().getLooper()); 364 365 mContext = context; 366 367 mPermissionReviewRequired = context.getResources() 368 .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired); 369 370 mCrashes = 0; 371 mBluetooth = null; 372 mBluetoothBinder = null; 373 mBluetoothGatt = null; 374 mBinding = false; 375 mUnbinding = false; 376 mEnable = false; 377 mState = BluetoothAdapter.STATE_OFF; 378 mQuietEnableExternal = false; 379 mEnableExternal = false; 380 mAddress = null; 381 mName = null; 382 mErrorRecoveryRetryCounter = 0; 383 mContentResolver = context.getContentResolver(); 384 // Observe BLE scan only mode settings change. 385 registerForBleScanModeChange(); 386 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 387 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 388 389 IntentFilter filter = new IntentFilter(); 390 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 391 filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); 392 filter.addAction(Intent.ACTION_SETTING_RESTORED); 393 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 394 mContext.registerReceiver(mReceiver, filter); 395 396 loadStoredNameAndAddress(); 397 if (isBluetoothPersistedStateOn()) { 398 if (DBG) { 399 Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); 400 } 401 mEnableExternal = true; 402 } 403 404 String airplaneModeRadios = 405 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS); 406 if (airplaneModeRadios == null || airplaneModeRadios.contains( 407 Settings.Global.RADIO_BLUETOOTH)) { 408 mContentResolver.registerContentObserver( 409 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, 410 mAirplaneModeObserver); 411 } 412 413 int systemUiUid = -1; 414 try { 415 // Check if device is configured with no home screen, which implies no SystemUI. 416 boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen); 417 if (!noHome) { 418 systemUiUid = mContext.getPackageManager() 419 .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, 420 UserHandle.USER_SYSTEM); 421 } 422 Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid)); 423 } catch (PackageManager.NameNotFoundException e) { 424 // Some platforms, such as wearables do not have a system ui. 425 Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); 426 } 427 mSystemUiUid = systemUiUid; 428 } 429 430 /** 431 * Returns true if airplane mode is currently on 432 */ isAirplaneModeOn()433 private boolean isAirplaneModeOn() { 434 return Settings.Global.getInt(mContext.getContentResolver(), 435 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 436 } 437 supportBluetoothPersistedState()438 private boolean supportBluetoothPersistedState() { 439 return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState); 440 } 441 442 /** 443 * Returns true if the Bluetooth saved state is "on" 444 */ isBluetoothPersistedStateOn()445 private boolean isBluetoothPersistedStateOn() { 446 if (!supportBluetoothPersistedState()) { 447 return false; 448 } 449 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); 450 if (DBG) { 451 Slog.d(TAG, "Bluetooth persisted state: " + state); 452 } 453 return state != BLUETOOTH_OFF; 454 } 455 456 /** 457 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 458 */ isBluetoothPersistedStateOnBluetooth()459 private boolean isBluetoothPersistedStateOnBluetooth() { 460 if (!supportBluetoothPersistedState()) { 461 return false; 462 } 463 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, 464 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; 465 } 466 467 /** 468 * Save the Bluetooth on/off state 469 */ persistBluetoothSetting(int value)470 private void persistBluetoothSetting(int value) { 471 if (DBG) { 472 Slog.d(TAG, "Persisting Bluetooth Setting: " + value); 473 } 474 // waive WRITE_SECURE_SETTINGS permission check 475 long callingIdentity = Binder.clearCallingIdentity(); 476 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); 477 Binder.restoreCallingIdentity(callingIdentity); 478 } 479 480 /** 481 * Returns true if the Bluetooth Adapter's name and address is 482 * locally cached 483 * @return 484 */ isNameAndAddressSet()485 private boolean isNameAndAddressSet() { 486 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0; 487 } 488 489 /** 490 * Retrieve the Bluetooth Adapter's name and address and save it in 491 * in the local cache 492 */ loadStoredNameAndAddress()493 private void loadStoredNameAndAddress() { 494 if (DBG) { 495 Slog.d(TAG, "Loading stored name and address"); 496 } 497 if (mContext.getResources() 498 .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation) 499 && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) 500 == 0) { 501 // if the valid flag is not set, don't load the address and name 502 if (DBG) { 503 Slog.d(TAG, "invalid bluetooth name and address stored"); 504 } 505 return; 506 } 507 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 508 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 509 if (DBG) { 510 Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 511 } 512 } 513 514 /** 515 * Save the Bluetooth name and address in the persistent store. 516 * Only non-null values will be saved. 517 * @param name 518 * @param address 519 */ storeNameAndAddress(String name, String address)520 private void storeNameAndAddress(String name, String address) { 521 if (name != null) { 522 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 523 mName = name; 524 if (DBG) { 525 Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver, 526 SECURE_SETTINGS_BLUETOOTH_NAME)); 527 } 528 } 529 530 if (address != null) { 531 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 532 mAddress = address; 533 if (DBG) { 534 Slog.d(TAG, 535 "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver, 536 SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 537 } 538 } 539 540 if ((name != null) && (address != null)) { 541 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 542 } 543 } 544 registerAdapter(IBluetoothManagerCallback callback)545 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) { 546 if (callback == null) { 547 Slog.w(TAG, "Callback is null in registerAdapter"); 548 return null; 549 } 550 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 551 msg.obj = callback; 552 mHandler.sendMessage(msg); 553 554 return mBluetooth; 555 } 556 unregisterAdapter(IBluetoothManagerCallback callback)557 public void unregisterAdapter(IBluetoothManagerCallback callback) { 558 if (callback == null) { 559 Slog.w(TAG, "Callback is null in unregisterAdapter"); 560 return; 561 } 562 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 563 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 564 msg.obj = callback; 565 mHandler.sendMessage(msg); 566 } 567 registerStateChangeCallback(IBluetoothStateChangeCallback callback)568 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 569 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 570 if (callback == null) { 571 Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); 572 return; 573 } 574 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 575 msg.obj = callback; 576 mHandler.sendMessage(msg); 577 } 578 unregisterStateChangeCallback(IBluetoothStateChangeCallback callback)579 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 580 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 581 if (callback == null) { 582 Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); 583 return; 584 } 585 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 586 msg.obj = callback; 587 mHandler.sendMessage(msg); 588 } 589 isEnabled()590 public boolean isEnabled() { 591 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { 592 Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user"); 593 return false; 594 } 595 596 try { 597 mBluetoothLock.readLock().lock(); 598 if (mBluetooth != null) { 599 return mBluetooth.isEnabled(); 600 } 601 } catch (RemoteException e) { 602 Slog.e(TAG, "isEnabled()", e); 603 } finally { 604 mBluetoothLock.readLock().unlock(); 605 } 606 return false; 607 } 608 getState()609 public int getState() { 610 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { 611 Slog.w(TAG, "getState(): report OFF for non-active and non system user"); 612 return BluetoothAdapter.STATE_OFF; 613 } 614 615 try { 616 mBluetoothLock.readLock().lock(); 617 if (mBluetooth != null) { 618 return mBluetooth.getState(); 619 } 620 } catch (RemoteException e) { 621 Slog.e(TAG, "getState()", e); 622 } finally { 623 mBluetoothLock.readLock().unlock(); 624 } 625 return BluetoothAdapter.STATE_OFF; 626 } 627 628 class ClientDeathRecipient implements IBinder.DeathRecipient { 629 private String mPackageName; 630 ClientDeathRecipient(String packageName)631 ClientDeathRecipient(String packageName) { 632 mPackageName = packageName; 633 } 634 binderDied()635 public void binderDied() { 636 if (DBG) { 637 Slog.d(TAG, "Binder is dead - unregister " + mPackageName); 638 } 639 640 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) { 641 IBinder token = entry.getKey(); 642 ClientDeathRecipient deathRec = entry.getValue(); 643 if (deathRec.equals(this)) { 644 updateBleAppCount(token, false, mPackageName); 645 break; 646 } 647 } 648 } 649 getPackageName()650 public String getPackageName() { 651 return mPackageName; 652 } 653 } 654 655 @Override isBleScanAlwaysAvailable()656 public boolean isBleScanAlwaysAvailable() { 657 if (isAirplaneModeOn() && !mEnable) { 658 return false; 659 } 660 try { 661 return Settings.Global.getInt(mContentResolver, 662 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0; 663 } catch (SettingNotFoundException e) { 664 } 665 return false; 666 } 667 668 // Monitor change of BLE scan only mode settings. registerForBleScanModeChange()669 private void registerForBleScanModeChange() { 670 ContentObserver contentObserver = new ContentObserver(null) { 671 @Override 672 public void onChange(boolean selfChange) { 673 if (isBleScanAlwaysAvailable()) { 674 // Nothing to do 675 return; 676 } 677 // BLE scan is not available. 678 disableBleScanMode(); 679 clearBleApps(); 680 try { 681 mBluetoothLock.readLock().lock(); 682 if (mBluetooth != null) { 683 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 684 mContext.getPackageName(), false); 685 mBluetooth.onBrEdrDown(); 686 } 687 } catch (RemoteException e) { 688 Slog.e(TAG, "error when disabling bluetooth", e); 689 } finally { 690 mBluetoothLock.readLock().unlock(); 691 } 692 } 693 }; 694 695 mContentResolver.registerContentObserver( 696 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false, 697 contentObserver); 698 } 699 700 // Disable ble scan only mode. disableBleScanMode()701 private void disableBleScanMode() { 702 try { 703 mBluetoothLock.writeLock().lock(); 704 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { 705 if (DBG) { 706 Slog.d(TAG, "Reseting the mEnable flag for clean disable"); 707 } 708 mEnable = false; 709 } 710 } catch (RemoteException e) { 711 Slog.e(TAG, "getState()", e); 712 } finally { 713 mBluetoothLock.writeLock().unlock(); 714 } 715 } 716 updateBleAppCount(IBinder token, boolean enable, String packageName)717 public int updateBleAppCount(IBinder token, boolean enable, String packageName) { 718 ClientDeathRecipient r = mBleApps.get(token); 719 if (r == null && enable) { 720 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); 721 try { 722 token.linkToDeath(deathRec, 0); 723 } catch (RemoteException ex) { 724 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!"); 725 } 726 mBleApps.put(token, deathRec); 727 if (DBG) { 728 Slog.d(TAG, "Registered for death of " + packageName); 729 } 730 } else if (!enable && r != null) { 731 // Unregister death recipient as the app goes away. 732 token.unlinkToDeath(r, 0); 733 mBleApps.remove(token); 734 if (DBG) { 735 Slog.d(TAG, "Unregistered for death of " + packageName); 736 } 737 } 738 int appCount = mBleApps.size(); 739 if (DBG) { 740 Slog.d(TAG, appCount + " registered Ble Apps"); 741 } 742 if (appCount == 0 && mEnable) { 743 disableBleScanMode(); 744 } 745 if (appCount == 0 && !mEnableExternal) { 746 sendBrEdrDownCallback(); 747 } 748 return appCount; 749 } 750 751 // Clear all apps using BLE scan only mode. clearBleApps()752 private void clearBleApps() { 753 mBleApps.clear(); 754 } 755 756 /** @hide */ isBleAppPresent()757 public boolean isBleAppPresent() { 758 if (DBG) { 759 Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); 760 } 761 return mBleApps.size() > 0; 762 } 763 764 /** 765 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on. 766 */ continueFromBleOnState()767 private void continueFromBleOnState() { 768 if (DBG) { 769 Slog.d(TAG, "continueFromBleOnState()"); 770 } 771 try { 772 mBluetoothLock.readLock().lock(); 773 if (mBluetooth == null) { 774 Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); 775 return; 776 } 777 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { 778 // This triggers transition to STATE_ON 779 mBluetooth.onLeServiceUp(); 780 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 781 } 782 } catch (RemoteException e) { 783 Slog.e(TAG, "Unable to call onServiceUp", e); 784 } finally { 785 mBluetoothLock.readLock().unlock(); 786 } 787 } 788 789 /** 790 * Inform BluetoothAdapter instances that BREDR part is down 791 * and turn off all service and stack if no LE app needs it 792 */ sendBrEdrDownCallback()793 private void sendBrEdrDownCallback() { 794 if (DBG) { 795 Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks"); 796 } 797 798 if (mBluetooth == null) { 799 Slog.w(TAG, "Bluetooth handle is null"); 800 return; 801 } 802 803 if (isBleAppPresent()) { 804 // Need to stay at BLE ON. Disconnect all Gatt connections 805 try { 806 mBluetoothGatt.unregAll(); 807 } catch (RemoteException e) { 808 Slog.e(TAG, "Unable to disconnect all apps.", e); 809 } 810 } else { 811 try { 812 mBluetoothLock.readLock().lock(); 813 if (mBluetooth != null) { 814 mBluetooth.onBrEdrDown(); 815 } 816 } catch (RemoteException e) { 817 Slog.e(TAG, "Call to onBrEdrDown() failed.", e); 818 } finally { 819 mBluetoothLock.readLock().unlock(); 820 } 821 } 822 823 } 824 enableNoAutoConnect(String packageName)825 public boolean enableNoAutoConnect(String packageName) { 826 if (isBluetoothDisallowed()) { 827 if (DBG) { 828 Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); 829 } 830 return false; 831 } 832 833 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 834 "Need BLUETOOTH ADMIN permission"); 835 836 if (DBG) { 837 Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " 838 + mBinding); 839 } 840 int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 841 842 if (callingAppId != Process.NFC_UID) { 843 throw new SecurityException("no permission to enable Bluetooth quietly"); 844 } 845 846 synchronized (mReceiver) { 847 mQuietEnableExternal = true; 848 mEnableExternal = true; 849 sendEnableMsg(true, 850 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); 851 } 852 return true; 853 } 854 enable(String packageName)855 public boolean enable(String packageName) throws RemoteException { 856 final int callingUid = Binder.getCallingUid(); 857 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; 858 859 if (isBluetoothDisallowed()) { 860 if (DBG) { 861 Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); 862 } 863 return false; 864 } 865 866 if (!callerSystem) { 867 if (!checkIfCallerIsForegroundUser()) { 868 Slog.w(TAG, "enable(): not allowed for non-active and non system user"); 869 return false; 870 } 871 872 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 873 "Need BLUETOOTH ADMIN permission"); 874 875 if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, 876 callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { 877 return false; 878 } 879 } 880 881 if (DBG) { 882 Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = " 883 + mBinding + " mState = " + BluetoothAdapter.nameForState(mState)); 884 } 885 886 synchronized (mReceiver) { 887 mQuietEnableExternal = false; 888 mEnableExternal = true; 889 // waive WRITE_SECURE_SETTINGS permission check 890 sendEnableMsg(false, 891 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); 892 } 893 if (DBG) { 894 Slog.d(TAG, "enable returning"); 895 } 896 return true; 897 } 898 disable(String packageName, boolean persist)899 public boolean disable(String packageName, boolean persist) throws RemoteException { 900 final int callingUid = Binder.getCallingUid(); 901 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; 902 903 if (!callerSystem) { 904 if (!checkIfCallerIsForegroundUser()) { 905 Slog.w(TAG, "disable(): not allowed for non-active and non system user"); 906 return false; 907 } 908 909 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 910 "Need BLUETOOTH ADMIN permission"); 911 912 if (isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, 913 callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { 914 return false; 915 } 916 } 917 918 if (DBG) { 919 Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding); 920 } 921 922 synchronized (mReceiver) { 923 if (persist) { 924 persistBluetoothSetting(BLUETOOTH_OFF); 925 } 926 mEnableExternal = false; 927 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 928 packageName); 929 } 930 return true; 931 } 932 startConsentUiIfNeeded(String packageName, int callingUid, String intentAction)933 private boolean startConsentUiIfNeeded(String packageName, 934 int callingUid, String intentAction) throws RemoteException { 935 if (checkBluetoothPermissionWhenPermissionReviewRequired()) { 936 return false; 937 } 938 try { 939 // Validate the package only if we are going to use it 940 ApplicationInfo applicationInfo = mContext.getPackageManager() 941 .getApplicationInfoAsUser(packageName, 942 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 943 UserHandle.getUserId(callingUid)); 944 if (applicationInfo.uid != callingUid) { 945 throw new SecurityException("Package " + packageName 946 + " not in uid " + callingUid); 947 } 948 949 Intent intent = new Intent(intentAction); 950 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 951 intent.setFlags( 952 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 953 try { 954 mContext.startActivity(intent); 955 } catch (ActivityNotFoundException e) { 956 // Shouldn't happen 957 Slog.e(TAG, "Intent to handle action " + intentAction + " missing"); 958 return false; 959 } 960 return true; 961 } catch (PackageManager.NameNotFoundException e) { 962 throw new RemoteException(e.getMessage()); 963 } 964 } 965 966 /** 967 * Check if the caller must still pass permission check or if the caller is exempted 968 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check. 969 * 970 * Commands from some callers may be exempted from triggering the consent UI when 971 * enabling bluetooth. This exemption is checked via the 972 * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip 973 * the consent UI where it may otherwise be required. 974 * 975 * @hide 976 */ checkBluetoothPermissionWhenPermissionReviewRequired()977 private boolean checkBluetoothPermissionWhenPermissionReviewRequired() { 978 if (!mPermissionReviewRequired) { 979 return false; 980 } 981 int result = mContext.checkCallingPermission( 982 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED); 983 return result == PackageManager.PERMISSION_GRANTED; 984 } 985 unbindAndFinish()986 public void unbindAndFinish() { 987 if (DBG) { 988 Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding 989 + " mUnbinding = " + mUnbinding); 990 } 991 992 try { 993 mBluetoothLock.writeLock().lock(); 994 if (mUnbinding) { 995 return; 996 } 997 mUnbinding = true; 998 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 999 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); 1000 if (mBluetooth != null) { 1001 //Unregister callback object 1002 try { 1003 mBluetooth.unregisterCallback(mBluetoothCallback); 1004 } catch (RemoteException re) { 1005 Slog.e(TAG, "Unable to unregister BluetoothCallback", re); 1006 } 1007 mBluetoothBinder = null; 1008 mBluetooth = null; 1009 mContext.unbindService(mConnection); 1010 mUnbinding = false; 1011 mBinding = false; 1012 } else { 1013 mUnbinding = false; 1014 } 1015 mBluetoothGatt = null; 1016 } finally { 1017 mBluetoothLock.writeLock().unlock(); 1018 } 1019 } 1020 getBluetoothGatt()1021 public IBluetoothGatt getBluetoothGatt() { 1022 // sync protection 1023 return mBluetoothGatt; 1024 } 1025 1026 @Override bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy)1027 public boolean bindBluetoothProfileService(int bluetoothProfile, 1028 IBluetoothProfileServiceConnection proxy) { 1029 if (!mEnable) { 1030 if (DBG) { 1031 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile 1032 + ", while Bluetooth was disabled"); 1033 } 1034 return false; 1035 } 1036 synchronized (mProfileServices) { 1037 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 1038 if (psc == null) { 1039 if (DBG) { 1040 Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " 1041 + bluetoothProfile); 1042 } 1043 1044 if (bluetoothProfile != BluetoothProfile.HEADSET) { 1045 return false; 1046 } 1047 1048 Intent intent = new Intent(IBluetoothHeadset.class.getName()); 1049 psc = new ProfileServiceConnections(intent); 1050 if (!psc.bindService()) { 1051 return false; 1052 } 1053 1054 mProfileServices.put(new Integer(bluetoothProfile), psc); 1055 } 1056 } 1057 1058 // Introducing a delay to give the client app time to prepare 1059 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 1060 addProxyMsg.arg1 = bluetoothProfile; 1061 addProxyMsg.obj = proxy; 1062 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 1063 return true; 1064 } 1065 1066 @Override unbindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy)1067 public void unbindBluetoothProfileService(int bluetoothProfile, 1068 IBluetoothProfileServiceConnection proxy) { 1069 synchronized (mProfileServices) { 1070 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 1071 if (psc == null) { 1072 return; 1073 } 1074 psc.removeProxy(proxy); 1075 } 1076 } 1077 unbindAllBluetoothProfileServices()1078 private void unbindAllBluetoothProfileServices() { 1079 synchronized (mProfileServices) { 1080 for (Integer i : mProfileServices.keySet()) { 1081 ProfileServiceConnections psc = mProfileServices.get(i); 1082 try { 1083 mContext.unbindService(psc); 1084 } catch (IllegalArgumentException e) { 1085 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 1086 } 1087 psc.removeAllProxies(); 1088 } 1089 mProfileServices.clear(); 1090 } 1091 } 1092 1093 /** 1094 * Send enable message and set adapter name and address. Called when the boot phase becomes 1095 * PHASE_SYSTEM_SERVICES_READY. 1096 */ handleOnBootPhase()1097 public void handleOnBootPhase() { 1098 if (DBG) { 1099 Slog.d(TAG, "Bluetooth boot completed"); 1100 } 1101 UserManagerInternal userManagerInternal = 1102 LocalServices.getService(UserManagerInternal.class); 1103 userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); 1104 final boolean isBluetoothDisallowed = isBluetoothDisallowed(); 1105 if (isBluetoothDisallowed) { 1106 return; 1107 } 1108 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 1109 if (DBG) { 1110 Slog.d(TAG, "Auto-enabling Bluetooth."); 1111 } 1112 sendEnableMsg(mQuietEnableExternal, 1113 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT, 1114 mContext.getPackageName()); 1115 } else if (!isNameAndAddressSet()) { 1116 if (DBG) { 1117 Slog.d(TAG, "Getting adapter name and address"); 1118 } 1119 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1120 mHandler.sendMessage(getMsg); 1121 } 1122 } 1123 1124 /** 1125 * Called when switching to a different foreground user. 1126 */ handleOnSwitchUser(int userHandle)1127 public void handleOnSwitchUser(int userHandle) { 1128 if (DBG) { 1129 Slog.d(TAG, "User " + userHandle + " switched"); 1130 } 1131 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 1132 } 1133 1134 /** 1135 * Called when user is unlocked. 1136 */ handleOnUnlockUser(int userHandle)1137 public void handleOnUnlockUser(int userHandle) { 1138 if (DBG) { 1139 Slog.d(TAG, "User " + userHandle + " unlocked"); 1140 } 1141 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 1142 } 1143 1144 /** 1145 * This class manages the clients connected to a given ProfileService 1146 * and maintains the connection with that service. 1147 */ 1148 private final class ProfileServiceConnections 1149 implements ServiceConnection, IBinder.DeathRecipient { 1150 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 1151 new RemoteCallbackList<IBluetoothProfileServiceConnection>(); 1152 IBinder mService; 1153 ComponentName mClassName; 1154 Intent mIntent; 1155 boolean mInvokingProxyCallbacks = false; 1156 ProfileServiceConnections(Intent intent)1157 ProfileServiceConnections(Intent intent) { 1158 mService = null; 1159 mClassName = null; 1160 mIntent = intent; 1161 } 1162 bindService()1163 private boolean bindService() { 1164 if (mIntent != null && mService == null && doBind(mIntent, this, 0, 1165 UserHandle.CURRENT_OR_SELF)) { 1166 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1167 msg.obj = this; 1168 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 1169 return true; 1170 } 1171 Slog.w(TAG, "Unable to bind with intent: " + mIntent); 1172 return false; 1173 } 1174 addProxy(IBluetoothProfileServiceConnection proxy)1175 private void addProxy(IBluetoothProfileServiceConnection proxy) { 1176 mProxies.register(proxy); 1177 if (mService != null) { 1178 try { 1179 proxy.onServiceConnected(mClassName, mService); 1180 } catch (RemoteException e) { 1181 Slog.e(TAG, "Unable to connect to proxy", e); 1182 } 1183 } else { 1184 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 1185 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1186 msg.obj = this; 1187 mHandler.sendMessage(msg); 1188 } 1189 } 1190 } 1191 removeProxy(IBluetoothProfileServiceConnection proxy)1192 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 1193 if (proxy != null) { 1194 if (mProxies.unregister(proxy)) { 1195 try { 1196 proxy.onServiceDisconnected(mClassName); 1197 } catch (RemoteException e) { 1198 Slog.e(TAG, "Unable to disconnect proxy", e); 1199 } 1200 } 1201 } else { 1202 Slog.w(TAG, "Trying to remove a null proxy"); 1203 } 1204 } 1205 removeAllProxies()1206 private void removeAllProxies() { 1207 onServiceDisconnected(mClassName); 1208 mProxies.kill(); 1209 } 1210 1211 @Override onServiceConnected(ComponentName className, IBinder service)1212 public void onServiceConnected(ComponentName className, IBinder service) { 1213 // remove timeout message 1214 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 1215 mService = service; 1216 mClassName = className; 1217 try { 1218 mService.linkToDeath(this, 0); 1219 } catch (RemoteException e) { 1220 Slog.e(TAG, "Unable to linkToDeath", e); 1221 } 1222 1223 if (mInvokingProxyCallbacks) { 1224 Slog.e(TAG, "Proxy callbacks already in progress."); 1225 return; 1226 } 1227 mInvokingProxyCallbacks = true; 1228 1229 final int n = mProxies.beginBroadcast(); 1230 try { 1231 for (int i = 0; i < n; i++) { 1232 try { 1233 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 1234 } catch (RemoteException e) { 1235 Slog.e(TAG, "Unable to connect to proxy", e); 1236 } 1237 } 1238 } finally { 1239 mProxies.finishBroadcast(); 1240 mInvokingProxyCallbacks = false; 1241 } 1242 } 1243 1244 @Override onServiceDisconnected(ComponentName className)1245 public void onServiceDisconnected(ComponentName className) { 1246 if (mService == null) { 1247 return; 1248 } 1249 mService.unlinkToDeath(this, 0); 1250 mService = null; 1251 mClassName = null; 1252 1253 if (mInvokingProxyCallbacks) { 1254 Slog.e(TAG, "Proxy callbacks already in progress."); 1255 return; 1256 } 1257 mInvokingProxyCallbacks = true; 1258 1259 final int n = mProxies.beginBroadcast(); 1260 try { 1261 for (int i = 0; i < n; i++) { 1262 try { 1263 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 1264 } catch (RemoteException e) { 1265 Slog.e(TAG, "Unable to disconnect from proxy", e); 1266 } 1267 } 1268 } finally { 1269 mProxies.finishBroadcast(); 1270 mInvokingProxyCallbacks = false; 1271 } 1272 } 1273 1274 @Override binderDied()1275 public void binderDied() { 1276 if (DBG) { 1277 Slog.w(TAG, "Profile service for profile: " + mClassName + " died."); 1278 } 1279 onServiceDisconnected(mClassName); 1280 // Trigger rebind 1281 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1282 msg.obj = this; 1283 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 1284 } 1285 } 1286 sendBluetoothStateCallback(boolean isUp)1287 private void sendBluetoothStateCallback(boolean isUp) { 1288 try { 1289 int n = mStateChangeCallbacks.beginBroadcast(); 1290 if (DBG) { 1291 Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n 1292 + " receivers."); 1293 } 1294 for (int i = 0; i < n; i++) { 1295 try { 1296 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 1297 } catch (RemoteException e) { 1298 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e); 1299 } 1300 } 1301 } finally { 1302 mStateChangeCallbacks.finishBroadcast(); 1303 } 1304 } 1305 1306 /** 1307 * Inform BluetoothAdapter instances that Adapter service is up 1308 */ sendBluetoothServiceUpCallback()1309 private void sendBluetoothServiceUpCallback() { 1310 try { 1311 int n = mCallbacks.beginBroadcast(); 1312 Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 1313 for (int i = 0; i < n; i++) { 1314 try { 1315 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 1316 } catch (RemoteException e) { 1317 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 1318 } 1319 } 1320 } finally { 1321 mCallbacks.finishBroadcast(); 1322 } 1323 } 1324 1325 /** 1326 * Inform BluetoothAdapter instances that Adapter service is down 1327 */ sendBluetoothServiceDownCallback()1328 private void sendBluetoothServiceDownCallback() { 1329 try { 1330 int n = mCallbacks.beginBroadcast(); 1331 Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1332 for (int i = 0; i < n; i++) { 1333 try { 1334 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1335 } catch (RemoteException e) { 1336 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1337 } 1338 } 1339 } finally { 1340 mCallbacks.finishBroadcast(); 1341 } 1342 } 1343 getAddress()1344 public String getAddress() { 1345 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1346 1347 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { 1348 Slog.w(TAG, "getAddress(): not allowed for non-active and non system user"); 1349 return null; 1350 } 1351 1352 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1353 != PackageManager.PERMISSION_GRANTED) { 1354 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1355 } 1356 1357 try { 1358 mBluetoothLock.readLock().lock(); 1359 if (mBluetooth != null) { 1360 return mBluetooth.getAddress(); 1361 } 1362 } catch (RemoteException e) { 1363 Slog.e(TAG, 1364 "getAddress(): Unable to retrieve address remotely. Returning cached address", 1365 e); 1366 } finally { 1367 mBluetoothLock.readLock().unlock(); 1368 } 1369 1370 // mAddress is accessed from outside. 1371 // It is alright without a lock. Here, bluetooth is off, no other thread is 1372 // changing mAddress 1373 return mAddress; 1374 } 1375 getName()1376 public String getName() { 1377 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1378 1379 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { 1380 Slog.w(TAG, "getName(): not allowed for non-active and non system user"); 1381 return null; 1382 } 1383 1384 try { 1385 mBluetoothLock.readLock().lock(); 1386 if (mBluetooth != null) { 1387 return mBluetooth.getName(); 1388 } 1389 } catch (RemoteException e) { 1390 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1391 } finally { 1392 mBluetoothLock.readLock().unlock(); 1393 } 1394 1395 // mName is accessed from outside. 1396 // It alright without a lock. Here, bluetooth is off, no other thread is 1397 // changing mName 1398 return mName; 1399 } 1400 1401 private class BluetoothServiceConnection implements ServiceConnection { onServiceConnected(ComponentName componentName, IBinder service)1402 public void onServiceConnected(ComponentName componentName, IBinder service) { 1403 String name = componentName.getClassName(); 1404 if (DBG) { 1405 Slog.d(TAG, "BluetoothServiceConnection: " + name); 1406 } 1407 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1408 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 1409 msg.arg1 = SERVICE_IBLUETOOTH; 1410 } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 1411 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1412 } else { 1413 Slog.e(TAG, "Unknown service connected: " + name); 1414 return; 1415 } 1416 msg.obj = service; 1417 mHandler.sendMessage(msg); 1418 } 1419 onServiceDisconnected(ComponentName componentName)1420 public void onServiceDisconnected(ComponentName componentName) { 1421 // Called if we unexpectedly disconnect. 1422 String name = componentName.getClassName(); 1423 if (DBG) { 1424 Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); 1425 } 1426 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1427 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 1428 msg.arg1 = SERVICE_IBLUETOOTH; 1429 } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 1430 msg.arg1 = SERVICE_IBLUETOOTHGATT; 1431 } else { 1432 Slog.e(TAG, "Unknown service disconnected: " + name); 1433 return; 1434 } 1435 mHandler.sendMessage(msg); 1436 } 1437 } 1438 1439 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 1440 1441 private class BluetoothHandler extends Handler { 1442 boolean mGetNameAddressOnly = false; 1443 BluetoothHandler(Looper looper)1444 BluetoothHandler(Looper looper) { 1445 super(looper); 1446 } 1447 1448 @Override handleMessage(Message msg)1449 public void handleMessage(Message msg) { 1450 switch (msg.what) { 1451 case MESSAGE_GET_NAME_AND_ADDRESS: 1452 if (DBG) { 1453 Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1454 } 1455 try { 1456 mBluetoothLock.writeLock().lock(); 1457 if ((mBluetooth == null) && (!mBinding)) { 1458 if (DBG) { 1459 Slog.d(TAG, "Binding to service to get name and address"); 1460 } 1461 mGetNameAddressOnly = true; 1462 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1463 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 1464 Intent i = new Intent(IBluetooth.class.getName()); 1465 if (!doBind(i, mConnection, 1466 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1467 UserHandle.CURRENT)) { 1468 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1469 } else { 1470 mBinding = true; 1471 } 1472 } else if (mBluetooth != null) { 1473 try { 1474 storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress()); 1475 } catch (RemoteException re) { 1476 Slog.e(TAG, "Unable to grab names", re); 1477 } 1478 if (mGetNameAddressOnly && !mEnable) { 1479 unbindAndFinish(); 1480 } 1481 mGetNameAddressOnly = false; 1482 } 1483 } finally { 1484 mBluetoothLock.writeLock().unlock(); 1485 } 1486 break; 1487 1488 case MESSAGE_ENABLE: 1489 if (DBG) { 1490 Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); 1491 } 1492 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1493 mEnable = true; 1494 1495 // Use service interface to get the exact state 1496 try { 1497 mBluetoothLock.readLock().lock(); 1498 if (mBluetooth != null) { 1499 int state = mBluetooth.getState(); 1500 if (state == BluetoothAdapter.STATE_BLE_ON) { 1501 Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); 1502 mBluetooth.onLeServiceUp(); 1503 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 1504 break; 1505 } 1506 } 1507 } catch (RemoteException e) { 1508 Slog.e(TAG, "", e); 1509 } finally { 1510 mBluetoothLock.readLock().unlock(); 1511 } 1512 1513 mQuietEnable = (msg.arg1 == 1); 1514 if (mBluetooth == null) { 1515 handleEnable(mQuietEnable); 1516 } else { 1517 // 1518 // We need to wait until transitioned to STATE_OFF and 1519 // the previous Bluetooth process has exited. The 1520 // waiting period has three components: 1521 // (a) Wait until the local state is STATE_OFF. This 1522 // is accomplished by "waitForOnOff(false, true)". 1523 // (b) Wait until the STATE_OFF state is updated to 1524 // all components. 1525 // (c) Wait until the Bluetooth process exits, and 1526 // ActivityManager detects it. 1527 // The waiting for (b) and (c) is accomplished by 1528 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 1529 // message. On slower devices, that delay needs to be 1530 // on the order of (2 * SERVICE_RESTART_TIME_MS). 1531 // 1532 waitForOnOff(false, true); 1533 Message restartMsg = 1534 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1535 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); 1536 } 1537 break; 1538 1539 case MESSAGE_DISABLE: 1540 if (DBG) { 1541 Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); 1542 } 1543 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1544 if (mEnable && mBluetooth != null) { 1545 waitForOnOff(true, false); 1546 mEnable = false; 1547 handleDisable(); 1548 waitForOnOff(false, false); 1549 } else { 1550 mEnable = false; 1551 handleDisable(); 1552 } 1553 break; 1554 1555 case MESSAGE_RESTORE_USER_SETTING: 1556 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { 1557 if (DBG) { 1558 Slog.d(TAG, "Restore Bluetooth state to disabled"); 1559 } 1560 persistBluetoothSetting(BLUETOOTH_OFF); 1561 mEnableExternal = false; 1562 sendDisableMsg( 1563 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, 1564 mContext.getPackageName()); 1565 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { 1566 if (DBG) { 1567 Slog.d(TAG, "Restore Bluetooth state to enabled"); 1568 } 1569 mQuietEnableExternal = false; 1570 mEnableExternal = true; 1571 // waive WRITE_SECURE_SETTINGS permission check 1572 sendEnableMsg(false, 1573 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, 1574 mContext.getPackageName()); 1575 } 1576 break; 1577 1578 case MESSAGE_REGISTER_ADAPTER: { 1579 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1580 mCallbacks.register(callback); 1581 break; 1582 } 1583 case MESSAGE_UNREGISTER_ADAPTER: { 1584 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1585 mCallbacks.unregister(callback); 1586 break; 1587 } 1588 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { 1589 IBluetoothStateChangeCallback callback = 1590 (IBluetoothStateChangeCallback) msg.obj; 1591 mStateChangeCallbacks.register(callback); 1592 break; 1593 } 1594 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: { 1595 IBluetoothStateChangeCallback callback = 1596 (IBluetoothStateChangeCallback) msg.obj; 1597 mStateChangeCallbacks.unregister(callback); 1598 break; 1599 } 1600 case MESSAGE_ADD_PROXY_DELAYED: { 1601 ProfileServiceConnections psc = mProfileServices.get(msg.arg1); 1602 if (psc == null) { 1603 break; 1604 } 1605 IBluetoothProfileServiceConnection proxy = 1606 (IBluetoothProfileServiceConnection) msg.obj; 1607 psc.addProxy(proxy); 1608 break; 1609 } 1610 case MESSAGE_BIND_PROFILE_SERVICE: { 1611 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1612 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1613 if (psc == null) { 1614 break; 1615 } 1616 psc.bindService(); 1617 break; 1618 } 1619 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { 1620 if (DBG) { 1621 Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 1622 } 1623 1624 IBinder service = (IBinder) msg.obj; 1625 try { 1626 mBluetoothLock.writeLock().lock(); 1627 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1628 mBluetoothGatt = 1629 IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service)); 1630 continueFromBleOnState(); 1631 break; 1632 } // else must be SERVICE_IBLUETOOTH 1633 1634 //Remove timeout 1635 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1636 1637 mBinding = false; 1638 mBluetoothBinder = service; 1639 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service)); 1640 1641 if (!isNameAndAddressSet()) { 1642 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1643 mHandler.sendMessage(getMsg); 1644 if (mGetNameAddressOnly) { 1645 return; 1646 } 1647 } 1648 1649 //Register callback object 1650 try { 1651 mBluetooth.registerCallback(mBluetoothCallback); 1652 } catch (RemoteException re) { 1653 Slog.e(TAG, "Unable to register BluetoothCallback", re); 1654 } 1655 //Inform BluetoothAdapter instances that service is up 1656 sendBluetoothServiceUpCallback(); 1657 1658 //Do enable request 1659 try { 1660 if (!mQuietEnable) { 1661 if (!mBluetooth.enable()) { 1662 Slog.e(TAG, "IBluetooth.enable() returned false"); 1663 } 1664 } else { 1665 if (!mBluetooth.enableNoAutoConnect()) { 1666 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false"); 1667 } 1668 } 1669 } catch (RemoteException e) { 1670 Slog.e(TAG, "Unable to call enable()", e); 1671 } 1672 } finally { 1673 mBluetoothLock.writeLock().unlock(); 1674 } 1675 1676 if (!mEnable) { 1677 waitForOnOff(true, false); 1678 handleDisable(); 1679 waitForOnOff(false, false); 1680 } 1681 break; 1682 } 1683 case MESSAGE_BLUETOOTH_STATE_CHANGE: { 1684 int prevState = msg.arg1; 1685 int newState = msg.arg2; 1686 if (DBG) { 1687 Slog.d(TAG, 1688 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState( 1689 prevState) + " > " + BluetoothAdapter.nameForState( 1690 newState)); 1691 } 1692 mState = newState; 1693 bluetoothStateChangeHandler(prevState, newState); 1694 // handle error state transition case from TURNING_ON to OFF 1695 // unbind and rebind bluetooth service and enable bluetooth 1696 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState 1697 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { 1698 recoverBluetoothServiceFromError(false); 1699 } 1700 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState 1701 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { 1702 recoverBluetoothServiceFromError(true); 1703 } 1704 // If we tried to enable BT while BT was in the process of shutting down, 1705 // wait for the BT process to fully tear down and then force a restart 1706 // here. This is a bit of a hack (b/29363429). 1707 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState 1708 == BluetoothAdapter.STATE_OFF)) { 1709 if (mEnable) { 1710 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); 1711 waitForOnOff(false, true); 1712 Message restartMsg = 1713 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1714 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); 1715 } 1716 } 1717 if (newState == BluetoothAdapter.STATE_ON 1718 || newState == BluetoothAdapter.STATE_BLE_ON) { 1719 // bluetooth is working, reset the counter 1720 if (mErrorRecoveryRetryCounter != 0) { 1721 Slog.w(TAG, "bluetooth is recovered from error"); 1722 mErrorRecoveryRetryCounter = 0; 1723 } 1724 } 1725 break; 1726 } 1727 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { 1728 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); 1729 try { 1730 mBluetoothLock.writeLock().lock(); 1731 if (msg.arg1 == SERVICE_IBLUETOOTH) { 1732 // if service is unbinded already, do nothing and return 1733 if (mBluetooth == null) { 1734 break; 1735 } 1736 mBluetooth = null; 1737 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1738 mBluetoothGatt = null; 1739 break; 1740 } else { 1741 Slog.e(TAG, "Unknown argument for service disconnect!"); 1742 break; 1743 } 1744 } finally { 1745 mBluetoothLock.writeLock().unlock(); 1746 } 1747 1748 // log the unexpected crash 1749 addCrashLog(); 1750 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH, 1751 mContext.getPackageName(), false); 1752 if (mEnable) { 1753 mEnable = false; 1754 // Send a Bluetooth Restart message 1755 Message restartMsg = 1756 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 1757 mHandler.sendMessageDelayed(restartMsg, SERVICE_RESTART_TIME_MS); 1758 } 1759 1760 sendBluetoothServiceDownCallback(); 1761 1762 // Send BT state broadcast to update 1763 // the BT icon correctly 1764 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState 1765 == BluetoothAdapter.STATE_ON)) { 1766 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1767 BluetoothAdapter.STATE_TURNING_OFF); 1768 mState = BluetoothAdapter.STATE_TURNING_OFF; 1769 } 1770 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1771 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1772 BluetoothAdapter.STATE_OFF); 1773 } 1774 1775 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1776 mState = BluetoothAdapter.STATE_OFF; 1777 break; 1778 } 1779 case MESSAGE_RESTART_BLUETOOTH_SERVICE: { 1780 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); 1781 /* Enable without persisting the setting as 1782 it doesnt change when IBluetooth 1783 service restarts */ 1784 mEnable = true; 1785 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, 1786 mContext.getPackageName(), true); 1787 handleEnable(mQuietEnable); 1788 break; 1789 } 1790 case MESSAGE_TIMEOUT_BIND: { 1791 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1792 mBluetoothLock.writeLock().lock(); 1793 mBinding = false; 1794 mBluetoothLock.writeLock().unlock(); 1795 break; 1796 } 1797 case MESSAGE_TIMEOUT_UNBIND: { 1798 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1799 mBluetoothLock.writeLock().lock(); 1800 mUnbinding = false; 1801 mBluetoothLock.writeLock().unlock(); 1802 break; 1803 } 1804 1805 case MESSAGE_USER_SWITCHED: { 1806 if (DBG) { 1807 Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 1808 } 1809 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1810 1811 /* disable and enable BT when detect a user switch */ 1812 if (mBluetooth != null && isEnabled()) { 1813 try { 1814 mBluetoothLock.readLock().lock(); 1815 if (mBluetooth != null) { 1816 mBluetooth.unregisterCallback(mBluetoothCallback); 1817 } 1818 } catch (RemoteException re) { 1819 Slog.e(TAG, "Unable to unregister", re); 1820 } finally { 1821 mBluetoothLock.readLock().unlock(); 1822 } 1823 1824 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1825 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 1826 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 1827 mState = BluetoothAdapter.STATE_OFF; 1828 } 1829 if (mState == BluetoothAdapter.STATE_OFF) { 1830 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 1831 mState = BluetoothAdapter.STATE_TURNING_ON; 1832 } 1833 1834 waitForOnOff(true, false); 1835 1836 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 1837 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 1838 } 1839 1840 unbindAllBluetoothProfileServices(); 1841 // disable 1842 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, 1843 mContext.getPackageName(), false); 1844 handleDisable(); 1845 // Pbap service need receive STATE_TURNING_OFF intent to close 1846 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1847 BluetoothAdapter.STATE_TURNING_OFF); 1848 1849 boolean didDisableTimeout = !waitForOnOff(false, true); 1850 1851 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1852 BluetoothAdapter.STATE_OFF); 1853 sendBluetoothServiceDownCallback(); 1854 1855 try { 1856 mBluetoothLock.writeLock().lock(); 1857 if (mBluetooth != null) { 1858 mBluetooth = null; 1859 // Unbind 1860 mContext.unbindService(mConnection); 1861 } 1862 mBluetoothGatt = null; 1863 } finally { 1864 mBluetoothLock.writeLock().unlock(); 1865 } 1866 1867 // 1868 // If disabling Bluetooth times out, wait for an 1869 // additional amount of time to ensure the process is 1870 // shut down completely before attempting to restart. 1871 // 1872 if (didDisableTimeout) { 1873 SystemClock.sleep(3000); 1874 } else { 1875 SystemClock.sleep(100); 1876 } 1877 1878 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1879 mState = BluetoothAdapter.STATE_OFF; 1880 // enable 1881 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, 1882 mContext.getPackageName(), true); 1883 // mEnable flag could have been reset on disableBLE. Reenable it. 1884 mEnable = true; 1885 handleEnable(mQuietEnable); 1886 } else if (mBinding || mBluetooth != null) { 1887 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 1888 userMsg.arg2 = 1 + msg.arg2; 1889 // if user is switched when service is binding retry after a delay 1890 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 1891 if (DBG) { 1892 Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2); 1893 } 1894 } 1895 break; 1896 } 1897 case MESSAGE_USER_UNLOCKED: { 1898 if (DBG) { 1899 Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1900 } 1901 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1902 1903 if (mEnable && !mBinding && (mBluetooth == null)) { 1904 // We should be connected, but we gave up for some 1905 // reason; maybe the Bluetooth service wasn't encryption 1906 // aware, so try binding again. 1907 if (DBG) { 1908 Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1909 } 1910 handleEnable(mQuietEnable); 1911 } 1912 } 1913 } 1914 } 1915 } 1916 handleEnable(boolean quietMode)1917 private void handleEnable(boolean quietMode) { 1918 mQuietEnable = quietMode; 1919 1920 try { 1921 mBluetoothLock.writeLock().lock(); 1922 if ((mBluetooth == null) && (!mBinding)) { 1923 //Start bind timeout and bind 1924 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1925 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 1926 Intent i = new Intent(IBluetooth.class.getName()); 1927 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1928 UserHandle.CURRENT)) { 1929 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1930 } else { 1931 mBinding = true; 1932 } 1933 } else if (mBluetooth != null) { 1934 //Enable bluetooth 1935 try { 1936 if (!mQuietEnable) { 1937 if (!mBluetooth.enable()) { 1938 Slog.e(TAG, "IBluetooth.enable() returned false"); 1939 } 1940 } else { 1941 if (!mBluetooth.enableNoAutoConnect()) { 1942 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false"); 1943 } 1944 } 1945 } catch (RemoteException e) { 1946 Slog.e(TAG, "Unable to call enable()", e); 1947 } 1948 } 1949 } finally { 1950 mBluetoothLock.writeLock().unlock(); 1951 } 1952 } 1953 doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user)1954 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1955 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1956 intent.setComponent(comp); 1957 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1958 Slog.e(TAG, "Fail to bind to: " + intent); 1959 return false; 1960 } 1961 return true; 1962 } 1963 handleDisable()1964 private void handleDisable() { 1965 try { 1966 mBluetoothLock.readLock().lock(); 1967 if (mBluetooth != null) { 1968 if (DBG) { 1969 Slog.d(TAG, "Sending off request."); 1970 } 1971 if (!mBluetooth.disable()) { 1972 Slog.e(TAG, "IBluetooth.disable() returned false"); 1973 } 1974 } 1975 } catch (RemoteException e) { 1976 Slog.e(TAG, "Unable to call disable()", e); 1977 } finally { 1978 mBluetoothLock.readLock().unlock(); 1979 } 1980 } 1981 checkIfCallerIsForegroundUser()1982 private boolean checkIfCallerIsForegroundUser() { 1983 int foregroundUser; 1984 int callingUser = UserHandle.getCallingUserId(); 1985 int callingUid = Binder.getCallingUid(); 1986 long callingIdentity = Binder.clearCallingIdentity(); 1987 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1988 UserInfo ui = um.getProfileParent(callingUser); 1989 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 1990 int callingAppId = UserHandle.getAppId(callingUid); 1991 boolean valid = false; 1992 try { 1993 foregroundUser = ActivityManager.getCurrentUser(); 1994 valid = (callingUser == foregroundUser) || parentUser == foregroundUser 1995 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; 1996 if (DBG && !valid) { 1997 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" 1998 + callingUser + " parentUser=" + parentUser + " foregroundUser=" 1999 + foregroundUser); 2000 } 2001 } finally { 2002 Binder.restoreCallingIdentity(callingIdentity); 2003 } 2004 return valid; 2005 } 2006 sendBleStateChanged(int prevState, int newState)2007 private void sendBleStateChanged(int prevState, int newState) { 2008 if (DBG) { 2009 Slog.d(TAG, 2010 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > " 2011 + BluetoothAdapter.nameForState(newState)); 2012 } 2013 // Send broadcast message to everyone else 2014 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 2015 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 2016 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 2017 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2018 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 2019 } 2020 bluetoothStateChangeHandler(int prevState, int newState)2021 private void bluetoothStateChangeHandler(int prevState, int newState) { 2022 boolean isStandardBroadcast = true; 2023 if (prevState == newState) { // No change. Nothing to do. 2024 return; 2025 } 2026 // Notify all proxy objects first of adapter state change 2027 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) { 2028 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 2029 && newState == BluetoothAdapter.STATE_BLE_ON); 2030 2031 if (newState == BluetoothAdapter.STATE_OFF) { 2032 // If Bluetooth is off, send service down event to proxy objects, and unbind 2033 if (DBG) { 2034 Slog.d(TAG, "Bluetooth is complete send Service Down"); 2035 } 2036 sendBluetoothServiceDownCallback(); 2037 unbindAndFinish(); 2038 sendBleStateChanged(prevState, newState); 2039 // Don't broadcast as it has already been broadcast before 2040 isStandardBroadcast = false; 2041 2042 } else if (!intermediate_off) { 2043 // connect to GattService 2044 if (DBG) { 2045 Slog.d(TAG, "Bluetooth is in LE only mode"); 2046 } 2047 if (mBluetoothGatt != null || !mContext.getPackageManager() 2048 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { 2049 continueFromBleOnState(); 2050 } else { 2051 if (DBG) { 2052 Slog.d(TAG, "Binding Bluetooth GATT service"); 2053 } 2054 Intent i = new Intent(IBluetoothGatt.class.getName()); 2055 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 2056 UserHandle.CURRENT); 2057 } 2058 sendBleStateChanged(prevState, newState); 2059 //Don't broadcase this as std intent 2060 isStandardBroadcast = false; 2061 2062 } else if (intermediate_off) { 2063 if (DBG) { 2064 Slog.d(TAG, "Intermediate off, back to LE only mode"); 2065 } 2066 // For LE only mode, broadcast as is 2067 sendBleStateChanged(prevState, newState); 2068 sendBluetoothStateCallback(false); // BT is OFF for general users 2069 // Broadcast as STATE_OFF 2070 newState = BluetoothAdapter.STATE_OFF; 2071 sendBrEdrDownCallback(); 2072 } 2073 } else if (newState == BluetoothAdapter.STATE_ON) { 2074 boolean isUp = (newState == BluetoothAdapter.STATE_ON); 2075 sendBluetoothStateCallback(isUp); 2076 sendBleStateChanged(prevState, newState); 2077 2078 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON 2079 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 2080 sendBleStateChanged(prevState, newState); 2081 isStandardBroadcast = false; 2082 2083 } else if (newState == BluetoothAdapter.STATE_TURNING_ON 2084 || newState == BluetoothAdapter.STATE_TURNING_OFF) { 2085 sendBleStateChanged(prevState, newState); 2086 } 2087 2088 if (isStandardBroadcast) { 2089 if (prevState == BluetoothAdapter.STATE_BLE_ON) { 2090 // Show prevState of BLE_ON as OFF to standard users 2091 prevState = BluetoothAdapter.STATE_OFF; 2092 } 2093 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 2094 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 2095 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 2096 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2097 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 2098 } 2099 } 2100 2101 /** 2102 * if on is true, wait for state become ON 2103 * if off is true, wait for state become OFF 2104 * if both on and off are false, wait for state not ON 2105 */ waitForOnOff(boolean on, boolean off)2106 private boolean waitForOnOff(boolean on, boolean off) { 2107 int i = 0; 2108 while (i < 10) { 2109 try { 2110 mBluetoothLock.readLock().lock(); 2111 if (mBluetooth == null) { 2112 break; 2113 } 2114 if (on) { 2115 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) { 2116 return true; 2117 } 2118 } else if (off) { 2119 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) { 2120 return true; 2121 } 2122 } else { 2123 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) { 2124 return true; 2125 } 2126 } 2127 } catch (RemoteException e) { 2128 Slog.e(TAG, "getState()", e); 2129 break; 2130 } finally { 2131 mBluetoothLock.readLock().unlock(); 2132 } 2133 if (on || off) { 2134 SystemClock.sleep(300); 2135 } else { 2136 SystemClock.sleep(50); 2137 } 2138 i++; 2139 } 2140 Slog.e(TAG, "waitForOnOff time out"); 2141 return false; 2142 } 2143 sendDisableMsg(int reason, String packageName)2144 private void sendDisableMsg(int reason, String packageName) { 2145 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 2146 addActiveLog(reason, packageName, false); 2147 } 2148 sendEnableMsg(boolean quietMode, int reason, String packageName)2149 private void sendEnableMsg(boolean quietMode, int reason, String packageName) { 2150 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); 2151 addActiveLog(reason, packageName, true); 2152 mLastEnabledTime = SystemClock.elapsedRealtime(); 2153 } 2154 addActiveLog(int reason, String packageName, boolean enable)2155 private void addActiveLog(int reason, String packageName, boolean enable) { 2156 synchronized (mActiveLogs) { 2157 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { 2158 mActiveLogs.remove(); 2159 } 2160 mActiveLogs.add( 2161 new ActiveLog(reason, packageName, enable, System.currentTimeMillis())); 2162 } 2163 2164 int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : 2165 StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; 2166 StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, 2167 Binder.getCallingUid(), null, state, reason, packageName); 2168 } 2169 addCrashLog()2170 private void addCrashLog() { 2171 synchronized (mCrashTimestamps) { 2172 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) { 2173 mCrashTimestamps.removeFirst(); 2174 } 2175 mCrashTimestamps.add(System.currentTimeMillis()); 2176 mCrashes++; 2177 } 2178 } 2179 recoverBluetoothServiceFromError(boolean clearBle)2180 private void recoverBluetoothServiceFromError(boolean clearBle) { 2181 Slog.e(TAG, "recoverBluetoothServiceFromError"); 2182 try { 2183 mBluetoothLock.readLock().lock(); 2184 if (mBluetooth != null) { 2185 //Unregister callback object 2186 mBluetooth.unregisterCallback(mBluetoothCallback); 2187 } 2188 } catch (RemoteException re) { 2189 Slog.e(TAG, "Unable to unregister", re); 2190 } finally { 2191 mBluetoothLock.readLock().unlock(); 2192 } 2193 2194 SystemClock.sleep(500); 2195 2196 // disable 2197 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR, 2198 mContext.getPackageName(), false); 2199 handleDisable(); 2200 2201 waitForOnOff(false, true); 2202 2203 sendBluetoothServiceDownCallback(); 2204 2205 try { 2206 mBluetoothLock.writeLock().lock(); 2207 if (mBluetooth != null) { 2208 mBluetooth = null; 2209 // Unbind 2210 mContext.unbindService(mConnection); 2211 } 2212 mBluetoothGatt = null; 2213 } finally { 2214 mBluetoothLock.writeLock().unlock(); 2215 } 2216 2217 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 2218 mState = BluetoothAdapter.STATE_OFF; 2219 2220 if (clearBle) { 2221 clearBleApps(); 2222 } 2223 2224 mEnable = false; 2225 2226 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 2227 // Send a Bluetooth Restart message to reenable bluetooth 2228 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2229 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 2230 } else { 2231 // todo: notify user to power down and power up phone to make bluetooth work. 2232 } 2233 } 2234 isBluetoothDisallowed()2235 private boolean isBluetoothDisallowed() { 2236 long callingIdentity = Binder.clearCallingIdentity(); 2237 try { 2238 return mContext.getSystemService(UserManager.class) 2239 .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); 2240 } finally { 2241 Binder.restoreCallingIdentity(callingIdentity); 2242 } 2243 } 2244 2245 /** 2246 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not 2247 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default 2248 * state if Bluetooth is not disallowed. 2249 * 2250 * @param userId user to disable bluetooth sharing for. 2251 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed. 2252 */ updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed)2253 private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) { 2254 final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", 2255 "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); 2256 final int newState = 2257 bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED 2258 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2259 try { 2260 final IPackageManager imp = AppGlobals.getPackageManager(); 2261 imp.setComponentEnabledSetting(oppLauncherComponent, newState, 2262 PackageManager.DONT_KILL_APP, userId); 2263 } catch (Exception e) { 2264 // The component was not found, do nothing. 2265 } 2266 } 2267 2268 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)2269 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2270 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { 2271 return; 2272 } 2273 String errorMsg = null; 2274 2275 boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); 2276 2277 if (!protoOut) { 2278 writer.println("Bluetooth Status"); 2279 writer.println(" enabled: " + isEnabled()); 2280 writer.println(" state: " + BluetoothAdapter.nameForState(mState)); 2281 writer.println(" address: " + mAddress); 2282 writer.println(" name: " + mName); 2283 if (mEnable) { 2284 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; 2285 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", 2286 (int) (onDuration / (1000 * 60 * 60)), 2287 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), 2288 (int) (onDuration % 1000)); 2289 writer.println(" time since enabled: " + onDurationString); 2290 } 2291 2292 if (mActiveLogs.size() == 0) { 2293 writer.println("\nBluetooth never enabled!"); 2294 } else { 2295 writer.println("\nEnable log:"); 2296 for (ActiveLog log : mActiveLogs) { 2297 writer.println(" " + log); 2298 } 2299 } 2300 2301 writer.println( 2302 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); 2303 if (mCrashes == CRASH_LOG_MAX_SIZE) { 2304 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); 2305 } 2306 for (Long time : mCrashTimestamps) { 2307 writer.println(" " + timeToLog(time)); 2308 } 2309 2310 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") 2311 + "registered"); 2312 for (ClientDeathRecipient app : mBleApps.values()) { 2313 writer.println(" " + app.getPackageName()); 2314 } 2315 2316 writer.println(""); 2317 writer.flush(); 2318 if (args.length == 0) { 2319 // Add arg to produce output 2320 args = new String[1]; 2321 args[0] = "--print"; 2322 } 2323 } 2324 2325 if (mBluetoothBinder == null) { 2326 errorMsg = "Bluetooth Service not connected"; 2327 } else { 2328 try { 2329 mBluetoothBinder.dump(fd, args); 2330 } catch (RemoteException re) { 2331 errorMsg = "RemoteException while dumping Bluetooth Service"; 2332 } 2333 } 2334 if (errorMsg != null) { 2335 // Silently return if we are extracting metrics in Protobuf format 2336 if (protoOut) { 2337 return; 2338 } 2339 writer.println(errorMsg); 2340 } 2341 } 2342 getEnableDisableReasonString(int reason)2343 private static String getEnableDisableReasonString(int reason) { 2344 switch (reason) { 2345 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST: 2346 return "APPLICATION_REQUEST"; 2347 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE: 2348 return "AIRPLANE_MODE"; 2349 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED: 2350 return "DISALLOWED"; 2351 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED: 2352 return "RESTARTED"; 2353 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR: 2354 return "START_ERROR"; 2355 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT: 2356 return "SYSTEM_BOOT"; 2357 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH: 2358 return "CRASH"; 2359 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH: 2360 return "USER_SWITCH"; 2361 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: 2362 return "RESTORE_USER_SETTING"; 2363 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: 2364 default: return "UNKNOWN[" + reason + "]"; 2365 } 2366 } 2367 } 2368