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.bluetooth; 18 19 import static android.Manifest.permission.BLUETOOTH_CONNECT; 20 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 21 import static android.permission.PermissionManager.PERMISSION_GRANTED; 22 import static android.permission.PermissionManager.PERMISSION_HARD_DENIED; 23 24 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_BT_ENABLED_NOTIFICATION; 25 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_ENHANCEMENT; 26 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_USER_TOGGLED_BLUETOOTH; 27 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.BLUETOOTH_APM_STATE; 28 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.NOTIFICATION_NOT_SHOWN; 29 import static com.android.server.bluetooth.BluetoothAirplaneModeListener.USED; 30 import static com.android.server.bluetooth.ChangeIds.RESTRICT_ENABLE_DISABLE; 31 32 import android.Manifest; 33 import android.annotation.NonNull; 34 import android.annotation.RequiresPermission; 35 import android.annotation.SuppressLint; 36 import android.app.ActivityManager; 37 import android.app.AppOpsManager; 38 import android.app.BroadcastOptions; 39 import android.app.admin.DevicePolicyManager; 40 import android.app.compat.CompatChanges; 41 import android.bluetooth.BluetoothA2dp; 42 import android.bluetooth.BluetoothAdapter; 43 import android.bluetooth.BluetoothHearingAid; 44 import android.bluetooth.BluetoothLeAudio; 45 import android.bluetooth.BluetoothProfile; 46 import android.bluetooth.BluetoothProtoEnums; 47 import android.bluetooth.BluetoothStatusCodes; 48 import android.bluetooth.IBluetooth; 49 import android.bluetooth.IBluetoothCallback; 50 import android.bluetooth.IBluetoothGatt; 51 import android.bluetooth.IBluetoothManager; 52 import android.bluetooth.IBluetoothManagerCallback; 53 import android.bluetooth.IBluetoothProfileServiceConnection; 54 import android.bluetooth.IBluetoothStateChangeCallback; 55 import android.content.AttributionSource; 56 import android.content.BroadcastReceiver; 57 import android.content.ComponentName; 58 import android.content.ContentResolver; 59 import android.content.Context; 60 import android.content.Intent; 61 import android.content.IntentFilter; 62 import android.content.ServiceConnection; 63 import android.content.pm.ApplicationInfo; 64 import android.content.pm.PackageInfo; 65 import android.content.pm.PackageManager; 66 import android.content.pm.ResolveInfo; 67 import android.content.res.Resources; 68 import android.database.ContentObserver; 69 import android.os.Binder; 70 import android.os.Bundle; 71 import android.os.Handler; 72 import android.os.HandlerThread; 73 import android.os.IBinder; 74 import android.os.Looper; 75 import android.os.Message; 76 import android.os.ParcelFileDescriptor; 77 import android.os.PowerExemptionManager; 78 import android.os.Process; 79 import android.os.RemoteCallbackList; 80 import android.os.RemoteException; 81 import android.os.SystemClock; 82 import android.os.SystemProperties; 83 import android.os.UserHandle; 84 import android.os.UserManager; 85 import android.permission.PermissionManager; 86 import android.provider.Settings; 87 import android.provider.Settings.SettingNotFoundException; 88 import android.sysprop.BluetoothProperties; 89 import android.text.TextUtils; 90 import android.util.Log; 91 import android.util.Pair; 92 import android.util.proto.ProtoOutputStream; 93 94 import com.android.bluetooth.BluetoothStatsLog; 95 import com.android.internal.annotations.GuardedBy; 96 import com.android.internal.annotations.VisibleForTesting; 97 import com.android.modules.utils.SynchronousResultReceiver; 98 import com.android.server.BluetoothManagerServiceDumpProto; 99 100 import java.io.FileDescriptor; 101 import java.io.FileOutputStream; 102 import java.io.PrintWriter; 103 import java.time.Duration; 104 import java.time.Instant; 105 import java.time.ZoneId; 106 import java.time.format.DateTimeFormatter; 107 import java.util.ArrayList; 108 import java.util.HashMap; 109 import java.util.LinkedList; 110 import java.util.List; 111 import java.util.Locale; 112 import java.util.Map; 113 import java.util.NoSuchElementException; 114 import java.util.Set; 115 import java.util.concurrent.ConcurrentHashMap; 116 import java.util.concurrent.TimeoutException; 117 import java.util.concurrent.locks.ReentrantReadWriteLock; 118 119 public class BluetoothManagerService extends IBluetoothManager.Stub { 120 private static final String TAG = "BluetoothManagerService"; 121 private static final boolean DBG = true; 122 123 private static final String BLUETOOTH_PRIVILEGED = 124 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 125 126 private static final int ACTIVE_LOG_MAX_SIZE = 20; 127 private static final int CRASH_LOG_MAX_SIZE = 100; 128 129 private static final int DEFAULT_REBIND_COUNT = 3; 130 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 131 132 /** 133 * Timeout value for synchronous binder call 134 */ 135 private static final Duration SYNC_CALLS_TIMEOUT = Duration.ofSeconds(3); 136 137 /** 138 * @return timeout value for synchronous binder call 139 */ getSyncTimeout()140 private static Duration getSyncTimeout() { 141 return SYNC_CALLS_TIMEOUT; 142 } 143 144 //Maximum msec to wait for service restart 145 private static final int SERVICE_RESTART_TIME_MS = 400; 146 //Maximum msec to wait for restart due to error 147 private static final int ERROR_RESTART_TIME_MS = 3000; 148 //Maximum msec to delay MESSAGE_USER_SWITCHED 149 private static final int USER_SWITCHED_TIME_MS = 200; 150 // Delay for the addProxy function in msec 151 private static final int ADD_PROXY_DELAY_MS = 100; 152 // Delay for retrying enable and disable in msec 153 private static final int ENABLE_DISABLE_DELAY_MS = 300; 154 private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300; 155 private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400000; 156 157 private static final int MESSAGE_ENABLE = 1; 158 @VisibleForTesting 159 static final int MESSAGE_DISABLE = 2; 160 private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; 161 private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; 162 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 163 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 164 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 165 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 166 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 167 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; 168 private static final int MESSAGE_TIMEOUT_BIND = 100; 169 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; 170 private static final int MESSAGE_USER_SWITCHED = 300; 171 private static final int MESSAGE_USER_UNLOCKED = 301; 172 private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 173 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 174 private static final int MESSAGE_RESTORE_USER_SETTING = 500; 175 private static final int MESSAGE_INIT_FLAGS_CHANGED = 600; 176 177 private static final int RESTORE_SETTING_TO_ON = 1; 178 private static final int RESTORE_SETTING_TO_OFF = 0; 179 180 private static final int MAX_ERROR_RESTART_RETRIES = 6; 181 private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; 182 183 // Bluetooth persisted setting is off 184 private static final int BLUETOOTH_OFF = 0; 185 // Bluetooth persisted setting is on 186 // and Airplane mode won't affect Bluetooth state at start up 187 private static final int BLUETOOTH_ON_BLUETOOTH = 1; 188 // Bluetooth persisted setting is on 189 // but Airplane mode will affect Bluetooth state at start up 190 // and Airplane mode will have higher priority. 191 @VisibleForTesting 192 static final int BLUETOOTH_ON_AIRPLANE = 2; 193 194 private static final int BLUETOOTH_OFF_APM = 0; 195 private static final int BLUETOOTH_ON_APM = 1; 196 197 private static final int SERVICE_IBLUETOOTH = 1; 198 private static final int SERVICE_IBLUETOOTHGATT = 2; 199 200 private static final int FLAGS_SYSTEM_APP = 201 ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; 202 203 private final Context mContext; 204 205 private final UserManager mUserManager; 206 207 // -3 match with Userhandle.USER_CURRENT_OR_SELF 208 private static final UserHandle USER_HANDLE_CURRENT_OR_SELF = UserHandle.of(-3); 209 // -10000 match with Userhandle.USER_NULL 210 private static final UserHandle USER_HANDLE_NULL = UserHandle.of(-10000); 211 212 // Locks are not provided for mName and mAddress. 213 // They are accessed in handler or broadcast receiver, same thread context. 214 private String mAddress; 215 private String mName; 216 private final ContentResolver mContentResolver; 217 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 218 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 219 private IBinder mBluetoothBinder; 220 221 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); 222 @GuardedBy("mBluetoothLock") 223 private IBluetooth mBluetooth; 224 225 private IBluetoothGatt mBluetoothGatt; 226 private boolean mBinding; 227 private boolean mUnbinding; 228 private List<Integer> mSupportedProfileList = new ArrayList<>(); 229 230 private BluetoothModeChangeHelper mBluetoothModeChangeHelper; 231 232 private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; 233 234 private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener; 235 236 private BluetoothNotificationManager mBluetoothNotificationManager; 237 238 private BluetoothSatelliteModeListener mBluetoothSatelliteModeListener; 239 240 // used inside handler thread 241 private boolean mQuietEnable = false; 242 private boolean mEnable; 243 private boolean mShutdownInProgress = false; 244 timeToLog(long timestamp)245 private static String timeToLog(long timestamp) { 246 return DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault()) 247 .format(Instant.ofEpochMilli(timestamp)); 248 } 249 250 /** 251 * Used for tracking apps that enabled / disabled Bluetooth. 252 */ 253 private class ActiveLog { 254 private int mReason; 255 private String mPackageName; 256 private boolean mEnable; 257 private long mTimestamp; 258 ActiveLog(int reason, String packageName, boolean enable, long timestamp)259 ActiveLog(int reason, String packageName, boolean enable, long timestamp) { 260 mReason = reason; 261 mPackageName = packageName; 262 mEnable = enable; 263 mTimestamp = timestamp; 264 } 265 toString()266 public String toString() { 267 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") 268 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName; 269 } 270 dump(ProtoOutputStream proto)271 void dump(ProtoOutputStream proto) { 272 proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp); 273 proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable); 274 proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName); 275 proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason); 276 } 277 } 278 279 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>(); 280 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>(); 281 private int mCrashes; 282 private long mLastEnabledTime; 283 284 // configuration from external IBinder call which is used to 285 // synchronize with broadcast receiver. 286 private boolean mQuietEnableExternal; 287 private boolean mEnableExternal; 288 289 // Map of apps registered to keep BLE scanning on. 290 private Map<IBinder, ClientDeathRecipient> mBleApps = 291 new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); 292 293 private int mState; 294 private final HandlerThread mBluetoothHandlerThread; 295 private final BluetoothHandler mHandler; 296 private int mErrorRecoveryRetryCounter; 297 private final int mSystemUiUid; 298 299 private boolean mIsHearingAidProfileSupported; 300 301 private AppOpsManager mAppOps; 302 303 // Save a ProfileServiceConnections object for each of the bound 304 // bluetooth profile services 305 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>(); 306 @GuardedBy("mProfileServices") 307 private boolean mUnbindingAll = false; 308 309 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 310 @Override 311 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 312 Message msg = 313 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState); 314 mHandler.sendMessage(msg); 315 } 316 }; 317 onUserRestrictionsChanged(UserHandle userHandle)318 public void onUserRestrictionsChanged(UserHandle userHandle) { 319 final boolean newBluetoothDisallowed = mUserManager.hasUserRestrictionForUser( 320 UserManager.DISALLOW_BLUETOOTH, userHandle); 321 // Disallow Bluetooth sharing when either Bluetooth is disallowed or Bluetooth sharing 322 // is disallowed 323 final boolean newBluetoothSharingDisallowed = mUserManager.hasUserRestrictionForUser( 324 UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle) || newBluetoothDisallowed; 325 326 // Disable OPP activities for this userHandle 327 updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); 328 329 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. 330 // Only trigger once instead of for all users 331 if (userHandle == UserHandle.SYSTEM && newBluetoothDisallowed) { 332 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, 333 mContext.getPackageName()); 334 } 335 } 336 337 @VisibleForTesting onInitFlagsChanged()338 public void onInitFlagsChanged() { 339 // TODO(b/265386284) 340 } 341 onFactoryReset(AttributionSource attributionSource)342 public boolean onFactoryReset(AttributionSource attributionSource) { 343 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 344 "Need BLUETOOTH_PRIVILEGED permission"); 345 346 // Wait for stable state if bluetooth is temporary state. 347 int state = getState(); 348 if (state == BluetoothAdapter.STATE_BLE_TURNING_ON 349 || state == BluetoothAdapter.STATE_TURNING_ON 350 || state == BluetoothAdapter.STATE_TURNING_OFF) { 351 if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) { 352 return false; 353 } 354 } 355 356 // Clear registered LE apps to force shut-off Bluetooth 357 clearBleApps(); 358 state = getState(); 359 mBluetoothLock.readLock().lock(); 360 try { 361 if (mBluetooth == null) { 362 return false; 363 } 364 if (state == BluetoothAdapter.STATE_BLE_ON) { 365 addActiveLog( 366 BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, 367 mContext.getPackageName(), false); 368 synchronousOnBrEdrDown(attributionSource); 369 return true; 370 } else if (state == BluetoothAdapter.STATE_ON) { 371 addActiveLog( 372 BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, 373 mContext.getPackageName(), false); 374 synchronousDisable(attributionSource); 375 return true; 376 } 377 } catch (RemoteException | TimeoutException e) { 378 Log.e(TAG, "Unable to shutdown Bluetooth", e); 379 } finally { 380 mBluetoothLock.readLock().unlock(); 381 } 382 return false; 383 } 384 estimateBusyTime(int state)385 private int estimateBusyTime(int state) { 386 if (state == BluetoothAdapter.STATE_BLE_ON && isBluetoothPersistedStateOn()) { 387 // Bluetooth is in BLE and is starting classic 388 return SERVICE_RESTART_TIME_MS; 389 } else if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF 390 && state != BluetoothAdapter.STATE_BLE_ON) { 391 // Bluetooth is turning state 392 return ADD_PROXY_DELAY_MS; 393 } else if (mHandler.hasMessages(MESSAGE_ENABLE) 394 || mHandler.hasMessages(MESSAGE_DISABLE) 395 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED) 396 || mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) 397 || mHandler.hasMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE) 398 || mHandler.hasMessages(MESSAGE_TIMEOUT_BIND) 399 || mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE)) { 400 // Bluetooth is restarting 401 return SERVICE_RESTART_TIME_MS; 402 } 403 return 0; 404 } 405 delayModeChangedIfNeeded(Object token, Runnable r, String modechanged)406 private void delayModeChangedIfNeeded(Object token, Runnable r, String modechanged) { 407 mHandler.removeCallbacksAndMessages(token); 408 409 final int state = getState(); 410 final int delayMs = estimateBusyTime(state); 411 Log.d(TAG, "delayModeChangedIfNeeded(" + modechanged + "): " 412 + "state=" + BluetoothAdapter.nameForState(state) 413 + ", isAirplaneModeOn()=" + isAirplaneModeOn() 414 + ", isSatelliteModeSensitive()=" + isSatelliteModeSensitive() 415 + ", isSatelliteModeOn()=" + isSatelliteModeOn() 416 + ", delayed=" + delayMs + "ms"); 417 418 if (delayMs > 0) { 419 mHandler.postDelayed(() -> delayModeChangedIfNeeded(token, r, modechanged), 420 token, delayMs); 421 } else { 422 r.run(); 423 } 424 } 425 426 private static final Object ON_AIRPLANE_MODE_CHANGED_TOKEN = new Object(); 427 private static final Object ON_SATELLITE_MODE_CHANGED_TOKEN = new Object(); 428 private static final Object ON_SWITCH_USER_TOKEN = new Object(); 429 430 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) onAirplaneModeChanged()431 void onAirplaneModeChanged() { 432 delayModeChangedIfNeeded(ON_AIRPLANE_MODE_CHANGED_TOKEN, 433 () -> handleAirplaneModeChanged(), "onAirplaneModeChanged"); 434 } 435 436 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) onSatelliteModeChanged()437 void onSatelliteModeChanged() { 438 delayModeChangedIfNeeded(ON_SATELLITE_MODE_CHANGED_TOKEN, 439 () -> handleSatelliteModeChanged(), "onSatelliteModeChanged"); 440 } 441 442 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) onSwitchUser(UserHandle userHandle)443 void onSwitchUser(UserHandle userHandle) { 444 delayModeChangedIfNeeded(ON_SWITCH_USER_TOKEN, 445 () -> handleSwitchUser(userHandle), "onSwitchUser"); 446 } 447 448 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) handleAirplaneModeChanged()449 private void handleAirplaneModeChanged() { 450 synchronized (this) { 451 if (isBluetoothPersistedStateOn()) { 452 if (isAirplaneModeOn()) { 453 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 454 } else { 455 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 456 } 457 } 458 459 int st = BluetoothAdapter.STATE_OFF; 460 try { 461 mBluetoothLock.readLock().lock(); 462 st = synchronousGetState(); 463 } catch (RemoteException | TimeoutException e) { 464 Log.e(TAG, "Unable to call getState", e); 465 return; 466 } finally { 467 mBluetoothLock.readLock().unlock(); 468 } 469 470 Log.d(TAG, 471 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( 472 st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); 473 474 if (isAirplaneModeOn()) { 475 // Clear registered LE apps to force shut-off 476 clearBleApps(); 477 478 // If state is BLE_ON make sure we trigger disableBLE 479 if (st == BluetoothAdapter.STATE_BLE_ON) { 480 mBluetoothLock.readLock().lock(); 481 try { 482 if (mBluetooth != null) { 483 addActiveLog( 484 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 485 mContext.getPackageName(), false); 486 synchronousOnBrEdrDown(mContext.getAttributionSource()); 487 mEnable = false; 488 mEnableExternal = false; 489 } 490 } catch (RemoteException | TimeoutException e) { 491 Log.e(TAG, "Unable to call onBrEdrDown", e); 492 } finally { 493 mBluetoothLock.readLock().unlock(); 494 } 495 } else if (st == BluetoothAdapter.STATE_ON) { 496 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 497 mContext.getPackageName()); 498 } 499 } else if (mEnableExternal) { 500 sendEnableMsg(mQuietEnableExternal, 501 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, 502 mContext.getPackageName()); 503 } 504 } 505 } 506 handleSatelliteModeChanged()507 private void handleSatelliteModeChanged() { 508 if (shouldBluetoothBeOn() && getState() != BluetoothAdapter.STATE_ON) { 509 sendEnableMsg(mQuietEnableExternal, 510 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SATELLITE_MODE, 511 mContext.getPackageName()); 512 } else if (!shouldBluetoothBeOn() && getState() != BluetoothAdapter.STATE_OFF) { 513 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_SATELLITE_MODE, 514 mContext.getPackageName()); 515 } 516 } 517 shouldBluetoothBeOn()518 private boolean shouldBluetoothBeOn() { 519 if (!isBluetoothPersistedStateOn()) { 520 Log.d(TAG, "shouldBluetoothBeOn: User want BT off."); 521 return false; 522 } 523 524 if (isSatelliteModeOn()) { 525 Log.d(TAG, "shouldBluetoothBeOn: BT should be off as satellite mode is on."); 526 return false; 527 } 528 529 if (isAirplaneModeOn() && isBluetoothPersistedStateOnAirplane()) { 530 Log.d(TAG, "shouldBluetoothBeOn: BT should be off as airplaneMode is on."); 531 return false; 532 } 533 534 Log.d(TAG, "shouldBluetoothBeOn: BT should be on."); 535 return true; 536 } 537 538 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 539 @Override 540 public void onReceive(Context context, Intent intent) { 541 String action = intent.getAction(); 542 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 543 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 544 if (DBG) { 545 Log.d(TAG, "Bluetooth Adapter name changed to " + newName + " by " 546 + mContext.getPackageName()); 547 } 548 if (newName != null) { 549 storeNameAndAddress(newName, null); 550 } 551 } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) { 552 String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS); 553 if (newAddress != null) { 554 if (DBG) { 555 Log.d(TAG, "Bluetooth Adapter address changed to " + newAddress); 556 } 557 storeNameAndAddress(null, newAddress); 558 } else { 559 if (DBG) { 560 Log.e(TAG, "No Bluetooth Adapter address parameter found"); 561 } 562 } 563 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { 564 final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 565 if (Settings.Global.BLUETOOTH_ON.equals(name)) { 566 // The Bluetooth On state may be changed during system restore. 567 final String prevValue = 568 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE); 569 final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); 570 571 if (DBG) { 572 Log.d(TAG, 573 "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue 574 + ", newValue=" + newValue); 575 } 576 577 if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) { 578 Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING, 579 newValue.equals("0") ? RESTORE_SETTING_TO_OFF 580 : RESTORE_SETTING_TO_ON, 0); 581 mHandler.sendMessage(msg); 582 } 583 } 584 } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action) 585 || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action) 586 || BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(action)) { 587 final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 588 BluetoothProfile.STATE_CONNECTED); 589 if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) 590 && state == BluetoothProfile.STATE_DISCONNECTED 591 && !mBluetoothModeChangeHelper.isMediaProfileConnected()) { 592 Log.i(TAG, "Device disconnected, reactivating pending flag changes"); 593 onInitFlagsChanged(); 594 } 595 } else if (action.equals(Intent.ACTION_SHUTDOWN)) { 596 Log.i(TAG, "Device is shutting down."); 597 mShutdownInProgress = true; 598 mBluetoothLock.readLock().lock(); 599 try { 600 mEnable = false; 601 mEnableExternal = false; 602 if (mBluetooth != null && (mState == BluetoothAdapter.STATE_BLE_ON)) { 603 synchronousOnBrEdrDown(mContext.getAttributionSource()); 604 } else if (mBluetooth != null && (mState == BluetoothAdapter.STATE_ON)) { 605 synchronousDisable(mContext.getAttributionSource()); 606 } 607 } catch (RemoteException | TimeoutException e) { 608 Log.e(TAG, "Unable to shutdown Bluetooth", e); 609 } finally { 610 mBluetoothLock.readLock().unlock(); 611 } 612 } 613 } 614 }; 615 BluetoothManagerService(Context context)616 BluetoothManagerService(Context context) { 617 mBluetoothHandlerThread = BluetoothServerProxy.getInstance() 618 .createHandlerThread("BluetoothManagerService"); 619 mBluetoothHandlerThread.start(); 620 621 mHandler = BluetoothServerProxy.getInstance().newBluetoothHandler( 622 new BluetoothHandler(mBluetoothHandlerThread.getLooper())); 623 624 mContext = context; 625 626 mCrashes = 0; 627 mBluetooth = null; 628 mBluetoothBinder = null; 629 mBluetoothGatt = null; 630 mBinding = false; 631 mUnbinding = false; 632 mEnable = false; 633 mState = BluetoothAdapter.STATE_OFF; 634 mQuietEnableExternal = false; 635 mEnableExternal = false; 636 mAddress = null; 637 mName = null; 638 mErrorRecoveryRetryCounter = 0; 639 mContentResolver = context.getContentResolver(); 640 641 // Observe BLE scan only mode settings change. 642 registerForBleScanModeChange(); 643 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 644 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 645 646 mUserManager = mContext.getSystemService(UserManager.class); 647 648 mBluetoothNotificationManager = new BluetoothNotificationManager(mContext); 649 650 // Disable ASHA if BLE is not supported, overriding any system property 651 if (!isBleSupported(mContext)) { 652 mIsHearingAidProfileSupported = false; 653 } else { 654 // ASHA default value is: 655 // * disabled on Automotive, TV, and Watch. 656 // * enabled for other form factor 657 // This default value can be overridden with a system property 658 final boolean isAshaEnabledByDefault = 659 !(isAutomotive(mContext) || isWatch(mContext) || isTv(mContext)); 660 mIsHearingAidProfileSupported = 661 BluetoothProperties.isProfileAshaCentralEnabled() 662 .orElse(isAshaEnabledByDefault); 663 } 664 665 String value = SystemProperties.get( 666 "persist.sys.fflag.override.settings_bluetooth_hearing_aid"); 667 668 if (!TextUtils.isEmpty(value)) { 669 boolean isHearingAidEnabled = Boolean.parseBoolean(value); 670 Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); 671 if (isHearingAidEnabled && !mIsHearingAidProfileSupported) { 672 // Overwrite to enable support by FeatureFlag 673 mIsHearingAidProfileSupported = true; 674 } 675 } 676 677 IntentFilter filter = new IntentFilter(); 678 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 679 filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); 680 filter.addAction(Intent.ACTION_SETTING_RESTORED); 681 filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); 682 filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 683 filter.addAction(Intent.ACTION_SHUTDOWN); 684 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 685 mContext.registerReceiver(mReceiver, filter); 686 687 IntentFilter filterUser = new IntentFilter(); 688 filterUser.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); 689 filterUser.addAction(Intent.ACTION_USER_SWITCHED); 690 filterUser.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 691 mContext.registerReceiverForAllUsers(new BroadcastReceiver() { 692 @Override 693 public void onReceive(Context context, Intent intent) { 694 switch (intent.getAction()) { 695 case Intent.ACTION_USER_SWITCHED: 696 int foregroundUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 697 propagateForegroundUserId(foregroundUserId); 698 break; 699 case UserManager.ACTION_USER_RESTRICTIONS_CHANGED: 700 onUserRestrictionsChanged(getSendingUser()); 701 break; 702 default: 703 Log.e(TAG, "Unknown broadcast received in BluetoothManagerService receiver" 704 + " registered across all users"); 705 } 706 } 707 }, filterUser, null, null); 708 709 loadStoredNameAndAddress(); 710 if (isBluetoothPersistedStateOn()) { 711 if (DBG) { 712 Log.d(TAG, "Startup: Bluetooth persisted state is ON."); 713 } 714 mEnableExternal = true; 715 } 716 717 String airplaneModeRadios = 718 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS); 719 if (airplaneModeRadios == null || airplaneModeRadios.contains( 720 Settings.Global.RADIO_BLUETOOTH)) { 721 mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener( 722 this, mBluetoothHandlerThread.getLooper(), context, 723 mBluetoothNotificationManager); 724 } 725 726 int systemUiUid = -1; 727 // Check if device is configured with no home screen, which implies no SystemUI. 728 try { 729 systemUiUid = mContext.createContextAsUser(UserHandle.SYSTEM, 0) 730 .getPackageManager() 731 .getPackageUid("com.android.systemui", 732 PackageManager.PackageInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY)); 733 Log.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid)); 734 } catch (PackageManager.NameNotFoundException e) { 735 Log.w(TAG, "Unable to resolve SystemUI's UID."); 736 } 737 mSystemUiUid = systemUiUid; 738 739 mBluetoothSatelliteModeListener = new BluetoothSatelliteModeListener( 740 this, mBluetoothHandlerThread.getLooper(), context); 741 } 742 743 /** 744 * Returns true if airplane mode is currently on 745 */ isAirplaneModeOn()746 private boolean isAirplaneModeOn() { 747 return Settings.Global.getInt(mContext.getContentResolver(), 748 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 749 } 750 751 /** 752 * @hide constant copied from {@link Settings.Global} 753 * TODO(b/274636414): Migrate to official API in Android V. 754 */ 755 @VisibleForTesting 756 static final String SETTINGS_SATELLITE_MODE_RADIOS = "satellite_mode_radios"; 757 /** 758 * @hide constant copied from {@link Settings.Global} 759 * TODO(b/274636414): Migrate to official API in Android V. 760 */ 761 @VisibleForTesting 762 static final String SETTINGS_SATELLITE_MODE_ENABLED = "satellite_mode_enabled"; 763 isSatelliteModeSensitive()764 private boolean isSatelliteModeSensitive() { 765 final String satelliteRadios = Settings.Global.getString(mContext.getContentResolver(), 766 SETTINGS_SATELLITE_MODE_RADIOS); 767 return satelliteRadios != null 768 && satelliteRadios.contains(Settings.Global.RADIO_BLUETOOTH); 769 } 770 771 /** Returns true if satellite mode is turned on. */ isSatelliteModeOn()772 private boolean isSatelliteModeOn() { 773 if (!isSatelliteModeSensitive()) return false; 774 return Settings.Global.getInt(mContext.getContentResolver(), 775 SETTINGS_SATELLITE_MODE_ENABLED, 0) == 1; 776 } 777 778 /** 779 * Returns true if airplane mode enhancement feature is enabled 780 */ isApmEnhancementOn()781 private boolean isApmEnhancementOn() { 782 return Settings.Global.getInt(mContext.getContentResolver(), APM_ENHANCEMENT, 0) == 1; 783 } 784 supportBluetoothPersistedState()785 private boolean supportBluetoothPersistedState() { 786 // Set default support to true to copy config default. 787 return BluetoothProperties.isSupportPersistedStateEnabled().orElse(true); 788 } 789 790 /** 791 * Returns true if the Bluetooth saved state is "on" 792 */ isBluetoothPersistedStateOn()793 private boolean isBluetoothPersistedStateOn() { 794 if (!supportBluetoothPersistedState()) { 795 return false; 796 } 797 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); 798 if (DBG) { 799 Log.d(TAG, "Bluetooth persisted state: " + state); 800 } 801 return state != BLUETOOTH_OFF; 802 } 803 isBluetoothPersistedStateOnAirplane()804 private boolean isBluetoothPersistedStateOnAirplane() { 805 if (!supportBluetoothPersistedState()) { 806 return false; 807 } 808 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); 809 if (DBG) { 810 Log.d(TAG, "Bluetooth persisted state: " + state); 811 } 812 return state == BLUETOOTH_ON_AIRPLANE; 813 } 814 815 /** 816 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 817 */ isBluetoothPersistedStateOnBluetooth()818 private boolean isBluetoothPersistedStateOnBluetooth() { 819 if (!supportBluetoothPersistedState()) { 820 return false; 821 } 822 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, 823 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; 824 } 825 826 /** 827 * Save the Bluetooth on/off state 828 */ persistBluetoothSetting(int value)829 private void persistBluetoothSetting(int value) { 830 if (DBG) { 831 Log.d(TAG, "Persisting Bluetooth Setting: " + value); 832 } 833 // waive WRITE_SECURE_SETTINGS permission check 834 final long callingIdentity = Binder.clearCallingIdentity(); 835 try { 836 Settings.Global.putInt(mContext.getContentResolver(), 837 Settings.Global.BLUETOOTH_ON, value); 838 } finally { 839 Binder.restoreCallingIdentity(callingIdentity); 840 } 841 } 842 843 /** 844 * Set the Settings Secure Int value for foreground user 845 */ setSettingsSecureInt(String name, int value)846 private void setSettingsSecureInt(String name, int value) { 847 if (DBG) { 848 Log.d(TAG, "Persisting Settings Secure Int: " + name + "=" + value); 849 } 850 851 // waive WRITE_SECURE_SETTINGS permission check 852 final long callingIdentity = Binder.clearCallingIdentity(); 853 try { 854 Context userContext = mContext.createContextAsUser( 855 UserHandle.of(ActivityManager.getCurrentUser()), 0); 856 Settings.Secure.putInt(userContext.getContentResolver(), name, value); 857 } finally { 858 Binder.restoreCallingIdentity(callingIdentity); 859 } 860 } 861 862 /** 863 * Return whether APM notification has been shown 864 */ isFirstTimeNotification(String name)865 private boolean isFirstTimeNotification(String name) { 866 boolean firstTime = false; 867 // waive WRITE_SECURE_SETTINGS permission check 868 final long callingIdentity = Binder.clearCallingIdentity(); 869 try { 870 Context userContext = mContext.createContextAsUser( 871 UserHandle.of(ActivityManager.getCurrentUser()), 0); 872 firstTime = Settings.Secure.getInt(userContext.getContentResolver(), name, 873 NOTIFICATION_NOT_SHOWN) == NOTIFICATION_NOT_SHOWN; 874 } finally { 875 Binder.restoreCallingIdentity(callingIdentity); 876 } 877 return firstTime; 878 } 879 880 /** 881 * Returns true if the Bluetooth Adapter's name and address is 882 * locally cached 883 * @return 884 */ isNameAndAddressSet()885 private boolean isNameAndAddressSet() { 886 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0; 887 } 888 889 /** 890 * Retrieve the Bluetooth Adapter's name and address and save it in 891 * in the local cache 892 */ loadStoredNameAndAddress()893 private void loadStoredNameAndAddress() { 894 if (DBG) { 895 Log.d(TAG, "Loading stored name and address"); 896 } 897 if (BluetoothProperties.isAdapterAddressValidationEnabled().orElse(false) 898 && Settings.Secure.getInt(mContentResolver, 899 Settings.Secure.BLUETOOTH_ADDR_VALID, 0) == 0) { 900 // if the valid flag is not set, don't load the address and name 901 if (DBG) { 902 Log.d(TAG, "invalid bluetooth name and address stored"); 903 } 904 return; 905 } 906 mName = BluetoothServerProxy.getInstance() 907 .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); 908 mAddress = BluetoothServerProxy.getInstance() 909 .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); 910 911 if (DBG) { 912 Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 913 } 914 } 915 916 /** 917 * Save the Bluetooth name and address in the persistent store. 918 * Only non-null values will be saved. 919 * @param name 920 * @param address 921 */ storeNameAndAddress(String name, String address)922 private void storeNameAndAddress(String name, String address) { 923 if (name != null) { 924 Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_NAME, name); 925 mName = name; 926 if (DBG) { 927 Log.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver, 928 Settings.Secure.BLUETOOTH_NAME)); 929 } 930 } 931 932 if (address != null) { 933 Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, address); 934 mAddress = address; 935 if (DBG) { 936 Log.d(TAG, "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver, 937 Settings.Secure.BLUETOOTH_ADDRESS)); 938 } 939 } 940 941 if ((name != null) && (address != null)) { 942 Settings.Secure.putInt(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 1); 943 } 944 } 945 registerAdapter(IBluetoothManagerCallback callback)946 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) { 947 if (callback == null) { 948 Log.w(TAG, "Callback is null in registerAdapter"); 949 return null; 950 } 951 synchronized (mCallbacks) { 952 mCallbacks.register(callback); 953 } 954 return mBluetooth; 955 } 956 unregisterAdapter(IBluetoothManagerCallback callback)957 public void unregisterAdapter(IBluetoothManagerCallback callback) { 958 if (callback == null) { 959 Log.w(TAG, "Callback is null in unregisterAdapter"); 960 return; 961 } 962 synchronized (mCallbacks) { 963 mCallbacks.unregister(callback); 964 } 965 } 966 registerStateChangeCallback(IBluetoothStateChangeCallback callback)967 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 968 if (callback == null) { 969 Log.w(TAG, "registerStateChangeCallback: Callback is null!"); 970 return; 971 } 972 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 973 msg.obj = callback; 974 mHandler.sendMessage(msg); 975 } 976 unregisterStateChangeCallback(IBluetoothStateChangeCallback callback)977 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 978 if (callback == null) { 979 Log.w(TAG, "unregisterStateChangeCallback: Callback is null!"); 980 return; 981 } 982 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 983 msg.obj = callback; 984 mHandler.sendMessage(msg); 985 } 986 isEnabled()987 public boolean isEnabled() { 988 return getState() == BluetoothAdapter.STATE_ON; 989 } 990 991 @GuardedBy("mBluetoothLock") synchronousDisable(AttributionSource attributionSource)992 private boolean synchronousDisable(AttributionSource attributionSource) 993 throws RemoteException, TimeoutException { 994 if (mBluetooth == null) return false; 995 final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get(); 996 mBluetooth.disable(attributionSource, recv); 997 return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); 998 } 999 1000 @GuardedBy("mBluetoothLock") synchronousEnable(boolean quietMode, AttributionSource attributionSource)1001 private boolean synchronousEnable(boolean quietMode, AttributionSource attributionSource) 1002 throws RemoteException, TimeoutException { 1003 if (mBluetooth == null) return false; 1004 final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get(); 1005 mBluetooth.enable(quietMode, attributionSource, recv); 1006 return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); 1007 } 1008 1009 @GuardedBy("mBluetoothLock") synchronousGetAddress(AttributionSource attributionSource)1010 private String synchronousGetAddress(AttributionSource attributionSource) 1011 throws RemoteException, TimeoutException { 1012 if (mBluetooth == null) return null; 1013 final SynchronousResultReceiver<String> recv = SynchronousResultReceiver.get(); 1014 mBluetooth.getAddress(attributionSource, recv); 1015 return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1016 } 1017 1018 @GuardedBy("mBluetoothLock") synchronousGetName(AttributionSource attributionSource)1019 private String synchronousGetName(AttributionSource attributionSource) 1020 throws RemoteException, TimeoutException { 1021 if (mBluetooth == null) return null; 1022 final SynchronousResultReceiver<String> recv = SynchronousResultReceiver.get(); 1023 mBluetooth.getName(attributionSource, recv); 1024 return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1025 } 1026 1027 @GuardedBy("mBluetoothLock") synchronousGetState()1028 private int synchronousGetState() 1029 throws RemoteException, TimeoutException { 1030 if (mBluetooth == null) return BluetoothAdapter.STATE_OFF; 1031 final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get(); 1032 mBluetooth.getState(recv); 1033 return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(BluetoothAdapter.STATE_OFF); 1034 } 1035 1036 @GuardedBy("mBluetoothLock") synchronousOnBrEdrDown(AttributionSource attributionSource)1037 private void synchronousOnBrEdrDown(AttributionSource attributionSource) 1038 throws RemoteException, TimeoutException { 1039 if (mBluetooth == null) return; 1040 final SynchronousResultReceiver recv = SynchronousResultReceiver.get(); 1041 mBluetooth.onBrEdrDown(attributionSource, recv); 1042 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1043 } 1044 1045 @GuardedBy("mBluetoothLock") synchronousOnLeServiceUp(AttributionSource attributionSource)1046 private void synchronousOnLeServiceUp(AttributionSource attributionSource) 1047 throws RemoteException, TimeoutException { 1048 if (mBluetooth == null) return; 1049 final SynchronousResultReceiver recv = SynchronousResultReceiver.get(); 1050 mBluetooth.onLeServiceUp(attributionSource, recv); 1051 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1052 } 1053 1054 @GuardedBy("mBluetoothLock") synchronousRegisterCallback(IBluetoothCallback callback, AttributionSource attributionSource)1055 private void synchronousRegisterCallback(IBluetoothCallback callback, 1056 AttributionSource attributionSource) throws RemoteException, TimeoutException { 1057 if (mBluetooth == null) return; 1058 final SynchronousResultReceiver recv = SynchronousResultReceiver.get(); 1059 mBluetooth.registerCallback(callback, attributionSource, recv); 1060 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1061 } 1062 1063 @GuardedBy("mBluetoothLock") synchronousUnregisterCallback(IBluetoothCallback callback, AttributionSource attributionSource)1064 private void synchronousUnregisterCallback(IBluetoothCallback callback, 1065 AttributionSource attributionSource) throws RemoteException, TimeoutException { 1066 if (mBluetooth == null) return; 1067 final SynchronousResultReceiver recv = SynchronousResultReceiver.get(); 1068 mBluetooth.unregisterCallback(callback, attributionSource, recv); 1069 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1070 } 1071 1072 @GuardedBy("mBluetoothLock") synchronousGetSupportedProfiles(AttributionSource attributionSource)1073 private List<Integer> synchronousGetSupportedProfiles(AttributionSource attributionSource) 1074 throws RemoteException, TimeoutException { 1075 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>(); 1076 if (mBluetooth == null) return supportedProfiles; 1077 final SynchronousResultReceiver<Long> recv = SynchronousResultReceiver.get(); 1078 mBluetooth.getSupportedProfiles(attributionSource, recv); 1079 final long supportedProfilesBitMask = 1080 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue((long) 0); 1081 1082 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) { 1083 if ((supportedProfilesBitMask & (1 << i)) != 0) { 1084 supportedProfiles.add(i); 1085 } 1086 } 1087 1088 return supportedProfiles; 1089 } 1090 1091 /** 1092 * Sends the current foreground user id to the Bluetooth process. This user id is used to 1093 * determine if Binder calls are coming from the active user. 1094 * 1095 * @param userId is the foreground user id we are propagating to the Bluetooth process 1096 */ propagateForegroundUserId(int userId)1097 private void propagateForegroundUserId(int userId) { 1098 mBluetoothLock.readLock().lock(); 1099 try { 1100 if (mBluetooth != null) { 1101 mBluetooth.setForegroundUserId(userId, mContext.getAttributionSource()); 1102 } 1103 } catch (RemoteException e) { 1104 Log.e(TAG, "Unable to set foreground user id", e); 1105 } finally { 1106 mBluetoothLock.readLock().unlock(); 1107 } 1108 } 1109 getState()1110 public int getState() { 1111 if (!isCallerSystem(getCallingAppId()) && !checkIfCallerIsForegroundUser()) { 1112 Log.w(TAG, "getState(): report OFF for non-active and non system user"); 1113 return BluetoothAdapter.STATE_OFF; 1114 } 1115 1116 mBluetoothLock.readLock().lock(); 1117 try { 1118 if (mBluetooth != null) { 1119 return synchronousGetState(); 1120 } 1121 } catch (RemoteException | TimeoutException e) { 1122 Log.e(TAG, "getState()", e); 1123 } finally { 1124 mBluetoothLock.readLock().unlock(); 1125 } 1126 return BluetoothAdapter.STATE_OFF; 1127 } 1128 1129 class ClientDeathRecipient implements IBinder.DeathRecipient { 1130 private String mPackageName; 1131 ClientDeathRecipient(String packageName)1132 ClientDeathRecipient(String packageName) { 1133 mPackageName = packageName; 1134 } 1135 binderDied()1136 public void binderDied() { 1137 if (DBG) { 1138 Log.d(TAG, "Binder is dead - unregister " + mPackageName); 1139 } 1140 1141 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) { 1142 IBinder token = entry.getKey(); 1143 ClientDeathRecipient deathRec = entry.getValue(); 1144 if (deathRec.equals(this)) { 1145 updateBleAppCount(token, false, mPackageName); 1146 break; 1147 } 1148 } 1149 } 1150 getPackageName()1151 public String getPackageName() { 1152 return mPackageName; 1153 } 1154 } 1155 1156 @Override isBleScanAlwaysAvailable()1157 public boolean isBleScanAlwaysAvailable() { 1158 if (isAirplaneModeOn() && !mEnable) { 1159 return false; 1160 } 1161 try { 1162 return Settings.Global.getInt(mContentResolver, 1163 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0; 1164 } catch (SettingNotFoundException e) { 1165 } 1166 return false; 1167 } 1168 1169 @Override isHearingAidProfileSupported()1170 public boolean isHearingAidProfileSupported() { 1171 return mIsHearingAidProfileSupported; 1172 } 1173 isDeviceProvisioned()1174 private boolean isDeviceProvisioned() { 1175 return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1176 0) != 0; 1177 } 1178 1179 // Monitor change of BLE scan only mode settings. registerForProvisioningStateChange()1180 private void registerForProvisioningStateChange() { 1181 ContentObserver contentObserver = new ContentObserver(null) { 1182 @Override 1183 public void onChange(boolean selfChange) { 1184 if (!isDeviceProvisioned()) { 1185 if (DBG) { 1186 Log.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not " 1187 + "provisioned"); 1188 } 1189 return; 1190 } 1191 if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) { 1192 Log.i(TAG, "Device provisioned, reactivating pending flag changes"); 1193 onInitFlagsChanged(); 1194 } 1195 } 1196 }; 1197 1198 mContentResolver.registerContentObserver( 1199 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false, 1200 contentObserver); 1201 } 1202 1203 // Monitor change of BLE scan only mode settings. registerForBleScanModeChange()1204 private void registerForBleScanModeChange() { 1205 ContentObserver contentObserver = new ContentObserver(null) { 1206 @Override 1207 public void onChange(boolean selfChange) { 1208 if (isBleScanAlwaysAvailable()) { 1209 // Nothing to do 1210 return; 1211 } 1212 // BLE scan is not available. 1213 disableBleScanMode(); 1214 clearBleApps(); 1215 mBluetoothLock.readLock().lock(); 1216 try { 1217 if (mBluetooth != null) { 1218 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 1219 mContext.getPackageName(), false); 1220 synchronousOnBrEdrDown(mContext.getAttributionSource()); 1221 } 1222 } catch (RemoteException | TimeoutException e) { 1223 Log.e(TAG, "error when disabling bluetooth", e); 1224 } finally { 1225 mBluetoothLock.readLock().unlock(); 1226 } 1227 } 1228 }; 1229 1230 mContentResolver.registerContentObserver(Settings.Global.getUriFor( 1231 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false, contentObserver); 1232 } 1233 1234 // Disable ble scan only mode. disableBleScanMode()1235 private void disableBleScanMode() { 1236 mBluetoothLock.writeLock().lock(); 1237 try { 1238 if (mBluetooth != null && synchronousGetState() != BluetoothAdapter.STATE_ON) { 1239 if (DBG) { 1240 Log.d(TAG, "Resetting the mEnable flag for clean disable"); 1241 } 1242 mEnable = false; 1243 } 1244 } catch (RemoteException | TimeoutException e) { 1245 Log.e(TAG, "getState()", e); 1246 } finally { 1247 mBluetoothLock.writeLock().unlock(); 1248 } 1249 } 1250 updateBleAppCount(IBinder token, boolean enable, String packageName)1251 private int updateBleAppCount(IBinder token, boolean enable, String packageName) { 1252 ClientDeathRecipient r = mBleApps.get(token); 1253 if (r == null && enable) { 1254 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); 1255 try { 1256 token.linkToDeath(deathRec, 0); 1257 } catch (RemoteException ex) { 1258 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!"); 1259 } 1260 mBleApps.put(token, deathRec); 1261 if (DBG) { 1262 Log.d(TAG, "Registered for death of " + packageName); 1263 } 1264 } else if (!enable && r != null) { 1265 // Unregister death recipient as the app goes away. 1266 token.unlinkToDeath(r, 0); 1267 mBleApps.remove(token); 1268 if (DBG) { 1269 Log.d(TAG, "Unregistered for death of " + packageName); 1270 } 1271 } 1272 int appCount = mBleApps.size(); 1273 if (DBG) { 1274 Log.d(TAG, appCount + " registered Ble Apps"); 1275 } 1276 return appCount; 1277 } 1278 1279 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) checkBluetoothPermissions(AttributionSource attributionSource, String message, boolean requireForeground)1280 private boolean checkBluetoothPermissions(AttributionSource attributionSource, String message, 1281 boolean requireForeground) { 1282 if (isBluetoothDisallowed()) { 1283 if (DBG) { 1284 Log.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); 1285 } 1286 return false; 1287 } 1288 int callingAppId = getCallingAppId(); 1289 if (!isCallerSystem(callingAppId) 1290 && !isCallerShell(callingAppId) 1291 && !isCallerRoot(callingAppId)) { 1292 checkPackage(attributionSource.getPackageName()); 1293 1294 if (requireForeground && !checkIfCallerIsForegroundUser()) { 1295 Log.w(TAG, "Not allowed for non-active and non system user"); 1296 return false; 1297 } 1298 1299 if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, message)) { 1300 return false; 1301 } 1302 } 1303 return true; 1304 } 1305 enableBle(AttributionSource attributionSource, IBinder token)1306 public boolean enableBle(AttributionSource attributionSource, IBinder token) 1307 throws RemoteException { 1308 final String packageName = attributionSource.getPackageName(); 1309 if (!checkBluetoothPermissions(attributionSource, "enableBle", false) 1310 || isAirplaneModeOn()) { 1311 if (DBG) { 1312 Log.d(TAG, "enableBle(): bluetooth disallowed"); 1313 } 1314 return false; 1315 } 1316 1317 if (DBG) { 1318 Log.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth 1319 + " mBinding = " + mBinding + " mState = " 1320 + BluetoothAdapter.nameForState(mState)); 1321 } 1322 1323 if (isSatelliteModeOn()) { 1324 Log.d(TAG, "enableBle(): not enabling - satellite mode is on."); 1325 return false; 1326 } 1327 1328 updateBleAppCount(token, true, packageName); 1329 1330 if (mState == BluetoothAdapter.STATE_ON 1331 || mState == BluetoothAdapter.STATE_BLE_ON 1332 || mState == BluetoothAdapter.STATE_TURNING_ON 1333 || mState == BluetoothAdapter.STATE_TURNING_OFF 1334 || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { 1335 Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on"); 1336 return true; 1337 } 1338 synchronized (mReceiver) { 1339 // waive WRITE_SECURE_SETTINGS permission check 1340 sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 1341 packageName, true); 1342 } 1343 return true; 1344 } 1345 1346 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) disableBle(AttributionSource attributionSource, IBinder token)1347 public boolean disableBle(AttributionSource attributionSource, IBinder token) 1348 throws RemoteException { 1349 final String packageName = attributionSource.getPackageName(); 1350 if (!checkBluetoothPermissions(attributionSource, "disableBle", false)) { 1351 if (DBG) { 1352 Log.d(TAG, "disableBLE(): bluetooth disallowed"); 1353 } 1354 return false; 1355 } 1356 1357 if (DBG) { 1358 Log.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth 1359 + " mBinding = " + mBinding + " mState = " 1360 + BluetoothAdapter.nameForState(mState)); 1361 } 1362 1363 if (isSatelliteModeOn()) { 1364 Log.d(TAG, "disableBle(): not disabling - satellite mode is on."); 1365 return false; 1366 } 1367 1368 if (mState == BluetoothAdapter.STATE_OFF) { 1369 Log.d(TAG, "disableBLE(): Already disabled"); 1370 return false; 1371 } 1372 updateBleAppCount(token, false, packageName); 1373 1374 if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { 1375 if (mEnable) { 1376 disableBleScanMode(); 1377 } 1378 if (!mEnableExternal) { 1379 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 1380 packageName, false); 1381 sendBrEdrDownCallback(attributionSource); 1382 } 1383 } 1384 return true; 1385 } 1386 1387 // Clear all apps using BLE scan only mode. clearBleApps()1388 private void clearBleApps() { 1389 mBleApps.clear(); 1390 } 1391 1392 /** @hide */ isBleAppPresent()1393 public boolean isBleAppPresent() { 1394 if (DBG) { 1395 Log.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); 1396 } 1397 return mBleApps.size() > 0; 1398 } 1399 1400 /** 1401 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on, 1402 * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off. 1403 */ 1404 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) continueFromBleOnState()1405 private void continueFromBleOnState() { 1406 if (DBG) { 1407 Log.d(TAG, "continueFromBleOnState()"); 1408 } 1409 mBluetoothLock.readLock().lock(); 1410 try { 1411 if (mBluetooth == null) { 1412 Log.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); 1413 return; 1414 } 1415 if (!mEnableExternal && !isBleAppPresent()) { 1416 Log.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now"); 1417 mEnable = false; 1418 synchronousOnBrEdrDown(mContext.getAttributionSource()); 1419 return; 1420 } 1421 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { 1422 // This triggers transition to STATE_ON 1423 synchronousOnLeServiceUp(mContext.getAttributionSource()); 1424 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 1425 } 1426 } catch (RemoteException | TimeoutException e) { 1427 Log.e(TAG, "Unable to call onServiceUp", e); 1428 } finally { 1429 mBluetoothLock.readLock().unlock(); 1430 } 1431 } 1432 1433 /** 1434 * Inform BluetoothAdapter instances that BREDR part is down 1435 * and turn off all service and stack if no LE app needs it 1436 */ 1437 @RequiresPermission(allOf = { 1438 android.Manifest.permission.BLUETOOTH_CONNECT, 1439 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 1440 }) sendBrEdrDownCallback(AttributionSource attributionSource)1441 private void sendBrEdrDownCallback(AttributionSource attributionSource) { 1442 if (DBG) { 1443 Log.d(TAG, "Calling sendBrEdrDownCallback callbacks"); 1444 } 1445 1446 if (mBluetooth == null) { 1447 Log.w(TAG, "Bluetooth handle is null"); 1448 return; 1449 } 1450 1451 if (isBleAppPresent()) { 1452 // Need to stay at BLE ON. Disconnect all Gatt connections 1453 try { 1454 final SynchronousResultReceiver recv = SynchronousResultReceiver.get(); 1455 mBluetoothGatt.unregAll(attributionSource, recv); 1456 recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); 1457 } catch (RemoteException | TimeoutException e) { 1458 Log.e(TAG, "Unable to disconnect all apps.", e); 1459 } 1460 } else { 1461 mBluetoothLock.readLock().lock(); 1462 try { 1463 if (mBluetooth != null) { 1464 synchronousOnBrEdrDown(attributionSource); 1465 } 1466 } catch (RemoteException | TimeoutException e) { 1467 Log.e(TAG, "Call to onBrEdrDown() failed.", e); 1468 } finally { 1469 mBluetoothLock.readLock().unlock(); 1470 } 1471 } 1472 1473 } 1474 enableNoAutoConnect(AttributionSource attributionSource)1475 public boolean enableNoAutoConnect(AttributionSource attributionSource) { 1476 final String packageName = attributionSource.getPackageName(); 1477 if (!checkBluetoothPermissions(attributionSource, "enableNoAutoConnect", false)) { 1478 if (DBG) { 1479 Log.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); 1480 } 1481 return false; 1482 } 1483 1484 if (DBG) { 1485 Log.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " 1486 + mBinding); 1487 } 1488 1489 int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 1490 if (callingAppId != Process.NFC_UID) { 1491 throw new SecurityException("no permission to enable Bluetooth quietly"); 1492 } 1493 1494 if (isSatelliteModeOn()) { 1495 Log.d(TAG, "enableNoAutoConnect(): not enabling - satellite mode is on."); 1496 return false; 1497 } 1498 1499 synchronized (mReceiver) { 1500 mQuietEnableExternal = true; 1501 mEnableExternal = true; 1502 sendEnableMsg(true, 1503 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); 1504 } 1505 return true; 1506 } 1507 enable(AttributionSource attributionSource)1508 public boolean enable(AttributionSource attributionSource) throws RemoteException { 1509 final String packageName = attributionSource.getPackageName(); 1510 if (!checkBluetoothPermissions(attributionSource, "enable", true)) { 1511 if (DBG) { 1512 Log.d(TAG, "enable(): not enabling - bluetooth disallowed"); 1513 } 1514 return false; 1515 } 1516 1517 final int callingUid = Binder.getCallingUid(); 1518 final int callingPid = Binder.getCallingPid(); 1519 if (CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) 1520 && !isPrivileged(callingPid, callingUid) 1521 && !isSystem(packageName, callingUid) 1522 && !isDeviceOwner(callingUid, packageName) 1523 && !isProfileOwner(callingUid, packageName)) { 1524 Log.d(TAG, "enable(): not enabling - Caller is not one of: " 1525 + "privileged | system | deviceOwner | profileOwner"); 1526 return false; 1527 } 1528 1529 if (isSatelliteModeOn()) { 1530 Log.d(TAG, "enable(): not enabling - satellite mode is on."); 1531 return false; 1532 } 1533 1534 if (DBG) { 1535 Log.d(TAG, "enable(" + packageName + "): mBluetooth=" + mBluetooth + " mBinding=" 1536 + mBinding + " mState=" + BluetoothAdapter.nameForState(mState)); 1537 } 1538 1539 synchronized (mReceiver) { 1540 mQuietEnableExternal = false; 1541 mEnableExternal = true; 1542 if (isAirplaneModeOn()) { 1543 mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); 1544 if (isApmEnhancementOn()) { 1545 setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_ON_APM); 1546 setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); 1547 if (isFirstTimeNotification(APM_BT_ENABLED_NOTIFICATION)) { 1548 final long callingIdentity = Binder.clearCallingIdentity(); 1549 try { 1550 mBluetoothAirplaneModeListener.sendApmNotification( 1551 "bluetooth_enabled_apm_title", 1552 "bluetooth_enabled_apm_message", 1553 APM_BT_ENABLED_NOTIFICATION); 1554 } catch (Exception e) { 1555 Log.e(TAG, "APM enhancement BT enabled notification not shown"); 1556 } finally { 1557 Binder.restoreCallingIdentity(callingIdentity); 1558 } 1559 } 1560 } 1561 } 1562 // waive WRITE_SECURE_SETTINGS permission check 1563 sendEnableMsg(false, 1564 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); 1565 } 1566 if (DBG) { 1567 Log.d(TAG, "enable returning"); 1568 } 1569 return true; 1570 } 1571 disable(AttributionSource attributionSource, boolean persist)1572 public boolean disable(AttributionSource attributionSource, boolean persist) 1573 throws RemoteException { 1574 if (!persist) { 1575 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1576 "Need BLUETOOTH_PRIVILEGED permission"); 1577 } 1578 1579 final String packageName = attributionSource.getPackageName(); 1580 if (!checkBluetoothPermissions(attributionSource, "disable", true)) { 1581 if (DBG) { 1582 Log.d(TAG, "disable(): not disabling - bluetooth disallowed"); 1583 } 1584 return false; 1585 } 1586 1587 final int callingUid = Binder.getCallingUid(); 1588 final int callingPid = Binder.getCallingPid(); 1589 if (CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) 1590 && !isPrivileged(callingPid, callingUid) 1591 && !isSystem(packageName, callingUid) 1592 && !isDeviceOwner(callingUid, packageName) 1593 && !isProfileOwner(callingUid, packageName)) { 1594 Log.d(TAG, "disable(): not disabling - Caller is not one of: " 1595 + "privileged | system | deviceOwner | profileOwner"); 1596 return false; 1597 } 1598 1599 if (isSatelliteModeOn()) { 1600 Log.d(TAG, "disable: not disabling - satellite mode is on."); 1601 return false; 1602 } 1603 1604 if (DBG) { 1605 Log.d(TAG, "disable(): mBluetooth=" + mBluetooth + ", persist=" + persist 1606 + ", mBinding=" + mBinding); 1607 } 1608 1609 synchronized (mReceiver) { 1610 if (isAirplaneModeOn()) { 1611 mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); 1612 if (isApmEnhancementOn()) { 1613 setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_OFF_APM); 1614 setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); 1615 } 1616 } 1617 1618 if (persist) { 1619 persistBluetoothSetting(BLUETOOTH_OFF); 1620 } 1621 mEnableExternal = false; 1622 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, 1623 packageName); 1624 } 1625 return true; 1626 } 1627 1628 /** 1629 * Check if AppOpsManager is available and the packageName belongs to calling uid 1630 * 1631 * A null package belongs to any uid 1632 */ checkPackage(String packageName)1633 private void checkPackage(String packageName) { 1634 int callingUid = Binder.getCallingUid(); 1635 1636 if (mAppOps == null) { 1637 Log.w(TAG, "checkPackage(): called before system boot up, uid " 1638 + callingUid + ", packageName " + packageName); 1639 throw new IllegalStateException("System has not boot yet"); 1640 } 1641 if (packageName == null) { 1642 Log.w(TAG, "checkPackage(): called with null packageName from " + callingUid); 1643 return; 1644 } 1645 1646 try { 1647 mAppOps.checkPackage(callingUid, packageName); 1648 } catch (SecurityException e) { 1649 Log.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + callingUid); 1650 throw new SecurityException(e.getMessage()); 1651 } 1652 } 1653 1654 /** 1655 * Check if the caller must still pass permission check or if the caller is exempted 1656 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check. 1657 * 1658 * Commands from some callers may be exempted from triggering the consent UI when 1659 * enabling bluetooth. This exemption is checked via the 1660 * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip 1661 * the consent UI where it may otherwise be required. 1662 * 1663 * @hide 1664 */ 1665 @SuppressLint("AndroidFrameworkRequiresPermission") checkBluetoothPermissionWhenWirelessConsentRequired()1666 private boolean checkBluetoothPermissionWhenWirelessConsentRequired() { 1667 int result = mContext.checkCallingPermission( 1668 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED); 1669 return result == PackageManager.PERMISSION_GRANTED; 1670 } 1671 1672 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) unbindAndFinish()1673 public void unbindAndFinish() { 1674 if (DBG) { 1675 Log.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding 1676 + " mUnbinding = " + mUnbinding); 1677 } 1678 1679 mBluetoothLock.writeLock().lock(); 1680 try { 1681 if (mUnbinding) { 1682 return; 1683 } 1684 mUnbinding = true; 1685 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1686 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); 1687 if (mBluetooth != null) { 1688 //Unregister callback object 1689 try { 1690 synchronousUnregisterCallback(mBluetoothCallback, 1691 mContext.getAttributionSource()); 1692 } catch (RemoteException | TimeoutException e) { 1693 Log.e(TAG, "Unable to unregister BluetoothCallback", e); 1694 } 1695 mBluetoothBinder = null; 1696 mBluetooth = null; 1697 mContext.unbindService(mConnection); 1698 mUnbinding = false; 1699 mBinding = false; 1700 } else { 1701 mUnbinding = false; 1702 } 1703 mBluetoothGatt = null; 1704 } finally { 1705 mBluetoothLock.writeLock().unlock(); 1706 } 1707 } 1708 getBluetoothGatt()1709 public IBluetoothGatt getBluetoothGatt() { 1710 // sync protection 1711 return mBluetoothGatt; 1712 } 1713 1714 @Override bindBluetoothProfileService(int bluetoothProfile, String serviceName, IBluetoothProfileServiceConnection proxy)1715 public boolean bindBluetoothProfileService(int bluetoothProfile, String serviceName, 1716 IBluetoothProfileServiceConnection proxy) { 1717 if (mState != BluetoothAdapter.STATE_ON) { 1718 if (DBG) { 1719 Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile 1720 + ", while Bluetooth was disabled"); 1721 } 1722 return false; 1723 } 1724 synchronized (mProfileServices) { 1725 if (!mSupportedProfileList.contains(bluetoothProfile)) { 1726 Log.w(TAG, "Cannot bind profile: " + bluetoothProfile 1727 + ", not in supported profiles list"); 1728 return false; 1729 } 1730 ProfileServiceConnections psc = 1731 mProfileServices.get(Integer.valueOf(bluetoothProfile)); 1732 if (psc == null) { 1733 if (DBG) { 1734 Log.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " 1735 + bluetoothProfile); 1736 } 1737 psc = new ProfileServiceConnections(new Intent(serviceName)); 1738 if (!psc.bindService(DEFAULT_REBIND_COUNT)) { 1739 return false; 1740 } 1741 1742 mProfileServices.put(new Integer(bluetoothProfile), psc); 1743 } 1744 } 1745 1746 // Introducing a delay to give the client app time to prepare 1747 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 1748 addProxyMsg.arg1 = bluetoothProfile; 1749 addProxyMsg.obj = proxy; 1750 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 1751 return true; 1752 } 1753 1754 @Override unbindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy)1755 public void unbindBluetoothProfileService(int bluetoothProfile, 1756 IBluetoothProfileServiceConnection proxy) { 1757 synchronized (mProfileServices) { 1758 Integer profile = new Integer(bluetoothProfile); 1759 ProfileServiceConnections psc = mProfileServices.get(profile); 1760 if (psc == null) { 1761 return; 1762 } 1763 psc.removeProxy(proxy); 1764 if (psc.isEmpty()) { 1765 // All prxoies are disconnected, unbind with the service. 1766 try { 1767 mContext.unbindService(psc); 1768 } catch (IllegalArgumentException e) { 1769 Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 1770 } 1771 if (!mUnbindingAll) { 1772 mProfileServices.remove(profile); 1773 } 1774 } 1775 } 1776 } 1777 unbindAllBluetoothProfileServices()1778 private void unbindAllBluetoothProfileServices() { 1779 synchronized (mProfileServices) { 1780 mUnbindingAll = true; 1781 for (Integer i : mProfileServices.keySet()) { 1782 ProfileServiceConnections psc = mProfileServices.get(i); 1783 try { 1784 mContext.unbindService(psc); 1785 } catch (IllegalArgumentException e) { 1786 Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 1787 } 1788 psc.removeAllProxies(); 1789 } 1790 mUnbindingAll = false; 1791 mProfileServices.clear(); 1792 } 1793 } 1794 1795 /** 1796 * Send enable message and set adapter name and address. Called when the boot phase becomes 1797 * PHASE_SYSTEM_SERVICES_READY. 1798 */ handleOnBootPhase()1799 public void handleOnBootPhase() { 1800 if (DBG) { 1801 Log.d(TAG, "Bluetooth boot completed"); 1802 } 1803 mAppOps = mContext.getSystemService(AppOpsManager.class); 1804 final boolean isBluetoothDisallowed = isBluetoothDisallowed(); 1805 if (isBluetoothDisallowed) { 1806 return; 1807 } 1808 final boolean isSafeMode = mContext.getPackageManager().isSafeMode(); 1809 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) { 1810 if (DBG) { 1811 Log.d(TAG, "Auto-enabling Bluetooth."); 1812 } 1813 sendEnableMsg(mQuietEnableExternal, 1814 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT, 1815 mContext.getPackageName()); 1816 } else if (!isNameAndAddressSet()) { 1817 if (DBG) { 1818 Log.d(TAG, "Getting adapter name and address"); 1819 } 1820 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1821 mHandler.sendMessage(getMsg); 1822 } 1823 1824 mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext); 1825 if (mBluetoothAirplaneModeListener != null) { 1826 mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); 1827 } 1828 registerForProvisioningStateChange(); 1829 mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG); 1830 loadApmEnhancementStateFromResource(); 1831 } 1832 1833 /** 1834 * Set BluetoothModeChangeHelper for testing 1835 */ 1836 @VisibleForTesting setBluetoothModeChangeHelper(BluetoothModeChangeHelper bluetoothModeChangeHelper)1837 void setBluetoothModeChangeHelper(BluetoothModeChangeHelper bluetoothModeChangeHelper) { 1838 mBluetoothModeChangeHelper = bluetoothModeChangeHelper; 1839 } 1840 1841 /** 1842 * Load whether APM Enhancement feature should be enabled from overlay 1843 */ 1844 @VisibleForTesting loadApmEnhancementStateFromResource()1845 void loadApmEnhancementStateFromResource() { 1846 String btPackageName = mBluetoothModeChangeHelper.getBluetoothPackageName(); 1847 if (btPackageName == null) { 1848 Log.e(TAG, "Unable to find Bluetooth package name with APM resources"); 1849 return; 1850 } 1851 try { 1852 Resources resources = mContext.getPackageManager() 1853 .getResourcesForApplication(btPackageName); 1854 int apmEnhancement = resources.getIdentifier("config_bluetooth_apm_enhancement_enabled", 1855 "bool", btPackageName); 1856 Settings.Global.putInt(mContext.getContentResolver(), 1857 APM_ENHANCEMENT, resources.getBoolean(apmEnhancement) ? 1 : 0); 1858 } catch (Exception e) { 1859 Log.e(TAG, "Unable to set whether APM enhancement should be enabled"); 1860 } 1861 } 1862 1863 /** 1864 * Called when switching to a different foreground user. 1865 */ handleSwitchUser(UserHandle userHandle)1866 void handleSwitchUser(UserHandle userHandle) { 1867 if (DBG) { 1868 Log.d(TAG, "User " + userHandle + " switched"); 1869 } 1870 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle.getIdentifier(), 0).sendToTarget(); 1871 } 1872 1873 /** 1874 * Called when user is unlocked. 1875 */ handleOnUnlockUser(UserHandle userHandle)1876 public void handleOnUnlockUser(UserHandle userHandle) { 1877 if (DBG) { 1878 Log.d(TAG, "User " + userHandle + " unlocked"); 1879 } 1880 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle.getIdentifier(), 0).sendToTarget(); 1881 } 1882 1883 /** 1884 * This class manages the clients connected to a given ProfileService 1885 * and maintains the connection with that service. 1886 */ 1887 private final class ProfileServiceConnections 1888 implements ServiceConnection, IBinder.DeathRecipient { 1889 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 1890 new RemoteCallbackList<IBluetoothProfileServiceConnection>(); 1891 IBinder mService; 1892 ComponentName mClassName; 1893 Intent mIntent; 1894 ProfileServiceConnections(Intent intent)1895 ProfileServiceConnections(Intent intent) { 1896 mService = null; 1897 mClassName = null; 1898 mIntent = intent; 1899 } 1900 bindService(int rebindCount)1901 private boolean bindService(int rebindCount) { 1902 int state = BluetoothAdapter.STATE_OFF; 1903 try { 1904 mBluetoothLock.readLock().lock(); 1905 state = synchronousGetState(); 1906 } catch (RemoteException | TimeoutException e) { 1907 Log.e(TAG, "Unable to call getState", e); 1908 return false; 1909 } finally { 1910 mBluetoothLock.readLock().unlock(); 1911 } 1912 1913 if (state != BluetoothAdapter.STATE_ON) { 1914 if (DBG) { 1915 Log.d(TAG, "Unable to bindService while Bluetooth is disabled"); 1916 } 1917 return false; 1918 } 1919 1920 if (mIntent != null && mService == null 1921 && doBind(mIntent, this, 0, USER_HANDLE_CURRENT_OR_SELF)) { 1922 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1923 msg.obj = this; 1924 msg.arg1 = rebindCount; 1925 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 1926 return true; 1927 } 1928 Log.w(TAG, "Unable to bind with intent: " + mIntent); 1929 return false; 1930 } 1931 addProxy(IBluetoothProfileServiceConnection proxy)1932 private void addProxy(IBluetoothProfileServiceConnection proxy) { 1933 mProxies.register(proxy); 1934 if (mService != null) { 1935 try { 1936 proxy.onServiceConnected(mClassName, mService); 1937 } catch (RemoteException e) { 1938 Log.e(TAG, "Unable to connect to proxy", e); 1939 } 1940 } else { 1941 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 1942 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1943 msg.obj = this; 1944 msg.arg1 = DEFAULT_REBIND_COUNT; 1945 mHandler.sendMessage(msg); 1946 } 1947 } 1948 } 1949 removeProxy(IBluetoothProfileServiceConnection proxy)1950 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 1951 if (proxy != null) { 1952 if (mProxies.unregister(proxy)) { 1953 try { 1954 proxy.onServiceDisconnected(mClassName); 1955 } catch (RemoteException e) { 1956 Log.e(TAG, "Unable to disconnect proxy", e); 1957 } 1958 } 1959 } else { 1960 Log.w(TAG, "Trying to remove a null proxy"); 1961 } 1962 } 1963 removeAllProxies()1964 private void removeAllProxies() { 1965 onServiceDisconnected(mClassName); 1966 mProxies.kill(); 1967 } 1968 isEmpty()1969 private boolean isEmpty() { 1970 return mProxies.getRegisteredCallbackCount() == 0; 1971 } 1972 1973 @Override onServiceConnected(ComponentName className, IBinder service)1974 public void onServiceConnected(ComponentName className, IBinder service) { 1975 // remove timeout message 1976 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 1977 mService = service; 1978 mClassName = className; 1979 try { 1980 mService.linkToDeath(this, 0); 1981 } catch (RemoteException e) { 1982 Log.e(TAG, "Unable to linkToDeath", e); 1983 } 1984 1985 synchronized (mProxies) { 1986 final int n = mProxies.beginBroadcast(); 1987 try { 1988 for (int i = 0; i < n; i++) { 1989 try { 1990 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 1991 } catch (RemoteException e) { 1992 Log.e(TAG, "Unable to connect to proxy", e); 1993 } 1994 } 1995 } finally { 1996 mProxies.finishBroadcast(); 1997 } 1998 } 1999 } 2000 2001 @Override onServiceDisconnected(ComponentName className)2002 public void onServiceDisconnected(ComponentName className) { 2003 if (mService == null) { 2004 return; 2005 } 2006 try { 2007 mService.unlinkToDeath(this, 0); 2008 } catch (NoSuchElementException e) { 2009 Log.e(TAG, "error unlinking to death", e); 2010 } 2011 mService = null; 2012 mClassName = null; 2013 2014 synchronized (mProxies) { 2015 final int n = mProxies.beginBroadcast(); 2016 try { 2017 for (int i = 0; i < n; i++) { 2018 try { 2019 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 2020 } catch (RemoteException e) { 2021 Log.e(TAG, "Unable to disconnect from proxy #" + i, e); 2022 } 2023 } 2024 } finally { 2025 mProxies.finishBroadcast(); 2026 } 2027 } 2028 } 2029 2030 @Override binderDied()2031 public void binderDied() { 2032 if (DBG) { 2033 Log.w(TAG, "Profile service for profile: " + mClassName + " died."); 2034 } 2035 onServiceDisconnected(mClassName); 2036 // Trigger rebind 2037 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 2038 msg.obj = this; 2039 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 2040 } 2041 } 2042 sendBluetoothStateCallback(boolean isUp)2043 private void sendBluetoothStateCallback(boolean isUp) { 2044 synchronized (mStateChangeCallbacks) { 2045 try { 2046 int n = mStateChangeCallbacks.beginBroadcast(); 2047 if (DBG) { 2048 Log.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n 2049 + " receivers."); 2050 } 2051 for (int i = 0; i < n; i++) { 2052 try { 2053 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 2054 } catch (RemoteException e) { 2055 Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e); 2056 } 2057 } 2058 } finally { 2059 mStateChangeCallbacks.finishBroadcast(); 2060 } 2061 } 2062 } 2063 2064 /** 2065 * Inform BluetoothAdapter instances that Adapter service is up 2066 */ sendBluetoothServiceUpCallback()2067 private void sendBluetoothServiceUpCallback() { 2068 synchronized (mCallbacks) { 2069 mBluetoothLock.readLock().lock(); 2070 try { 2071 int n = mCallbacks.beginBroadcast(); 2072 Log.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 2073 for (int i = 0; i < n; i++) { 2074 try { 2075 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 2076 } catch (RemoteException e) { 2077 Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 2078 } 2079 } 2080 } finally { 2081 mCallbacks.finishBroadcast(); 2082 mBluetoothLock.readLock().unlock(); 2083 } 2084 } 2085 } 2086 2087 /** 2088 * Inform BluetoothAdapter instances that Adapter service is down 2089 */ sendBluetoothServiceDownCallback()2090 private void sendBluetoothServiceDownCallback() { 2091 synchronized (mCallbacks) { 2092 try { 2093 int n = mCallbacks.beginBroadcast(); 2094 Log.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 2095 for (int i = 0; i < n; i++) { 2096 try { 2097 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 2098 } catch (RemoteException e) { 2099 Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 2100 } 2101 } 2102 } finally { 2103 mCallbacks.finishBroadcast(); 2104 } 2105 } 2106 } 2107 getAddress(AttributionSource attributionSource)2108 public String getAddress(AttributionSource attributionSource) { 2109 if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getAddress")) { 2110 return null; 2111 } 2112 2113 if (!isCallerSystem(getCallingAppId()) && !checkIfCallerIsForegroundUser()) { 2114 Log.w(TAG, "getAddress(): not allowed for non-active and non system user"); 2115 return null; 2116 } 2117 2118 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 2119 != PackageManager.PERMISSION_GRANTED) { 2120 return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 2121 } 2122 2123 mBluetoothLock.readLock().lock(); 2124 try { 2125 if (mBluetooth != null) { 2126 return synchronousGetAddress(attributionSource); 2127 } 2128 } catch (RemoteException | TimeoutException e) { 2129 Log.e(TAG, 2130 "getAddress(): Unable to retrieve address remotely. Returning cached address", 2131 e); 2132 } finally { 2133 mBluetoothLock.readLock().unlock(); 2134 } 2135 2136 // mAddress is accessed from outside. 2137 // It is alright without a lock. Here, bluetooth is off, no other thread is 2138 // changing mAddress 2139 return mAddress; 2140 } 2141 getName(AttributionSource attributionSource)2142 public String getName(AttributionSource attributionSource) { 2143 if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getName")) { 2144 return null; 2145 } 2146 2147 if (!isCallerSystem(getCallingAppId()) && !checkIfCallerIsForegroundUser()) { 2148 Log.w(TAG, "getName(): not allowed for non-active and non system user"); 2149 return null; 2150 } 2151 2152 mBluetoothLock.readLock().lock(); 2153 try { 2154 if (mBluetooth != null) { 2155 return synchronousGetName(attributionSource); 2156 } 2157 } catch (RemoteException | TimeoutException e) { 2158 Log.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 2159 } finally { 2160 mBluetoothLock.readLock().unlock(); 2161 } 2162 2163 // mName is accessed from outside. 2164 // It alright without a lock. Here, bluetooth is off, no other thread is 2165 // changing mName 2166 return mName; 2167 } 2168 2169 private class BluetoothServiceConnection implements ServiceConnection { onServiceConnected(ComponentName componentName, IBinder service)2170 public void onServiceConnected(ComponentName componentName, IBinder service) { 2171 String name = componentName.getClassName(); 2172 if (DBG) { 2173 Log.d(TAG, "BluetoothServiceConnection: " + name); 2174 } 2175 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 2176 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 2177 msg.arg1 = SERVICE_IBLUETOOTH; 2178 } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 2179 msg.arg1 = SERVICE_IBLUETOOTHGATT; 2180 } else { 2181 Log.e(TAG, "Unknown service connected: " + name); 2182 return; 2183 } 2184 msg.obj = service; 2185 mHandler.sendMessage(msg); 2186 } 2187 onServiceDisconnected(ComponentName componentName)2188 public void onServiceDisconnected(ComponentName componentName) { 2189 // Called if we unexpectedly disconnect. 2190 String name = componentName.getClassName(); 2191 if (DBG) { 2192 Log.d(TAG, "BluetoothServiceConnection, disconnected: " + name); 2193 } 2194 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 2195 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 2196 msg.arg1 = SERVICE_IBLUETOOTH; 2197 } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 2198 msg.arg1 = SERVICE_IBLUETOOTHGATT; 2199 } else { 2200 Log.e(TAG, "Unknown service disconnected: " + name); 2201 return; 2202 } 2203 mHandler.sendMessage(msg); 2204 } 2205 } 2206 2207 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 2208 2209 @VisibleForTesting 2210 class BluetoothHandler extends Handler { 2211 boolean mGetNameAddressOnly = false; 2212 private int mWaitForEnableRetry; 2213 private int mWaitForDisableRetry; 2214 BluetoothHandler(Looper looper)2215 BluetoothHandler(Looper looper) { 2216 super(looper); 2217 } 2218 2219 @Override handleMessage(Message msg)2220 public void handleMessage(Message msg) { 2221 switch (msg.what) { 2222 case MESSAGE_GET_NAME_AND_ADDRESS: 2223 if (DBG) { 2224 Log.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 2225 } 2226 mBluetoothLock.writeLock().lock(); 2227 try { 2228 if ((mBluetooth == null) && (!mBinding)) { 2229 if (DBG) { 2230 Log.d(TAG, "Binding to service to get name and address"); 2231 } 2232 mGetNameAddressOnly = true; 2233 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 2234 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 2235 Intent i = new Intent(IBluetooth.class.getName()); 2236 if (!doBind(i, mConnection, 2237 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 2238 UserHandle.CURRENT)) { 2239 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 2240 } else { 2241 mBinding = true; 2242 } 2243 } else if (mBluetooth != null) { 2244 try { 2245 storeNameAndAddress( 2246 synchronousGetName(mContext.getAttributionSource()), 2247 synchronousGetAddress(mContext.getAttributionSource())); 2248 } catch (RemoteException | TimeoutException e) { 2249 Log.e(TAG, "Unable to grab names", e); 2250 } 2251 if (mGetNameAddressOnly && !mEnable) { 2252 unbindAndFinish(); 2253 } 2254 mGetNameAddressOnly = false; 2255 } 2256 } finally { 2257 mBluetoothLock.writeLock().unlock(); 2258 } 2259 break; 2260 2261 case MESSAGE_ENABLE: 2262 int quietEnable = msg.arg1; 2263 int isBle = msg.arg2; 2264 if (mShutdownInProgress) { 2265 Log.d(TAG, "Skip Bluetooth Enable in device shutdown process"); 2266 break; 2267 } 2268 2269 if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) 2270 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { 2271 // We are handling enable or disable right now, wait for it. 2272 mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, 2273 quietEnable, isBle), ENABLE_DISABLE_DELAY_MS); 2274 break; 2275 } 2276 2277 if (DBG) { 2278 Log.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth =" 2279 + mBluetooth); 2280 } 2281 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2282 mEnable = true; 2283 2284 if (isBle == 0) { 2285 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 2286 } 2287 2288 // Use service interface to get the exact state 2289 mBluetoothLock.readLock().lock(); 2290 try { 2291 if (mBluetooth != null) { 2292 boolean isHandled = true; 2293 int state = synchronousGetState(); 2294 switch (state) { 2295 case BluetoothAdapter.STATE_BLE_ON: 2296 if (isBle == 1) { 2297 Log.i(TAG, "Already at BLE_ON State"); 2298 } else { 2299 Log.w(TAG, "BT Enable in BLE_ON State, going to ON"); 2300 synchronousOnLeServiceUp(mContext.getAttributionSource()); 2301 } 2302 break; 2303 case BluetoothAdapter.STATE_BLE_TURNING_ON: 2304 case BluetoothAdapter.STATE_TURNING_ON: 2305 case BluetoothAdapter.STATE_ON: 2306 Log.i(TAG, "MESSAGE_ENABLE: already enabled"); 2307 break; 2308 default: 2309 isHandled = false; 2310 break; 2311 } 2312 if (isHandled) break; 2313 } 2314 } catch (RemoteException | TimeoutException e) { 2315 Log.e(TAG, "", e); 2316 } finally { 2317 mBluetoothLock.readLock().unlock(); 2318 } 2319 2320 mQuietEnable = (quietEnable == 1); 2321 if (mBluetooth == null) { 2322 handleEnable(mQuietEnable); 2323 } else { 2324 // 2325 // We need to wait until transitioned to STATE_OFF and 2326 // the previous Bluetooth process has exited. The 2327 // waiting period has three components: 2328 // (a) Wait until the local state is STATE_OFF. This 2329 // is accomplished by sending delay a message 2330 // MESSAGE_HANDLE_ENABLE_DELAYED 2331 // (b) Wait until the STATE_OFF state is updated to 2332 // all components. 2333 // (c) Wait until the Bluetooth process exits, and 2334 // ActivityManager detects it. 2335 // The waiting for (b) and (c) is accomplished by 2336 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 2337 // message. The delay time is backed off if Bluetooth 2338 // continuously failed to turn on itself. 2339 // 2340 mWaitForEnableRetry = 0; 2341 Message enableDelayedMsg = 2342 mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); 2343 mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); 2344 } 2345 break; 2346 2347 case MESSAGE_DISABLE: 2348 if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding 2349 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { 2350 // We are handling enable or disable right now, wait for it. 2351 mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), 2352 ENABLE_DISABLE_DELAY_MS); 2353 break; 2354 } 2355 2356 if (DBG) { 2357 Log.d(TAG, "MESSAGE_DISABLE: mBluetooth =" + mBluetooth 2358 + ", mBinding = " + mBinding); 2359 } 2360 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2361 2362 if (mEnable && mBluetooth != null) { 2363 mWaitForDisableRetry = 0; 2364 Message disableDelayedMsg = 2365 mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); 2366 mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); 2367 } else { 2368 mEnable = false; 2369 handleDisable(); 2370 } 2371 break; 2372 2373 case MESSAGE_HANDLE_ENABLE_DELAYED: { 2374 // The Bluetooth is turning off, wait for STATE_OFF 2375 if (mState != BluetoothAdapter.STATE_OFF) { 2376 if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { 2377 mWaitForEnableRetry++; 2378 Message enableDelayedMsg = 2379 mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); 2380 mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); 2381 break; 2382 } else { 2383 Log.e(TAG, "Wait for STATE_OFF timeout"); 2384 } 2385 } 2386 // Either state is changed to STATE_OFF or reaches the maximum retry, we 2387 // should move forward to the next step. 2388 mWaitForEnableRetry = 0; 2389 Message restartMsg = 2390 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2391 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); 2392 Log.d(TAG, "Handle enable is finished"); 2393 break; 2394 } 2395 2396 case MESSAGE_HANDLE_DISABLE_DELAYED: { 2397 boolean disabling = (msg.arg1 == 1); 2398 Log.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); 2399 if (!disabling) { 2400 // The Bluetooth is turning on, wait for STATE_ON 2401 if (mState != BluetoothAdapter.STATE_ON) { 2402 if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { 2403 mWaitForDisableRetry++; 2404 Message disableDelayedMsg = mHandler.obtainMessage( 2405 MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); 2406 mHandler.sendMessageDelayed(disableDelayedMsg, 2407 ENABLE_DISABLE_DELAY_MS); 2408 break; 2409 } else { 2410 Log.e(TAG, "Wait for STATE_ON timeout"); 2411 } 2412 } 2413 // Either state is changed to STATE_ON or reaches the maximum retry, we 2414 // should move forward to the next step. 2415 mWaitForDisableRetry = 0; 2416 mEnable = false; 2417 handleDisable(); 2418 // Wait for state exiting STATE_ON 2419 Message disableDelayedMsg = 2420 mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); 2421 mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); 2422 } else { 2423 // The Bluetooth is turning off, wait for exiting STATE_ON 2424 if (mState == BluetoothAdapter.STATE_ON) { 2425 if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { 2426 mWaitForDisableRetry++; 2427 Message disableDelayedMsg = mHandler.obtainMessage( 2428 MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); 2429 mHandler.sendMessageDelayed(disableDelayedMsg, 2430 ENABLE_DISABLE_DELAY_MS); 2431 break; 2432 } else { 2433 Log.e(TAG, "Wait for exiting STATE_ON timeout"); 2434 } 2435 } 2436 // Either state is exited from STATE_ON or reaches the maximum retry, we 2437 // should move forward to the next step. 2438 Log.d(TAG, "Handle disable is finished"); 2439 } 2440 break; 2441 } 2442 2443 case MESSAGE_RESTORE_USER_SETTING: 2444 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { 2445 if (DBG) { 2446 Log.d(TAG, "Restore Bluetooth state to disabled"); 2447 } 2448 persistBluetoothSetting(BLUETOOTH_OFF); 2449 mEnableExternal = false; 2450 sendDisableMsg( 2451 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, 2452 mContext.getPackageName()); 2453 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { 2454 if (DBG) { 2455 Log.d(TAG, "Restore Bluetooth state to enabled"); 2456 } 2457 mQuietEnableExternal = false; 2458 mEnableExternal = true; 2459 // waive WRITE_SECURE_SETTINGS permission check 2460 sendEnableMsg(false, 2461 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, 2462 mContext.getPackageName()); 2463 } 2464 break; 2465 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { 2466 IBluetoothStateChangeCallback callback = 2467 (IBluetoothStateChangeCallback) msg.obj; 2468 mStateChangeCallbacks.register(callback); 2469 break; 2470 } 2471 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: { 2472 IBluetoothStateChangeCallback callback = 2473 (IBluetoothStateChangeCallback) msg.obj; 2474 mStateChangeCallbacks.unregister(callback); 2475 break; 2476 } 2477 case MESSAGE_ADD_PROXY_DELAYED: { 2478 ProfileServiceConnections psc = mProfileServices.get(msg.arg1); 2479 if (psc == null) { 2480 break; 2481 } 2482 IBluetoothProfileServiceConnection proxy = 2483 (IBluetoothProfileServiceConnection) msg.obj; 2484 psc.addProxy(proxy); 2485 break; 2486 } 2487 case MESSAGE_BIND_PROFILE_SERVICE: { 2488 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 2489 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 2490 if (psc == null) { 2491 break; 2492 } 2493 if (msg.arg1 > 0) { 2494 try { 2495 mContext.unbindService(psc); 2496 } catch (IllegalArgumentException e) { 2497 Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 2498 } 2499 psc.bindService(msg.arg1 - 1); 2500 } 2501 break; 2502 } 2503 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { 2504 if (DBG) { 2505 Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 2506 } 2507 2508 IBinder service = (IBinder) msg.obj; 2509 mBluetoothLock.writeLock().lock(); 2510 try { 2511 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 2512 mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 2513 continueFromBleOnState(); 2514 break; 2515 } // else must be SERVICE_IBLUETOOTH 2516 2517 //Remove timeout 2518 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 2519 2520 mBinding = false; 2521 mBluetoothBinder = service; 2522 mBluetooth = IBluetooth.Stub.asInterface(service); 2523 2524 int foregroundUserId = ActivityManager.getCurrentUser(); 2525 propagateForegroundUserId(foregroundUserId); 2526 2527 if (!isNameAndAddressSet()) { 2528 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 2529 mHandler.sendMessage(getMsg); 2530 if (mGetNameAddressOnly) { 2531 return; 2532 } 2533 } 2534 2535 //Register callback object 2536 try { 2537 synchronousRegisterCallback(mBluetoothCallback, 2538 mContext.getAttributionSource()); 2539 } catch (RemoteException | TimeoutException e) { 2540 Log.e(TAG, "Unable to register BluetoothCallback", e); 2541 } 2542 //Inform BluetoothAdapter instances that service is up 2543 sendBluetoothServiceUpCallback(); 2544 2545 // Get the supported profiles list 2546 try { 2547 mSupportedProfileList = synchronousGetSupportedProfiles( 2548 mContext.getAttributionSource()); 2549 } catch (RemoteException | TimeoutException e) { 2550 Log.e(TAG, "Unable to get the supported profiles list", e); 2551 } 2552 2553 //Do enable request 2554 try { 2555 if (!synchronousEnable(mQuietEnable, mContext.getAttributionSource())) { 2556 Log.e(TAG, "IBluetooth.enable() returned false"); 2557 } 2558 } catch (RemoteException | TimeoutException e) { 2559 Log.e(TAG, "Unable to call enable()", e); 2560 } 2561 } finally { 2562 mBluetoothLock.writeLock().unlock(); 2563 } 2564 2565 if (!mEnable) { 2566 waitForState(Set.of(BluetoothAdapter.STATE_ON)); 2567 handleDisable(); 2568 waitForState(Set.of(BluetoothAdapter.STATE_OFF, 2569 BluetoothAdapter.STATE_TURNING_ON, 2570 BluetoothAdapter.STATE_TURNING_OFF, 2571 BluetoothAdapter.STATE_BLE_TURNING_ON, 2572 BluetoothAdapter.STATE_BLE_ON, 2573 BluetoothAdapter.STATE_BLE_TURNING_OFF)); 2574 } 2575 break; 2576 } 2577 case MESSAGE_BLUETOOTH_STATE_CHANGE: { 2578 int prevState = msg.arg1; 2579 int newState = msg.arg2; 2580 if (DBG) { 2581 Log.d(TAG, 2582 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState( 2583 prevState) + " > " + BluetoothAdapter.nameForState( 2584 newState)); 2585 } 2586 mState = newState; 2587 bluetoothStateChangeHandler(prevState, newState); 2588 // handle error state transition case from TURNING_ON to OFF 2589 // unbind and rebind bluetooth service and enable bluetooth 2590 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState 2591 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { 2592 recoverBluetoothServiceFromError(false); 2593 } 2594 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState 2595 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { 2596 recoverBluetoothServiceFromError(true); 2597 } 2598 // If we tried to enable BT while BT was in the process of shutting down, 2599 // wait for the BT process to fully tear down and then force a restart 2600 // here. This is a bit of a hack (b/29363429). 2601 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState 2602 == BluetoothAdapter.STATE_OFF)) { 2603 if (mEnable) { 2604 Log.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); 2605 waitForState(Set.of(BluetoothAdapter.STATE_OFF)); 2606 Message restartMsg = 2607 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2608 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); 2609 } 2610 } 2611 if (newState == BluetoothAdapter.STATE_ON 2612 || newState == BluetoothAdapter.STATE_BLE_ON) { 2613 // bluetooth is working, reset the counter 2614 if (mErrorRecoveryRetryCounter != 0) { 2615 Log.w(TAG, "bluetooth is recovered from error"); 2616 mErrorRecoveryRetryCounter = 0; 2617 } 2618 } 2619 break; 2620 } 2621 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { 2622 Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); 2623 mBluetoothLock.writeLock().lock(); 2624 try { 2625 if (msg.arg1 == SERVICE_IBLUETOOTH) { 2626 // if service is unbinded already, do nothing and return 2627 if (mBluetooth == null) { 2628 break; 2629 } 2630 mBluetooth = null; 2631 mSupportedProfileList.clear(); 2632 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 2633 mBluetoothGatt = null; 2634 break; 2635 } else { 2636 Log.e(TAG, "Unknown argument for service disconnect!"); 2637 break; 2638 } 2639 } finally { 2640 mBluetoothLock.writeLock().unlock(); 2641 } 2642 2643 // log the unexpected crash 2644 addCrashLog(); 2645 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH, 2646 mContext.getPackageName(), false); 2647 if (mEnable) { 2648 mEnable = false; 2649 // Send a Bluetooth Restart message 2650 Message restartMsg = 2651 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 2652 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); 2653 } 2654 2655 sendBluetoothServiceDownCallback(); 2656 2657 // Send BT state broadcast to update 2658 // the BT icon correctly 2659 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState 2660 == BluetoothAdapter.STATE_ON)) { 2661 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 2662 BluetoothAdapter.STATE_TURNING_OFF); 2663 mState = BluetoothAdapter.STATE_TURNING_OFF; 2664 } 2665 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 2666 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 2667 BluetoothAdapter.STATE_OFF); 2668 } 2669 2670 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 2671 mState = BluetoothAdapter.STATE_OFF; 2672 break; 2673 } 2674 case MESSAGE_RESTART_BLUETOOTH_SERVICE: { 2675 mErrorRecoveryRetryCounter++; 2676 Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count=" 2677 + mErrorRecoveryRetryCounter); 2678 if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) { 2679 /* Enable without persisting the setting as 2680 it doesnt change when IBluetooth 2681 service restarts */ 2682 mEnable = true; 2683 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, 2684 mContext.getPackageName(), true); 2685 handleEnable(mQuietEnable); 2686 } else { 2687 mBluetoothLock.writeLock().lock(); 2688 mBluetooth = null; 2689 mBluetoothLock.writeLock().unlock(); 2690 Log.e(TAG, "Reach maximum retry to restart Bluetooth!"); 2691 } 2692 break; 2693 } 2694 case MESSAGE_TIMEOUT_BIND: { 2695 Log.e(TAG, "MESSAGE_TIMEOUT_BIND"); 2696 mBluetoothLock.writeLock().lock(); 2697 mBinding = false; 2698 mBluetoothLock.writeLock().unlock(); 2699 break; 2700 } 2701 2702 case MESSAGE_USER_SWITCHED: { 2703 if (DBG) { 2704 Log.d(TAG, "MESSAGE_USER_SWITCHED"); 2705 } 2706 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 2707 mBluetoothNotificationManager.createNotificationChannels(); 2708 2709 /* disable and enable BT when detect a user switch */ 2710 if (mBluetooth != null && isEnabled()) { 2711 restartForReason(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH); 2712 } else if (mBinding || mBluetooth != null) { 2713 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 2714 userMsg.arg2 = 1 + msg.arg2; 2715 // if user is switched when service is binding retry after a delay 2716 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 2717 if (DBG) { 2718 Log.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2); 2719 } 2720 } 2721 break; 2722 } 2723 case MESSAGE_USER_UNLOCKED: { 2724 if (DBG) { 2725 Log.d(TAG, "MESSAGE_USER_UNLOCKED"); 2726 } 2727 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 2728 2729 if (mEnable && !mBinding && (mBluetooth == null)) { 2730 // We should be connected, but we gave up for some 2731 // reason; maybe the Bluetooth service wasn't encryption 2732 // aware, so try binding again. 2733 if (DBG) { 2734 Log.d(TAG, "Enabled but not bound; retrying after unlock"); 2735 } 2736 handleEnable(mQuietEnable); 2737 } 2738 break; 2739 } 2740 case MESSAGE_INIT_FLAGS_CHANGED: { 2741 if (DBG) { 2742 Log.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED"); 2743 } 2744 mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); 2745 if (mBluetoothModeChangeHelper.isMediaProfileConnected()) { 2746 Log.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " 2747 + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS 2748 + " ms due to existing connections"); 2749 mHandler.sendEmptyMessageDelayed( 2750 MESSAGE_INIT_FLAGS_CHANGED, 2751 DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); 2752 break; 2753 } 2754 if (!isDeviceProvisioned()) { 2755 Log.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " 2756 + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS 2757 + "ms because device is not provisioned"); 2758 mHandler.sendEmptyMessageDelayed( 2759 MESSAGE_INIT_FLAGS_CHANGED, 2760 DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); 2761 break; 2762 } 2763 if (mBluetooth != null && isEnabled()) { 2764 Log.i(TAG, "Restarting Bluetooth due to init flag change"); 2765 restartForReason( 2766 BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); 2767 } 2768 break; 2769 } 2770 } 2771 } 2772 2773 @RequiresPermission(allOf = { 2774 android.Manifest.permission.BLUETOOTH_CONNECT, 2775 android.Manifest.permission.BLUETOOTH_PRIVILEGED 2776 }) restartForReason(int reason)2777 private void restartForReason(int reason) { 2778 mBluetoothLock.readLock().lock(); 2779 try { 2780 if (mBluetooth != null) { 2781 synchronousUnregisterCallback(mBluetoothCallback, 2782 mContext.getAttributionSource()); 2783 } 2784 } catch (RemoteException | TimeoutException e) { 2785 Log.e(TAG, "Unable to unregister", e); 2786 } finally { 2787 mBluetoothLock.readLock().unlock(); 2788 } 2789 2790 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 2791 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 2792 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 2793 mState = BluetoothAdapter.STATE_OFF; 2794 } 2795 if (mState == BluetoothAdapter.STATE_OFF) { 2796 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 2797 mState = BluetoothAdapter.STATE_TURNING_ON; 2798 } 2799 2800 waitForState(Set.of(BluetoothAdapter.STATE_ON)); 2801 2802 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 2803 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 2804 } 2805 2806 unbindAllBluetoothProfileServices(); 2807 // disable 2808 addActiveLog(reason, mContext.getPackageName(), false); 2809 handleDisable(); 2810 // Pbap service need receive STATE_TURNING_OFF intent to close 2811 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 2812 BluetoothAdapter.STATE_TURNING_OFF); 2813 2814 boolean didDisableTimeout = 2815 !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); 2816 2817 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 2818 BluetoothAdapter.STATE_OFF); 2819 sendBluetoothServiceDownCallback(); 2820 2821 mBluetoothLock.writeLock().lock(); 2822 try { 2823 if (mBluetooth != null) { 2824 mBluetooth = null; 2825 // Unbind 2826 mContext.unbindService(mConnection); 2827 } 2828 mBluetoothGatt = null; 2829 } finally { 2830 mBluetoothLock.writeLock().unlock(); 2831 } 2832 2833 // 2834 // If disabling Bluetooth times out, wait for an 2835 // additional amount of time to ensure the process is 2836 // shut down completely before attempting to restart. 2837 // 2838 if (didDisableTimeout) { 2839 SystemClock.sleep(3000); 2840 } else { 2841 SystemClock.sleep(100); 2842 } 2843 2844 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 2845 mState = BluetoothAdapter.STATE_OFF; 2846 // enable 2847 addActiveLog(reason, mContext.getPackageName(), true); 2848 // mEnable flag could have been reset on disableBLE. Reenable it. 2849 mEnable = true; 2850 handleEnable(mQuietEnable); 2851 } 2852 } 2853 2854 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) handleEnable(boolean quietMode)2855 private void handleEnable(boolean quietMode) { 2856 mQuietEnable = quietMode; 2857 2858 mBluetoothLock.writeLock().lock(); 2859 try { 2860 if ((mBluetooth == null) && (!mBinding)) { 2861 Log.d(TAG, "binding Bluetooth service"); 2862 //Start bind timeout and bind 2863 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 2864 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 2865 Intent i = new Intent(IBluetooth.class.getName()); 2866 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 2867 UserHandle.CURRENT)) { 2868 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 2869 } else { 2870 mBinding = true; 2871 } 2872 } else if (mBluetooth != null) { 2873 //Enable bluetooth 2874 try { 2875 if (!synchronousEnable(mQuietEnable, mContext.getAttributionSource())) { 2876 Log.e(TAG, "IBluetooth.enable() returned false"); 2877 } 2878 } catch (RemoteException | TimeoutException e) { 2879 Log.e(TAG, "Unable to call enable()", e); 2880 } 2881 } 2882 } finally { 2883 mBluetoothLock.writeLock().unlock(); 2884 } 2885 } 2886 doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user)2887 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 2888 ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(), 0); 2889 intent.setComponent(comp); 2890 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 2891 Log.e(TAG, "Fail to bind to: " + intent); 2892 return false; 2893 } 2894 return true; 2895 } 2896 2897 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) handleDisable()2898 private void handleDisable() { 2899 mBluetoothLock.readLock().lock(); 2900 try { 2901 if (mBluetooth != null) { 2902 if (DBG) { 2903 Log.d(TAG, "Sending off request."); 2904 } 2905 if (!synchronousDisable(mContext.getAttributionSource())) { 2906 Log.e(TAG, "IBluetooth.disable() returned false"); 2907 } 2908 } 2909 } catch (RemoteException | TimeoutException e) { 2910 Log.e(TAG, "Unable to call disable()", e); 2911 } finally { 2912 mBluetoothLock.readLock().unlock(); 2913 } 2914 } 2915 getCallingAppId()2916 private static int getCallingAppId() { 2917 return UserHandle.getAppId(Binder.getCallingUid()); 2918 } isCallerSystem(int callingAppId)2919 private static boolean isCallerSystem(int callingAppId) { 2920 return callingAppId == Process.SYSTEM_UID; 2921 } isCallerShell(int callingAppId)2922 private static boolean isCallerShell(int callingAppId) { 2923 return callingAppId == Process.SHELL_UID; 2924 } isCallerRoot(int callingAppId)2925 private static boolean isCallerRoot(int callingAppId) { 2926 return callingAppId == Process.ROOT_UID; 2927 } 2928 checkIfCallerIsForegroundUser()2929 private boolean checkIfCallerIsForegroundUser() { 2930 int callingUid = Binder.getCallingUid(); 2931 UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid); 2932 final long callingIdentity = Binder.clearCallingIdentity(); 2933 UserManager userManager = mContext.getSystemService(UserManager.class); 2934 UserHandle uh = userManager.getProfileParent(callingUser); 2935 UserHandle parentUser = (uh != null) ? uh : USER_HANDLE_NULL; 2936 int callingAppId = UserHandle.getAppId(callingUid); 2937 boolean valid = false; 2938 try { 2939 UserHandle foregroundUser = UserHandle.of(ActivityManager.getCurrentUser()); 2940 valid = (callingUser == foregroundUser) || parentUser == foregroundUser 2941 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid 2942 || callingAppId == Process.SHELL_UID; 2943 if (DBG && !valid) { 2944 Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" 2945 + callingUser + " parentUser=" + parentUser + " foregroundUser=" 2946 + foregroundUser); 2947 } 2948 } finally { 2949 Binder.restoreCallingIdentity(callingIdentity); 2950 } 2951 return valid; 2952 } 2953 sendBleStateChanged(int prevState, int newState)2954 private void sendBleStateChanged(int prevState, int newState) { 2955 if (DBG) { 2956 Log.d(TAG, 2957 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > " 2958 + BluetoothAdapter.nameForState(newState)); 2959 } 2960 // Send broadcast message to everyone else 2961 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 2962 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 2963 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 2964 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2965 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions()); 2966 } 2967 isBleState(int state)2968 private boolean isBleState(int state) { 2969 switch (state) { 2970 case BluetoothAdapter.STATE_BLE_ON: 2971 case BluetoothAdapter.STATE_BLE_TURNING_ON: 2972 case BluetoothAdapter.STATE_BLE_TURNING_OFF: 2973 return true; 2974 } 2975 return false; 2976 } 2977 2978 @RequiresPermission(allOf = { 2979 android.Manifest.permission.BLUETOOTH_CONNECT, 2980 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 2981 }) bluetoothStateChangeHandler(int prevState, int newState)2982 private void bluetoothStateChangeHandler(int prevState, int newState) { 2983 boolean isStandardBroadcast = true; 2984 if (prevState == newState) { // No change. Nothing to do. 2985 return; 2986 } 2987 // Notify all proxy objects first of adapter state change 2988 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) { 2989 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 2990 && newState == BluetoothAdapter.STATE_BLE_ON); 2991 2992 if (newState == BluetoothAdapter.STATE_OFF) { 2993 // If Bluetooth is off, send service down event to proxy objects, and unbind 2994 if (DBG) { 2995 Log.d(TAG, "Bluetooth is complete send Service Down"); 2996 } 2997 sendBluetoothServiceDownCallback(); 2998 unbindAndFinish(); 2999 sendBleStateChanged(prevState, newState); 3000 3001 /* Currently, the OFF intent is broadcasted externally only when we transition 3002 * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state, 3003 * we are guaranteed that the OFF intent has been broadcasted earlier and we 3004 * can safely skip it. 3005 * Conversely, if the previous state is not a BLE state, it indicates that some 3006 * sort of crash has occurred, moving us directly to STATE_OFF without ever 3007 * passing through BLE_ON. We should broadcast the OFF intent in this case. */ 3008 isStandardBroadcast = !isBleState(prevState); 3009 3010 } else if (!intermediate_off) { 3011 // connect to GattService 3012 if (DBG) { 3013 Log.d(TAG, "Bluetooth is in LE only mode"); 3014 } 3015 if (mBluetoothGatt != null || !mContext.getPackageManager() 3016 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { 3017 continueFromBleOnState(); 3018 } else { 3019 if (DBG) { 3020 Log.d(TAG, "Binding Bluetooth GATT service"); 3021 } 3022 Intent i = new Intent(IBluetoothGatt.class.getName()); 3023 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 3024 UserHandle.CURRENT); 3025 } 3026 sendBleStateChanged(prevState, newState); 3027 //Don't broadcase this as std intent 3028 isStandardBroadcast = false; 3029 3030 } else if (intermediate_off) { 3031 if (DBG) { 3032 Log.d(TAG, "Intermediate off, back to LE only mode"); 3033 } 3034 // For LE only mode, broadcast as is 3035 sendBleStateChanged(prevState, newState); 3036 sendBluetoothStateCallback(false); // BT is OFF for general users 3037 // Broadcast as STATE_OFF 3038 newState = BluetoothAdapter.STATE_OFF; 3039 sendBrEdrDownCallback(mContext.getAttributionSource()); 3040 } 3041 } else if (newState == BluetoothAdapter.STATE_ON) { 3042 boolean isUp = (newState == BluetoothAdapter.STATE_ON); 3043 sendBluetoothStateCallback(isUp); 3044 sendBleStateChanged(prevState, newState); 3045 3046 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) { 3047 sendBleStateChanged(prevState, newState); 3048 isStandardBroadcast = false; 3049 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 3050 sendBleStateChanged(prevState, newState); 3051 if (prevState != BluetoothAdapter.STATE_TURNING_OFF) { 3052 isStandardBroadcast = false; 3053 } else { 3054 // Broadcast as STATE_OFF for app that do not receive BLE update 3055 newState = BluetoothAdapter.STATE_OFF; 3056 sendBrEdrDownCallback(mContext.getAttributionSource()); 3057 } 3058 } else if (newState == BluetoothAdapter.STATE_TURNING_ON 3059 || newState == BluetoothAdapter.STATE_TURNING_OFF) { 3060 sendBleStateChanged(prevState, newState); 3061 } 3062 3063 if (isStandardBroadcast) { 3064 if (prevState == BluetoothAdapter.STATE_BLE_ON) { 3065 // Show prevState of BLE_ON as OFF to standard users 3066 prevState = BluetoothAdapter.STATE_OFF; 3067 } 3068 if (DBG) { 3069 Log.d(TAG, 3070 "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > " 3071 + BluetoothAdapter.nameForState(newState)); 3072 } 3073 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 3074 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 3075 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 3076 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3077 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, 3078 getTempAllowlistBroadcastOptions()); 3079 } 3080 } 3081 waitForManagerState(int state)3082 boolean waitForManagerState(int state) { 3083 return waitForState(Set.of(state), false); 3084 } 3085 waitForState(Set<Integer> states)3086 private boolean waitForState(Set<Integer> states) { 3087 return waitForState(states, true); 3088 } waitForState(Set<Integer> states, boolean failIfUnbind)3089 private boolean waitForState(Set<Integer> states, boolean failIfUnbind) { 3090 for (int i = 0; i < 10; i++) { 3091 mBluetoothLock.readLock().lock(); 3092 try { 3093 if (mBluetooth == null && failIfUnbind) { 3094 Log.e(TAG, "waitForState " + states + " Bluetooth is not unbind"); 3095 return false; 3096 } 3097 if (mBluetooth == null && states.contains(BluetoothAdapter.STATE_OFF)) { 3098 return true; // We are so OFF that the bluetooth is not bind 3099 } 3100 if (mBluetooth != null && states.contains(synchronousGetState())) { 3101 return true; 3102 } 3103 } catch (RemoteException | TimeoutException e) { 3104 Log.e(TAG, "getState()", e); 3105 break; 3106 } finally { 3107 mBluetoothLock.readLock().unlock(); 3108 } 3109 SystemClock.sleep(300); 3110 } 3111 Log.e(TAG, "waitForState " + states + " time out"); 3112 return false; 3113 } 3114 sendDisableMsg(int reason, String packageName)3115 private void sendDisableMsg(int reason, String packageName) { 3116 BluetoothServerProxy.getInstance().handlerSendWhatMessage(mHandler, MESSAGE_DISABLE); 3117 addActiveLog(reason, packageName, false); 3118 } 3119 sendEnableMsg(boolean quietMode, int reason, String packageName)3120 private void sendEnableMsg(boolean quietMode, int reason, String packageName) { 3121 sendEnableMsg(quietMode, reason, packageName, false); 3122 } 3123 sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle)3124 private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) { 3125 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 3126 isBle ? 1 : 0)); 3127 addActiveLog(reason, packageName, true); 3128 mLastEnabledTime = SystemClock.elapsedRealtime(); 3129 } 3130 addActiveLog(int reason, String packageName, boolean enable)3131 private void addActiveLog(int reason, String packageName, boolean enable) { 3132 synchronized (mActiveLogs) { 3133 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { 3134 mActiveLogs.remove(); 3135 } 3136 mActiveLogs.add( 3137 new ActiveLog(reason, packageName, enable, System.currentTimeMillis())); 3138 3139 int state = 3140 enable 3141 ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED 3142 : BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; 3143 3144 BluetoothStatsLog.write_non_chained( 3145 BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, 3146 Binder.getCallingUid(), 3147 null, 3148 state, 3149 reason, 3150 packageName); 3151 } 3152 } 3153 addCrashLog()3154 private void addCrashLog() { 3155 synchronized (mCrashTimestamps) { 3156 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) { 3157 mCrashTimestamps.removeFirst(); 3158 } 3159 mCrashTimestamps.add(System.currentTimeMillis()); 3160 mCrashes++; 3161 } 3162 } 3163 3164 @RequiresPermission(allOf = { 3165 android.Manifest.permission.BLUETOOTH_CONNECT, 3166 android.Manifest.permission.BLUETOOTH_PRIVILEGED, 3167 }) recoverBluetoothServiceFromError(boolean clearBle)3168 private void recoverBluetoothServiceFromError(boolean clearBle) { 3169 Log.e(TAG, "recoverBluetoothServiceFromError"); 3170 boolean repeatAirplaneRunnable = false; 3171 3172 // 0 means we are matching unset `what` since we are using a token instead 3173 if (mHandler.hasMessages(0, ON_AIRPLANE_MODE_CHANGED_TOKEN)) { 3174 mHandler.removeCallbacksAndMessages(ON_AIRPLANE_MODE_CHANGED_TOKEN); 3175 repeatAirplaneRunnable = true; 3176 } 3177 mBluetoothLock.readLock().lock(); 3178 try { 3179 if (mBluetooth != null) { 3180 //Unregister callback object 3181 synchronousUnregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); 3182 } 3183 } catch (RemoteException | TimeoutException e) { 3184 Log.e(TAG, "Unable to unregister", e); 3185 } finally { 3186 mBluetoothLock.readLock().unlock(); 3187 } 3188 3189 SystemClock.sleep(500); 3190 3191 // disable 3192 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR, 3193 mContext.getPackageName(), false); 3194 handleDisable(); 3195 3196 waitForState(Set.of(BluetoothAdapter.STATE_OFF)); 3197 3198 sendBluetoothServiceDownCallback(); 3199 3200 mBluetoothLock.writeLock().lock(); 3201 try { 3202 if (mBluetooth != null) { 3203 mBluetooth = null; 3204 // Unbind 3205 mContext.unbindService(mConnection); 3206 } 3207 mBluetoothGatt = null; 3208 } finally { 3209 mBluetoothLock.writeLock().unlock(); 3210 } 3211 3212 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 3213 mState = BluetoothAdapter.STATE_OFF; 3214 3215 if (clearBle) { 3216 clearBleApps(); 3217 } 3218 3219 mEnable = false; 3220 3221 // Send a Bluetooth Restart message to reenable bluetooth 3222 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); 3223 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 3224 3225 if (repeatAirplaneRunnable) { 3226 onAirplaneModeChanged(); 3227 } 3228 } 3229 isBluetoothDisallowed()3230 private boolean isBluetoothDisallowed() { 3231 final long callingIdentity = Binder.clearCallingIdentity(); 3232 try { 3233 return mContext.getSystemService(UserManager.class) 3234 .hasUserRestrictionForUser(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); 3235 } finally { 3236 Binder.restoreCallingIdentity(callingIdentity); 3237 } 3238 } 3239 3240 /** 3241 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not 3242 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default 3243 * state if Bluetooth is not disallowed. 3244 * 3245 * @param userHandle user to disable bluetooth sharing for 3246 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed. 3247 */ updateOppLauncherComponentState(UserHandle userHandle, boolean bluetoothSharingDisallowed)3248 private void updateOppLauncherComponentState(UserHandle userHandle, 3249 boolean bluetoothSharingDisallowed) { 3250 try { 3251 int newState; 3252 if (bluetoothSharingDisallowed) { 3253 newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 3254 } else if (BluetoothProperties.isProfileOppEnabled().orElse(false)) { 3255 newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 3256 } else { 3257 newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 3258 } 3259 3260 // Bluetooth OPP activities that should always be enabled, 3261 // even when Bluetooth is turned OFF. 3262 List<String> baseBluetoothOppActivities = List.of( 3263 // Base sharing activity 3264 "com.android.bluetooth.opp.BluetoothOppLauncherActivity", 3265 // BT enable activities 3266 "com.android.bluetooth.opp.BluetoothOppBtEnableActivity", 3267 "com.android.bluetooth.opp.BluetoothOppBtEnablingActivity", 3268 "com.android.bluetooth.opp.BluetoothOppBtErrorActivity"); 3269 3270 PackageManager systemPackageManager = mContext.getPackageManager(); 3271 PackageManager userPackageManager = mContext.createContextAsUser(userHandle, 0) 3272 .getPackageManager(); 3273 var allPackages = systemPackageManager.getPackagesForUid(Process.BLUETOOTH_UID); 3274 for (String candidatePackage : allPackages) { 3275 Log.v(TAG, "Searching package " + candidatePackage); 3276 PackageInfo packageInfo; 3277 try { 3278 packageInfo = systemPackageManager.getPackageInfo( 3279 candidatePackage, 3280 PackageManager.PackageInfoFlags.of( 3281 PackageManager.GET_ACTIVITIES 3282 | PackageManager.MATCH_ANY_USER 3283 | PackageManager.MATCH_UNINSTALLED_PACKAGES 3284 | PackageManager.MATCH_DISABLED_COMPONENTS)); 3285 } catch (PackageManager.NameNotFoundException e) { 3286 // ignore, try next package 3287 Log.e(TAG, "Could not find package " + candidatePackage); 3288 continue; 3289 } catch (Exception e) { 3290 Log.e(TAG, "Error while loading package" + e); 3291 continue; 3292 } 3293 if (packageInfo.activities == null) { 3294 continue; 3295 } 3296 for (var activity : packageInfo.activities) { 3297 Log.v(TAG, "Checking activity " + activity.name); 3298 if (baseBluetoothOppActivities.contains(activity.name)) { 3299 for (String activityName : baseBluetoothOppActivities) { 3300 userPackageManager.setComponentEnabledSetting( 3301 new ComponentName(candidatePackage, activityName), 3302 newState, 3303 PackageManager.DONT_KILL_APP 3304 ); 3305 } 3306 return; 3307 } 3308 } 3309 } 3310 3311 Log.e(TAG, 3312 "Cannot toggle Bluetooth OPP activities, could not find them in any package"); 3313 } catch (Exception e) { 3314 Log.e(TAG, "updateOppLauncherComponentState failed: " + e); 3315 } 3316 } 3317 getServiceRestartMs()3318 private int getServiceRestartMs() { 3319 return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS; 3320 } 3321 3322 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)3323 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 3324 if ((mContext.checkCallingOrSelfPermission( 3325 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED)) { 3326 return; 3327 } 3328 if ((args.length > 0) && args[0].startsWith("--proto")) { 3329 dumpProto(fd); 3330 return; 3331 } 3332 String errorMsg = null; 3333 3334 writer.println("Bluetooth Status"); 3335 writer.println(" enabled: " + isEnabled()); 3336 writer.println(" state: " + BluetoothAdapter.nameForState(mState)); 3337 writer.println(" address: " + mAddress); 3338 writer.println(" name: " + mName); 3339 if (mEnable) { 3340 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; 3341 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", 3342 (int) (onDuration / (1000 * 60 * 60)), 3343 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), 3344 (int) (onDuration % 1000)); 3345 writer.println(" time since enabled: " + onDurationString); 3346 } 3347 3348 if (mActiveLogs.size() == 0) { 3349 writer.println("\nBluetooth never enabled!"); 3350 } else { 3351 writer.println("\nEnable log:"); 3352 for (ActiveLog log : mActiveLogs) { 3353 writer.println(" " + log); 3354 } 3355 } 3356 3357 writer.println( 3358 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); 3359 if (mCrashes == CRASH_LOG_MAX_SIZE) { 3360 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); 3361 } 3362 for (Long time : mCrashTimestamps) { 3363 writer.println(" " + timeToLog(time)); 3364 } 3365 3366 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") 3367 + " registered"); 3368 for (ClientDeathRecipient app : mBleApps.values()) { 3369 writer.println(" " + app.getPackageName()); 3370 } 3371 3372 writer.println("\nBluetoothManagerService:"); 3373 writer.println(" mEnable:" + mEnable); 3374 writer.println(" mQuietEnable:" + mQuietEnable); 3375 writer.println(" mEnableExternal:" + mEnableExternal); 3376 writer.println(" mQuietEnableExternal:" + mQuietEnableExternal); 3377 3378 writer.println(""); 3379 writer.flush(); 3380 if (args.length == 0) { 3381 // Add arg to produce output 3382 args = new String[1]; 3383 args[0] = "--print"; 3384 } 3385 3386 if (mBluetoothBinder == null) { 3387 errorMsg = "Bluetooth Service not connected"; 3388 } else { 3389 try { 3390 mBluetoothBinder.dump(fd, args); 3391 } catch (RemoteException re) { 3392 errorMsg = "RemoteException while dumping Bluetooth Service"; 3393 } 3394 } 3395 if (errorMsg != null) { 3396 writer.println(errorMsg); 3397 } 3398 } 3399 dumpProto(FileDescriptor fd)3400 private void dumpProto(FileDescriptor fd) { 3401 final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd)); 3402 proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled()); 3403 proto.write(BluetoothManagerServiceDumpProto.STATE, mState); 3404 proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, 3405 BluetoothAdapter.nameForState(mState)); 3406 proto.write(BluetoothManagerServiceDumpProto.ADDRESS, mAddress); 3407 proto.write(BluetoothManagerServiceDumpProto.NAME, mName); 3408 if (mEnable) { 3409 proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime); 3410 } 3411 proto.write(BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS, 3412 SystemClock.elapsedRealtime()); 3413 for (ActiveLog log : mActiveLogs) { 3414 long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS); 3415 log.dump(proto); 3416 proto.end(token); 3417 } 3418 proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes); 3419 proto.write(BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED, 3420 mCrashes == CRASH_LOG_MAX_SIZE); 3421 for (Long time : mCrashTimestamps) { 3422 proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time); 3423 } 3424 proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size()); 3425 for (ClientDeathRecipient app : mBleApps.values()) { 3426 proto.write(BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES, 3427 app.getPackageName()); 3428 } 3429 proto.flush(); 3430 } 3431 getEnableDisableReasonString(int reason)3432 private static String getEnableDisableReasonString(int reason) { 3433 switch (reason) { 3434 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST: 3435 return "APPLICATION_REQUEST"; 3436 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE: 3437 return "AIRPLANE_MODE"; 3438 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED: 3439 return "DISALLOWED"; 3440 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED: 3441 return "RESTARTED"; 3442 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR: 3443 return "START_ERROR"; 3444 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT: 3445 return "SYSTEM_BOOT"; 3446 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH: 3447 return "CRASH"; 3448 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH: 3449 return "USER_SWITCH"; 3450 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: 3451 return "RESTORE_USER_SETTING"; 3452 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: 3453 return "FACTORY_RESET"; 3454 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED: 3455 return "INIT_FLAGS_CHANGED"; 3456 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: 3457 default: return "UNKNOWN[" + reason + "]"; 3458 } 3459 } 3460 3461 @SuppressLint("AndroidFrameworkRequiresPermission") checkPermissionForDataDelivery(Context context, String permission, AttributionSource attributionSource, String message)3462 private static boolean checkPermissionForDataDelivery(Context context, String permission, 3463 AttributionSource attributionSource, String message) { 3464 PermissionManager pm = context.getSystemService(PermissionManager.class); 3465 if (pm == null) { 3466 return false; 3467 } 3468 AttributionSource currentAttribution = new AttributionSource 3469 .Builder(context.getAttributionSource()) 3470 .setNext(attributionSource) 3471 .build(); 3472 final int result = pm.checkPermissionForDataDeliveryFromDataSource(permission, 3473 currentAttribution, message); 3474 if (result == PERMISSION_GRANTED) { 3475 return true; 3476 } 3477 3478 final String msg = "Need " + permission + " permission for " + attributionSource + ": " 3479 + message; 3480 if (result == PERMISSION_HARD_DENIED) { 3481 throw new SecurityException(msg); 3482 } else { 3483 Log.w(TAG, msg); 3484 return false; 3485 } 3486 } 3487 3488 /** 3489 * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns 3490 * false if the result is a soft denial. Throws SecurityException if the result is a hard 3491 * denial. 3492 * 3493 * <p>Should be used in situations where the app op should not be noted. 3494 */ 3495 @SuppressLint("AndroidFrameworkRequiresPermission") 3496 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) checkConnectPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message)3497 public static boolean checkConnectPermissionForDataDelivery( 3498 Context context, AttributionSource attributionSource, String message) { 3499 return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, 3500 attributionSource, message); 3501 } 3502 3503 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)3504 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 3505 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 3506 @NonNull String[] args) { 3507 return new BluetoothShellCommand(this, mContext).exec(this, in.getFileDescriptor(), 3508 out.getFileDescriptor(), err.getFileDescriptor(), args); 3509 } 3510 3511 // TODO(b/193460475): Remove when tooling supports SystemApi to public API. 3512 @SuppressLint("NewApi") getTempAllowlistBroadcastOptions()3513 static @NonNull Bundle getTempAllowlistBroadcastOptions() { 3514 final long duration = 10_000; 3515 final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); 3516 bOptions.setTemporaryAppAllowlist(duration, 3517 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 3518 PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); 3519 return bOptions.toBundle(); 3520 } 3521 resolveSystemService(@onNull Intent intent, @NonNull PackageManager pm, int flags)3522 private ComponentName resolveSystemService(@NonNull Intent intent, 3523 @NonNull PackageManager pm, int flags) { 3524 List<ResolveInfo> results = pm.queryIntentServices(intent, flags); 3525 if (results == null) { 3526 return null; 3527 } 3528 ComponentName comp = null; 3529 for (int i = 0; i < results.size(); i++) { 3530 ResolveInfo ri = results.get(i); 3531 if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 3532 continue; 3533 } 3534 ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName, 3535 ri.serviceInfo.name); 3536 if (comp != null) { 3537 throw new IllegalStateException("Multiple system services handle " + intent 3538 + ": " + comp + ", " + foundComp); 3539 } 3540 comp = foundComp; 3541 } 3542 return comp; 3543 } 3544 isPrivileged(int pid, int uid)3545 private boolean isPrivileged(int pid, int uid) { 3546 return (mContext.checkPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED, pid, uid) 3547 == PackageManager.PERMISSION_GRANTED) 3548 || (mContext.getPackageManager().checkSignatures(uid, Process.SYSTEM_UID) 3549 == PackageManager.SIGNATURE_MATCH); 3550 } 3551 getDeviceOwner()3552 private Pair<UserHandle, ComponentName> getDeviceOwner() { 3553 DevicePolicyManager devicePolicyManager = 3554 mContext.getSystemService(DevicePolicyManager.class); 3555 if (devicePolicyManager == null) return null; 3556 long ident = Binder.clearCallingIdentity(); 3557 UserHandle deviceOwnerUser = null; 3558 ComponentName deviceOwnerComponent = null; 3559 try { 3560 deviceOwnerUser = devicePolicyManager.getDeviceOwnerUser(); 3561 deviceOwnerComponent = devicePolicyManager.getDeviceOwnerComponentOnAnyUser(); 3562 } finally { 3563 Binder.restoreCallingIdentity(ident); 3564 } 3565 if (deviceOwnerUser == null || deviceOwnerComponent == null 3566 || deviceOwnerComponent.getPackageName() == null) { 3567 return null; 3568 } 3569 return new Pair<>(deviceOwnerUser, deviceOwnerComponent); 3570 } 3571 isDeviceOwner(int uid, String packageName)3572 private boolean isDeviceOwner(int uid, String packageName) { 3573 if (packageName == null) { 3574 Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); 3575 return false; 3576 } 3577 3578 Pair<UserHandle, ComponentName> deviceOwner = getDeviceOwner(); 3579 3580 // no device owner 3581 if (deviceOwner == null) return false; 3582 3583 return deviceOwner.first.equals(UserHandle.getUserHandleForUid(uid)) 3584 && deviceOwner.second.getPackageName().equals(packageName); 3585 } 3586 isProfileOwner(int uid, String packageName)3587 private boolean isProfileOwner(int uid, String packageName) { 3588 Context userContext; 3589 try { 3590 userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, 3591 UserHandle.getUserHandleForUid(uid)); 3592 } catch (PackageManager.NameNotFoundException e) { 3593 Log.e(TAG, "Unknown package name"); 3594 return false; 3595 } 3596 if (userContext == null) { 3597 Log.e(TAG, "Unable to retrieve user context for " + uid); 3598 return false; 3599 } 3600 DevicePolicyManager devicePolicyManager = 3601 userContext.getSystemService(DevicePolicyManager.class); 3602 if (devicePolicyManager == null) { 3603 Log.w(TAG, "Error retrieving DPM service"); 3604 return false; 3605 } 3606 return devicePolicyManager.isProfileOwnerApp(packageName); 3607 } 3608 isSystem(String packageName, int uid)3609 public boolean isSystem(String packageName, int uid) { 3610 long ident = Binder.clearCallingIdentity(); 3611 try { 3612 ApplicationInfo info = mContext.getPackageManager().getApplicationInfoAsUser( 3613 packageName, 0, UserHandle.getUserHandleForUid(uid)); 3614 return (info.flags & FLAGS_SYSTEM_APP) != 0; 3615 } catch (PackageManager.NameNotFoundException e) { 3616 return false; 3617 } finally { 3618 Binder.restoreCallingIdentity(ident); 3619 } 3620 } 3621 3622 /** 3623 * Sets Bluetooth HCI snoop log mode 3624 */ 3625 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) 3626 @Override setBtHciSnoopLogMode(int mode)3627 public int setBtHciSnoopLogMode(int mode) { 3628 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 3629 "Need BLUETOOTH_PRIVILEGED permission"); 3630 final BluetoothProperties.snoop_log_mode_values snoopMode; 3631 3632 switch (mode) { 3633 case BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED: 3634 snoopMode = BluetoothProperties.snoop_log_mode_values.DISABLED; 3635 break; 3636 case BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED: 3637 snoopMode = BluetoothProperties.snoop_log_mode_values.FILTERED; 3638 break; 3639 case BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL: 3640 snoopMode = BluetoothProperties.snoop_log_mode_values.FULL; 3641 break; 3642 default: 3643 Log.e(TAG, "setBtHciSnoopLogMode: Not a valid mode:" + mode); 3644 return BluetoothStatusCodes.ERROR_BAD_PARAMETERS; 3645 } 3646 try { 3647 BluetoothProperties.snoop_log_mode(snoopMode); 3648 } catch (RuntimeException e) { 3649 Log.e(TAG, "setBtHciSnoopLogMode: Failed to set mode to " + mode + ": " + e); 3650 return BluetoothStatusCodes.ERROR_UNKNOWN; 3651 } 3652 return BluetoothStatusCodes.SUCCESS; 3653 } 3654 3655 /** 3656 * Gets Bluetooth HCI snoop log mode 3657 */ 3658 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) 3659 @Override getBtHciSnoopLogMode()3660 public int getBtHciSnoopLogMode() { 3661 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 3662 "Need BLUETOOTH_PRIVILEGED permission"); 3663 BluetoothProperties.snoop_log_mode_values mode = BluetoothProperties.snoop_log_mode() 3664 .orElse(BluetoothProperties.snoop_log_mode_values.DISABLED); 3665 if (mode == BluetoothProperties.snoop_log_mode_values.FILTERED) { 3666 return BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED; 3667 } else if (mode == BluetoothProperties.snoop_log_mode_values.FULL) { 3668 return BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL; 3669 } 3670 return BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED; 3671 } 3672 3673 /** 3674 * Check if BLE is supported by this platform 3675 * @param context current device context 3676 * @return true if BLE is supported, false otherwise 3677 */ isBleSupported(Context context)3678 private static boolean isBleSupported(Context context) { 3679 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE); 3680 } 3681 3682 /** 3683 * Check if this is an automotive device 3684 * @param context current device context 3685 * @return true if this Android device is an automotive device, false otherwise 3686 */ isAutomotive(Context context)3687 private static boolean isAutomotive(Context context) { 3688 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 3689 } 3690 3691 /** 3692 * Check if this is a watch device 3693 * @param context current device context 3694 * @return true if this Android device is a watch device, false otherwise 3695 */ isWatch(Context context)3696 private static boolean isWatch(Context context) { 3697 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); 3698 } 3699 3700 /** 3701 * Check if this is a TV device 3702 * @param context current device context 3703 * @return true if this Android device is a TV device, false otherwise 3704 */ isTv(Context context)3705 private static boolean isTv(Context context) { 3706 PackageManager pm = context.getPackageManager(); 3707 return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) 3708 || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); 3709 } 3710 } 3711 3712