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.bluetooth.BluetoothAdapter.STATE_BLE_ON;
20 import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_OFF;
21 import static android.bluetooth.BluetoothAdapter.STATE_BLE_TURNING_ON;
22 import static android.bluetooth.BluetoothAdapter.STATE_OFF;
23 import static android.bluetooth.BluetoothAdapter.STATE_ON;
24 import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF;
25 import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;
26 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE;
27 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST;
28 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH;
29 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED;
30 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET;
31 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED;
32 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING;
33 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_SATELLITE_MODE;
34 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR;
35 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT;
36 import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH;
37 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
38 
39 import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
40 
41 import static java.util.Objects.requireNonNull;
42 
43 import android.annotation.NonNull;
44 import android.app.ActivityManager;
45 import android.app.BroadcastOptions;
46 import android.bluetooth.BluetoothAdapter;
47 import android.bluetooth.BluetoothStatusCodes;
48 import android.bluetooth.IBluetooth;
49 import android.bluetooth.IBluetoothCallback;
50 import android.bluetooth.IBluetoothManager;
51 import android.bluetooth.IBluetoothManagerCallback;
52 import android.content.BroadcastReceiver;
53 import android.content.ComponentName;
54 import android.content.ContentResolver;
55 import android.content.Context;
56 import android.content.Intent;
57 import android.content.IntentFilter;
58 import android.content.ServiceConnection;
59 import android.content.pm.ApplicationInfo;
60 import android.content.pm.PackageInfo;
61 import android.content.pm.PackageManager;
62 import android.content.pm.ResolveInfo;
63 import android.database.ContentObserver;
64 import android.os.Binder;
65 import android.os.Build;
66 import android.os.Bundle;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.Looper;
70 import android.os.Message;
71 import android.os.PowerExemptionManager;
72 import android.os.Process;
73 import android.os.RemoteCallbackList;
74 import android.os.RemoteException;
75 import android.os.SystemClock;
76 import android.os.SystemProperties;
77 import android.os.UserHandle;
78 import android.os.UserManager;
79 import android.provider.Settings;
80 import android.provider.Settings.SettingNotFoundException;
81 import android.sysprop.BluetoothProperties;
82 import android.util.proto.ProtoOutputStream;
83 
84 import androidx.annotation.RequiresApi;
85 
86 import com.android.bluetooth.BluetoothStatsLog;
87 import com.android.bluetooth.flags.Flags;
88 import com.android.internal.annotations.GuardedBy;
89 import com.android.internal.annotations.VisibleForTesting;
90 import com.android.modules.expresslog.Counter;
91 import com.android.server.BluetoothManagerServiceDumpProto;
92 import com.android.server.bluetooth.airplane.AirplaneModeListener;
93 import com.android.server.bluetooth.satellite.SatelliteModeListener;
94 
95 import libcore.util.SneakyThrow;
96 
97 import kotlin.Unit;
98 import kotlin.time.TimeSource;
99 
100 import java.io.FileDescriptor;
101 import java.io.FileOutputStream;
102 import java.io.PrintWriter;
103 import java.lang.reflect.InvocationTargetException;
104 import java.lang.reflect.Method;
105 import java.time.Duration;
106 import java.time.Instant;
107 import java.time.ZoneId;
108 import java.time.format.DateTimeFormatter;
109 import java.util.Arrays;
110 import java.util.LinkedList;
111 import java.util.List;
112 import java.util.Locale;
113 import java.util.Map;
114 import java.util.concurrent.Callable;
115 import java.util.concurrent.CompletableFuture;
116 import java.util.concurrent.ConcurrentHashMap;
117 import java.util.concurrent.ExecutionException;
118 import java.util.concurrent.Executors;
119 import java.util.concurrent.FutureTask;
120 import java.util.concurrent.TimeUnit;
121 import java.util.concurrent.TimeoutException;
122 import java.util.concurrent.locks.ReentrantReadWriteLock;
123 
124 class BluetoothManagerService {
125     private static final String TAG = BluetoothManagerService.class.getSimpleName();
126 
127     private static final int ACTIVE_LOG_MAX_SIZE = 20;
128     private static final int CRASH_LOG_MAX_SIZE = 100;
129 
130     // See android.os.Build.HW_TIMEOUT_MULTIPLIER. This should not be set on real hw
131     private static final int HW_MULTIPLIER = SystemProperties.getInt("ro.hw_timeout_multiplier", 1);
132 
133     // Maximum msec to wait for a bind
134     private static final int TIMEOUT_BIND_MS = 4000 * HW_MULTIPLIER;
135 
136     // Timeout value for synchronous binder call
137     private static final Duration STATE_TIMEOUT = Duration.ofSeconds(4 * HW_MULTIPLIER);
138 
139     // Maximum msec to wait for service restart
140     private static final int SERVICE_RESTART_TIME_MS = 400 * HW_MULTIPLIER;
141     // Maximum msec to wait for restart due to error
142     private static final int ERROR_RESTART_TIME_MS = 3000 * HW_MULTIPLIER;
143     // Maximum msec to delay MESSAGE_USER_SWITCHED
144     private static final int USER_SWITCHED_TIME_MS = 200 * HW_MULTIPLIER;
145     // Delay for the addProxy function in msec
146     private static final int ADD_PROXY_DELAY_MS = 100 * HW_MULTIPLIER;
147     // Delay for retrying enable and disable in msec
148     private static final int ENABLE_DISABLE_DELAY_MS = 300 * HW_MULTIPLIER;
149 
150     @VisibleForTesting static final int MESSAGE_ENABLE = 1;
151     @VisibleForTesting static final int MESSAGE_DISABLE = 2;
152     @VisibleForTesting static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3;
153     @VisibleForTesting static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
154     @VisibleForTesting static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
155     @VisibleForTesting static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
156     @VisibleForTesting static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
157     @VisibleForTesting static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
158     @VisibleForTesting static final int MESSAGE_TIMEOUT_BIND = 100;
159     @VisibleForTesting static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
160     @VisibleForTesting static final int MESSAGE_USER_SWITCHED = 300;
161     @VisibleForTesting static final int MESSAGE_USER_UNLOCKED = 301;
162     @VisibleForTesting static final int MESSAGE_RESTORE_USER_SETTING = 500;
163 
164     private static final int RESTORE_SETTING_TO_ON = 1;
165     private static final int RESTORE_SETTING_TO_OFF = 0;
166 
167     private static final int MAX_ERROR_RESTART_RETRIES = 6;
168     private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10;
169 
170     // Bluetooth persisted setting is off
171     @VisibleForTesting static final int BLUETOOTH_OFF = 0;
172     // Bluetooth persisted setting is on
173     // and Airplane mode won't affect Bluetooth state at start up
174     // This is the default value
175     @VisibleForTesting static final int BLUETOOTH_ON_BLUETOOTH = 1;
176     // Bluetooth persisted setting is on
177     // but Airplane mode will affect Bluetooth state at start up
178     // and Airplane mode will have higher priority.
179     @VisibleForTesting static final int BLUETOOTH_ON_AIRPLANE = 2;
180 
181     private final Context mContext;
182     private final Looper mLooper;
183 
184     private final UserManager mUserManager;
185 
186     // Locks are not provided for mName and mAddress.
187     // They are accessed in handler or broadcast receiver, same thread context.
188     private String mAddress = null;
189     private String mName = null;
190     private final ContentResolver mContentResolver;
191     private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks =
192             new RemoteCallbackList<IBluetoothManagerCallback>();
193     private final BluetoothServiceBinder mBinder;
194 
195     private final ReentrantReadWriteLock mAdapterLock = new ReentrantReadWriteLock();
196 
197     @GuardedBy("mAdapterLock")
198     private AdapterBinder mAdapter = null;
199 
200     // used inside handler thread
201     private boolean mQuietEnable = false;
202     private boolean mEnable = false;
203     private boolean mShutdownInProgress = false;
204 
205     private Context mCurrentUserContext = null;
206 
timeToLog(long timestamp)207     static String timeToLog(long timestamp) {
208         return DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS")
209                 .withZone(ZoneId.systemDefault())
210                 .format(Instant.ofEpochMilli(timestamp));
211     }
212 
213     // Used for tracking apps that enabled / disabled Bluetooth.
214     private static class ActiveLog {
215         private int mReason;
216         private String mPackageName;
217         private boolean mEnable;
218         private boolean mIsBle;
219         private long mTimestamp;
220 
ActiveLog(int reason, String packageName, boolean enable, boolean isBle, long timestamp)221         ActiveLog(int reason, String packageName, boolean enable, boolean isBle, long timestamp) {
222             mReason = reason;
223             mPackageName = packageName;
224             mEnable = enable;
225             mIsBle = isBle;
226             mTimestamp = timestamp;
227             Log.d(TAG, this.toString());
228         }
229 
230         @Override
toString()231         public String toString() {
232             return timeToLog(mTimestamp)
233                     + (" \tPackage [" + mPackageName + "]")
234                     + " requested to"
235                     + (" [" + (mEnable ? "Enable" : "Disable") + (mIsBle ? "Ble" : "") + "]")
236                     + (". \tReason is " + getEnableDisableReasonString(mReason));
237         }
238 
getTimestamp()239         long getTimestamp() {
240             return mTimestamp;
241         }
242 
getEnable()243         boolean getEnable() {
244             return mEnable;
245         }
246 
dump(ProtoOutputStream proto)247         void dump(ProtoOutputStream proto) {
248             proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp);
249             proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable);
250             proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName);
251             proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason);
252         }
253     }
254 
255     private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
256     private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
257     private int mCrashes = 0;
258     private long mLastEnabledTime;
259 
260     // configuration from external IBinder call which is used to
261     // synchronize with broadcast receiver.
262     private boolean mQuietEnableExternal = false;
263     private boolean mEnableExternal = false;
264 
265     // Map of apps registered to keep BLE scanning on.
266     private Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<>();
267 
268     private final BluetoothAdapterState mState = new BluetoothAdapterState();
269 
270     private final BluetoothHandler mHandler;
271     private int mErrorRecoveryRetryCounter = 0;
272 
273     private final boolean mIsHearingAidProfileSupported;
274 
275     private final IBluetoothCallback mBluetoothCallback =
276             new IBluetoothCallback.Stub() {
277                 @Override
278                 public void onBluetoothStateChange(int prevState, int newState)
279                         throws RemoteException {
280                     mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState)
281                             .sendToTarget();
282                 }
283             };
284 
onUserRestrictionsChanged(UserHandle userHandle)285     public void onUserRestrictionsChanged(UserHandle userHandle) {
286         final boolean newBluetoothDisallowed =
287                 mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_BLUETOOTH, userHandle);
288         // Disallow Bluetooth sharing when either Bluetooth is disallowed or Bluetooth sharing
289         // is disallowed
290         final boolean newBluetoothSharingDisallowed =
291                 mUserManager.hasUserRestrictionForUser(
292                                 UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle)
293                         || newBluetoothDisallowed;
294 
295         // Disable OPP activities for this userHandle
296         updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed);
297 
298         // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
299         // Only trigger once instead of for all users
300         if (UserHandle.SYSTEM.equals(userHandle) && newBluetoothDisallowed) {
301             sendDisableMsg(ENABLE_DISABLE_REASON_DISALLOWED);
302         }
303     }
304 
onFactoryReset()305     boolean onFactoryReset() {
306         // Wait for stable state if bluetooth is temporary state.
307         int state = getState();
308         if (state == STATE_BLE_TURNING_ON
309                 || state == STATE_TURNING_ON
310                 || state == STATE_TURNING_OFF) {
311             if (!waitForState(STATE_BLE_ON, STATE_ON)) {
312                 return false;
313             }
314         }
315 
316         // Clear registered LE apps to force shut-off Bluetooth
317         clearBleApps();
318         state = getState();
319         mAdapterLock.readLock().lock();
320         try {
321             if (mAdapter == null) {
322                 return false;
323             }
324             if (state == STATE_BLE_ON) {
325                 addActiveLog(ENABLE_DISABLE_REASON_FACTORY_RESET, false);
326                 mAdapter.stopBle(mContext.getAttributionSource());
327                 return true;
328             } else if (state == STATE_ON) {
329                 addActiveLog(ENABLE_DISABLE_REASON_FACTORY_RESET, false);
330                 mAdapter.disable(mContext.getAttributionSource());
331                 return true;
332             }
333         } catch (RemoteException e) {
334             Log.e(TAG, "Unable to shutdown Bluetooth", e);
335         } finally {
336             mAdapterLock.readLock().unlock();
337         }
338         return false;
339     }
340 
estimateBusyTime(int state)341     private int estimateBusyTime(int state) {
342         if (state == STATE_BLE_ON && isBluetoothPersistedStateOn()) {
343             // Bluetooth is in BLE and is starting classic
344             return SERVICE_RESTART_TIME_MS;
345         } else if (state != STATE_ON && state != STATE_OFF && state != STATE_BLE_ON) {
346             // Bluetooth is turning state
347             return ADD_PROXY_DELAY_MS;
348         } else if (mHandler.hasMessages(MESSAGE_ENABLE)
349                 || mHandler.hasMessages(MESSAGE_DISABLE)
350                 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)
351                 || mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
352                 || mHandler.hasMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE)
353                 || mHandler.hasMessages(MESSAGE_TIMEOUT_BIND)) {
354             Log.d(
355                     TAG,
356                     "Busy reason:"
357                             + " ENABLE="
358                             + mHandler.hasMessages(MESSAGE_ENABLE)
359                             + " DISABLE="
360                             + mHandler.hasMessages(MESSAGE_DISABLE)
361                             + " HANDLE_ENABLE_DELAYED="
362                             + mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)
363                             + " HANDLE_DISABLE_DELAYED="
364                             + mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
365                             + " RESTART_BLUETOOTH_SERVICE="
366                             + mHandler.hasMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE)
367                             + " TIMEOUT_BIND="
368                             + mHandler.hasMessages(MESSAGE_TIMEOUT_BIND));
369             // Bluetooth is restarting
370             return SERVICE_RESTART_TIME_MS;
371         }
372         return 0;
373     }
374 
delayModeChangedIfNeeded(Object token, Runnable r, String modechanged)375     private void delayModeChangedIfNeeded(Object token, Runnable r, String modechanged) {
376         final int state = getState();
377         final int delayMs = estimateBusyTime(state);
378         Log.d(
379                 TAG,
380                 ("delayModeChangedIfNeeded(" + modechanged + "):")
381                         + (" state=" + BluetoothAdapter.nameForState(state))
382                         + (" Airplane.isOnOverrode=" + AirplaneModeListener.isOnOverrode())
383                         + (" Airplane.isOn=" + AirplaneModeListener.isOn())
384                         + (" isSatelliteModeOn()=" + isSatelliteModeOn())
385                         + (" delayed=" + delayMs + "ms"));
386 
387         mHandler.removeCallbacksAndMessages(token);
388 
389         if (delayMs > 0) {
390             mHandler.postDelayed(
391                     () -> delayModeChangedIfNeeded(token, r, modechanged), token, delayMs);
392         } else {
393             r.run();
394         }
395     }
396 
397     /** Send Intent to the Notification Service in the Bluetooth app */
sendToggleNotification(String notificationReason)398     Unit sendToggleNotification(String notificationReason) {
399         Intent intent =
400                 new Intent("android.bluetooth.notification.action.SEND_TOGGLE_NOTIFICATION");
401         intent.setComponent(resolveSystemService(intent));
402         intent.putExtra(
403                 "android.bluetooth.notification.extra.NOTIFICATION_REASON", notificationReason);
404         mCurrentUserContext.startService(intent);
405         return Unit.INSTANCE;
406     }
407 
408     private static final Object ON_AIRPLANE_MODE_CHANGED_TOKEN = new Object();
409     private static final Object ON_SATELLITE_MODE_CHANGED_TOKEN = new Object();
410     private static final Object ON_SWITCH_USER_TOKEN = new Object();
411 
onAirplaneModeChanged(boolean isAirplaneModeOn)412     Unit onAirplaneModeChanged(boolean isAirplaneModeOn) {
413         mHandler.postDelayed(
414                 () ->
415                         delayModeChangedIfNeeded(
416                                 ON_AIRPLANE_MODE_CHANGED_TOKEN,
417                                 () -> handleAirplaneModeChanged(isAirplaneModeOn),
418                                 "onAirplaneModeChanged"),
419                 ON_AIRPLANE_MODE_CHANGED_TOKEN,
420                 0);
421         return Unit.INSTANCE;
422     }
423 
424     // TODO(b/289584302): Update to private once use_new_satellite_mode is enabled
onSatelliteModeChanged(boolean isSatelliteModeOn)425     Unit onSatelliteModeChanged(boolean isSatelliteModeOn) {
426         mHandler.postDelayed(
427                 () ->
428                         delayModeChangedIfNeeded(
429                                 ON_SATELLITE_MODE_CHANGED_TOKEN,
430                                 () -> handleSatelliteModeChanged(isSatelliteModeOn),
431                                 "onSatelliteModeChanged"),
432                 ON_SATELLITE_MODE_CHANGED_TOKEN,
433                 0);
434         return Unit.INSTANCE;
435     }
436 
onSwitchUser(UserHandle userHandle)437     void onSwitchUser(UserHandle userHandle) {
438         mHandler.postDelayed(
439                 () ->
440                         delayModeChangedIfNeeded(
441                                 ON_SWITCH_USER_TOKEN,
442                                 () -> handleSwitchUser(userHandle),
443                                 "onSwitchUser"),
444                 ON_SWITCH_USER_TOKEN,
445                 0);
446     }
447 
forceToOffFromModeChange(int currentState, int reason)448     private void forceToOffFromModeChange(int currentState, int reason) {
449         // Clear registered LE apps to force shut-off
450         clearBleApps();
451 
452         if (reason == ENABLE_DISABLE_REASON_SATELLITE_MODE
453                 || !AirplaneModeListener.hasUserToggledApm(mCurrentUserContext)) {
454             // AirplaneMode can have a state where it does not impact the AutoOnFeature
455             AutoOnFeature.pause();
456         }
457 
458         if (currentState == STATE_ON) {
459             sendDisableMsg(reason);
460         } else if (currentState == STATE_BLE_ON) {
461             // If currentState is BLE_ON make sure we trigger stopBle
462             mAdapterLock.readLock().lock();
463             try {
464                 if (mAdapter != null) {
465                     addActiveLog(reason, false);
466                     mAdapter.stopBle(mContext.getAttributionSource());
467                     mEnable = false;
468                     mEnableExternal = false;
469                 }
470             } catch (RemoteException e) {
471                 Log.e(TAG, "Unable to call stopBle", e);
472             } finally {
473                 mAdapterLock.readLock().unlock();
474             }
475         }
476     }
477 
handleAirplaneModeChanged(boolean isAirplaneModeOn)478     private void handleAirplaneModeChanged(boolean isAirplaneModeOn) {
479         synchronized (this) {
480             if (isBluetoothPersistedStateOn()) {
481                 if (isAirplaneModeOn) {
482                     setBluetoothPersistedState(BLUETOOTH_ON_AIRPLANE);
483                 } else {
484                     setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH);
485                 }
486             }
487 
488             int currentState = mState.get();
489 
490             Log.d(
491                     TAG,
492                     ("handleAirplaneModeChanged(" + isAirplaneModeOn + "):")
493                             + (" currentState=" + BluetoothAdapter.nameForState(currentState)));
494 
495             if (isAirplaneModeOn) {
496                 forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE);
497             } else if (mEnableExternal) {
498                 sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_AIRPLANE_MODE);
499             } else if (currentState != STATE_ON) {
500                 autoOnSetupTimer();
501             }
502         }
503     }
504 
handleSatelliteModeChanged(boolean isSatelliteModeOn)505     private void handleSatelliteModeChanged(boolean isSatelliteModeOn) {
506         final int currentState = mState.get();
507 
508         if (shouldBluetoothBeOn(isSatelliteModeOn) && currentState != STATE_ON) {
509             sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_SATELLITE_MODE);
510         } else if (!shouldBluetoothBeOn(isSatelliteModeOn) && currentState != STATE_OFF) {
511             forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_SATELLITE_MODE);
512         } else if (!isSatelliteModeOn
513                 && !shouldBluetoothBeOn(isSatelliteModeOn)
514                 && currentState != STATE_ON) {
515             autoOnSetupTimer();
516         }
517     }
518 
shouldBluetoothBeOn(boolean isSatelliteModeOn)519     private boolean shouldBluetoothBeOn(boolean isSatelliteModeOn) {
520         if (!isBluetoothPersistedStateOn()) {
521             Log.d(TAG, "shouldBluetoothBeOn: User want BT off.");
522             return false;
523         }
524 
525         if (isSatelliteModeOn) {
526             Log.d(TAG, "shouldBluetoothBeOn: BT should be off as satellite mode is on.");
527             return false;
528         }
529 
530         if (AirplaneModeListener.isOnOverrode() && isBluetoothPersistedStateOnAirplane()) {
531             Log.d(TAG, "shouldBluetoothBeOn: BT should be off as airplaneMode is on.");
532             return false;
533         }
534 
535         Log.d(TAG, "shouldBluetoothBeOn: BT should be on.");
536         return true;
537     }
538 
539     private final BroadcastReceiver mReceiver =
540             new BroadcastReceiver() {
541                 @Override
542                 public void onReceive(Context context, Intent intent) {
543                     String action = intent.getAction();
544                     if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
545                         String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
546                         if (newName != null) {
547                             Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
548                             storeNameAndAddress(newName, null);
549                         }
550                     } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
551                         String newAddress =
552                                 intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
553                         if (newAddress != null) {
554                             Log.d(TAG, "Local address changed to …" + logAddress(newAddress));
555                             storeNameAndAddress(null, newAddress);
556                         } else {
557                             Log.e(TAG, "No Bluetooth Adapter address parameter found");
558                         }
559                     } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
560                         final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
561                         if (Settings.Global.BLUETOOTH_ON.equals(name)) {
562                             // The Bluetooth On state may be changed during system restore.
563                             final String prevValue =
564                                     intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
565                             final String newValue =
566                                     intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
567 
568                             Log.d(
569                                     TAG,
570                                     "ACTION_SETTING_RESTORED with BLUETOOTH_ON"
571                                             + (" prevValue=" + prevValue)
572                                             + (" newValue=" + newValue));
573 
574                             if ((newValue != null)
575                                     && (prevValue != null)
576                                     && !prevValue.equals(newValue)) {
577                                 mHandler.obtainMessage(
578                                                 MESSAGE_RESTORE_USER_SETTING,
579                                                 newValue.equals("0")
580                                                         ? RESTORE_SETTING_TO_OFF
581                                                         : RESTORE_SETTING_TO_ON,
582                                                 0)
583                                         .sendToTarget();
584                             }
585                         }
586                     } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
587                         Log.i(TAG, "Device is shutting down.");
588                         mShutdownInProgress = true;
589                         mAdapterLock.readLock().lock();
590                         try {
591                             mEnable = false;
592                             mEnableExternal = false;
593                             if (mAdapter != null && mState.oneOf(STATE_BLE_ON)) {
594                                 mAdapter.stopBle(mContext.getAttributionSource());
595                             } else if (mAdapter != null && mState.oneOf(STATE_ON)) {
596                                 mAdapter.disable(mContext.getAttributionSource());
597                             }
598                         } catch (RemoteException e) {
599                             Log.e(TAG, "Unable to shutdown Bluetooth", e);
600                         } finally {
601                             mAdapterLock.readLock().unlock();
602                         }
603                     }
604                 }
605             };
606 
BluetoothManagerService(@onNull Context context, @NonNull Looper looper)607     BluetoothManagerService(@NonNull Context context, @NonNull Looper looper) {
608         mContext = requireNonNull(context, "Context cannot be null");
609         mContentResolver = requireNonNull(mContext.getContentResolver(), "Resolver cannot be null");
610         mLooper = requireNonNull(looper, "Looper cannot be null");
611 
612         mUserManager =
613                 requireNonNull(
614                         mContext.getSystemService(UserManager.class),
615                         "UserManager system service cannot be null");
616 
617         mBinder = new BluetoothServiceBinder(this, mLooper, mContext, mUserManager);
618         mHandler = new BluetoothHandler(mLooper);
619 
620         // Observe BLE scan only mode settings change.
621         if (Flags.respectBleScanSetting()) {
622             BleScanSettingListener.initialize(mLooper, mContentResolver, this::onBleScanDisabled);
623         } else {
624             registerForBleScanModeChange();
625         }
626 
627         // Disable ASHA if BLE is not supported, overriding any system property
628         if (!isBleSupported(mContext)) {
629             mIsHearingAidProfileSupported = false;
630         } else {
631             // ASHA default value is:
632             //   * disabled on Automotive, TV, and Watch.
633             //   * enabled for other form factor
634             // This default value can be overridden with a system property
635             final boolean isAshaEnabledByDefault =
636                     !(isAutomotive(mContext) || isWatch(mContext) || isTv(mContext));
637             mIsHearingAidProfileSupported =
638                     BluetoothProperties.isProfileAshaCentralEnabled()
639                             .orElse(isAshaEnabledByDefault);
640         }
641 
642         IntentFilter filter = new IntentFilter();
643         filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
644         filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
645         filter.addAction(Intent.ACTION_SETTING_RESTORED);
646         filter.addAction(Intent.ACTION_SHUTDOWN);
647         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
648         mContext.registerReceiver(mReceiver, filter, null, mHandler);
649 
650         IntentFilter filterUser = new IntentFilter();
651         filterUser.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
652         filterUser.addAction(Intent.ACTION_USER_SWITCHED);
653         filterUser.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
654         mContext.registerReceiverForAllUsers(
655                 new BroadcastReceiver() {
656                     @Override
657                     public void onReceive(Context context, Intent intent) {
658                         switch (intent.getAction()) {
659                             case Intent.ACTION_USER_SWITCHED:
660                                 int foregroundUserId =
661                                         intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
662                                 propagateForegroundUserId(foregroundUserId);
663                                 break;
664                             case UserManager.ACTION_USER_RESTRICTIONS_CHANGED:
665                                 onUserRestrictionsChanged(getSendingUser());
666                                 break;
667                             default:
668                                 Log.e(
669                                         TAG,
670                                         "Unknown broadcast received in BluetoothManagerService"
671                                                 + " receiver registered across all users");
672                         }
673                     }
674                 },
675                 filterUser,
676                 null,
677                 mHandler);
678 
679         loadStoredNameAndAddress();
680         if (isBluetoothPersistedStateOn()) {
681             Log.i(TAG, "Startup: Bluetooth persisted state is ON.");
682             mEnableExternal = true;
683         }
684 
685         { // AutoOn feature initialization of flag guarding
686             final boolean autoOnFlag = Flags.autoOnFeature();
687             final boolean autoOnProperty =
688                     SystemProperties.getBoolean("bluetooth.server.automatic_turn_on", false);
689             Log.d(TAG, "AutoOnFeature status: flag=" + autoOnFlag + ", property=" + autoOnProperty);
690 
691             mDeviceConfigAllowAutoOn = autoOnFlag && autoOnProperty;
692             if (mDeviceConfigAllowAutoOn) {
693                 Counter.logIncrement("bluetooth.value_auto_on_supported");
694             }
695         }
696     }
697 
onBleScanDisabled()698     private Unit onBleScanDisabled() {
699         if (mState.oneOf(STATE_OFF, STATE_BLE_TURNING_OFF)) {
700             Log.i(TAG, "onBleScanDisabled: Nothing to do, Bluetooth is already turning off");
701             return Unit.INSTANCE;
702         }
703         clearBleApps();
704         try {
705             mAdapter.unregAllGattClient(mContext.getAttributionSource());
706         } catch (RemoteException e) {
707             Log.e(TAG, "onBleScanDisabled: unregAllGattClient failed", e);
708         }
709         if (mState.oneOf(STATE_BLE_ON)) {
710             Log.i(TAG, "onBleScanDisabled: Shutting down BLE_ON mode");
711             try {
712                 mAdapter.stopBle(mContext.getAttributionSource());
713             } catch (RemoteException e) {
714                 Log.e(TAG, "onBleScanDisabled: stopBle failed", e);
715             }
716         } else {
717             Log.i(TAG, "onBleScanDisabled: Bluetooth is not in BLE_ON, staying on");
718         }
719         return Unit.INSTANCE;
720     }
721 
getBinder()722     IBluetoothManager.Stub getBinder() {
723         return mBinder;
724     }
725 
726     /** Returns true if satellite mode is turned on. */
isSatelliteModeOn()727     private boolean isSatelliteModeOn() {
728         return SatelliteModeListener.isOn();
729     }
730 
731     /** Returns true if the Bluetooth saved state is "on" */
isBluetoothPersistedStateOn()732     private boolean isBluetoothPersistedStateOn() {
733         final int state =
734                 BluetoothServerProxy.getInstance()
735                         .getBluetoothPersistedState(mContentResolver, BLUETOOTH_ON_BLUETOOTH);
736         Log.d(TAG, "isBluetoothPersistedStateOn: " + state);
737         return state != BLUETOOTH_OFF;
738     }
739 
isBluetoothPersistedStateOnAirplane()740     private boolean isBluetoothPersistedStateOnAirplane() {
741         final int state =
742                 BluetoothServerProxy.getInstance()
743                         .getBluetoothPersistedState(mContentResolver, BLUETOOTH_ON_BLUETOOTH);
744         Log.d(TAG, "isBluetoothPersistedStateOnAirplane: " + state);
745         return state == BLUETOOTH_ON_AIRPLANE;
746     }
747 
748     /** Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH */
isBluetoothPersistedStateOnBluetooth()749     private boolean isBluetoothPersistedStateOnBluetooth() {
750         final int state =
751                 BluetoothServerProxy.getInstance()
752                         .getBluetoothPersistedState(mContentResolver, BLUETOOTH_ON_BLUETOOTH);
753         Log.d(TAG, "isBluetoothPersistedStateOnBluetooth: " + state);
754         return state == BLUETOOTH_ON_BLUETOOTH;
755     }
756 
setBluetoothPersistedState(int state)757     private void setBluetoothPersistedState(int state) {
758         BluetoothServerProxy.getInstance().setBluetoothPersistedState(mContentResolver, state);
759     }
760 
761     /** Returns true if the Bluetooth Adapter's name and address is locally cached */
isNameAndAddressSet()762     private boolean isNameAndAddressSet() {
763         return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
764     }
765 
766     /** Retrieve the Bluetooth Adapter's name and address and save it in the local cache */
loadStoredNameAndAddress()767     private void loadStoredNameAndAddress() {
768         if (BluetoothProperties.isAdapterAddressValidationEnabled().orElse(false)
769                 && Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 0)
770                         == 0) {
771             // if the valid flag is not set, don't load the address and name
772             Log.w(TAG, "There is no valid bluetooth name and address stored");
773             return;
774         }
775         mName =
776                 BluetoothServerProxy.getInstance()
777                         .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME);
778         mAddress =
779                 BluetoothServerProxy.getInstance()
780                         .settingsSecureGetString(
781                                 mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS);
782 
783         Log.d(TAG, "loadStoredNameAndAddress: Name=" + mName + ", Address=" + logAddress(mAddress));
784     }
785 
logAddress(String address)786     private String logAddress(String address) {
787         if (address == null) {
788             return "[address is null]";
789         }
790         if (address.length() != 17) {
791             return "[address invalid]";
792         }
793         return "XX:XX:XX:XX:" + address.substring(address.length() - 5);
794     }
795 
796     /**
797      * Save the Bluetooth name and address in the persistent store. Only non-null values will be
798      * saved.
799      */
storeNameAndAddress(String name, String address)800     private void storeNameAndAddress(String name, String address) {
801         final String logHeader = "storeNameAndAddress(" + name + ", " + logAddress(address) + "): ";
802         if (name != null) {
803             if (Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_NAME, name)) {
804                 mName = name;
805             } else {
806                 Log.e(TAG, logHeader + "Failed. Name is still " + mName);
807             }
808         }
809 
810         if (address != null) {
811             if (Settings.Secure.putString(
812                     mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, address)) {
813                 mAddress = address;
814             } else {
815                 Log.e(TAG, logHeader + "Failed. Address is still " + logAddress(mAddress));
816             }
817         }
818 
819         if ((mName != null) && (mAddress != null)) {
820             Settings.Secure.putInt(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 1);
821         }
822         Log.d(TAG, logHeader + "Completed successfully");
823     }
824 
registerAdapter(IBluetoothManagerCallback callback)825     IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
826         synchronized (mCallbacks) {
827             mCallbacks.register(callback);
828         }
829         return mAdapter != null ? mAdapter.getAdapterBinder() : null;
830     }
831 
unregisterAdapter(IBluetoothManagerCallback callback)832     void unregisterAdapter(IBluetoothManagerCallback callback) {
833         synchronized (mCallbacks) {
834             mCallbacks.unregister(callback);
835         }
836     }
837 
isEnabled()838     boolean isEnabled() {
839         return getState() == STATE_ON;
840     }
841 
842     /**
843      * Sends the current foreground user id to the Bluetooth process. This user id is used to
844      * determine if Binder calls are coming from the active user.
845      *
846      * @param userId is the foreground user id we are propagating to the Bluetooth process
847      */
propagateForegroundUserId(int userId)848     private void propagateForegroundUserId(int userId) {
849         mAdapterLock.readLock().lock();
850         try {
851             if (mAdapter != null) {
852                 mAdapter.setForegroundUserId(userId, mContext.getAttributionSource());
853             }
854         } catch (RemoteException e) {
855             Log.e(TAG, "Unable to set foreground user id", e);
856         } finally {
857             mAdapterLock.readLock().unlock();
858         }
859     }
860 
getState()861     int getState() {
862         return mState.get();
863     }
864 
865     class ClientDeathRecipient implements IBinder.DeathRecipient {
866         private String mPackageName;
867 
ClientDeathRecipient(String packageName)868         ClientDeathRecipient(String packageName) {
869             mPackageName = packageName;
870         }
871 
binderDied()872         public void binderDied() {
873             Log.w(TAG, "Binder is dead - unregister " + mPackageName);
874 
875             for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
876                 IBinder token = entry.getKey();
877                 ClientDeathRecipient deathRec = entry.getValue();
878                 if (deathRec.equals(this)) {
879                     updateBleAppCount(token, false, mPackageName);
880                     break;
881                 }
882             }
883         }
884 
getPackageName()885         public String getPackageName() {
886             return mPackageName;
887         }
888     }
889 
isBleScanAvailable()890     boolean isBleScanAvailable() {
891         if (Flags.airplaneModeXBleOn()) {
892             if (AirplaneModeListener.isOn() && !mEnable) {
893                 return false;
894             }
895         } else {
896             if (AirplaneModeListener.isOnOverrode() && !mEnable) {
897                 return false;
898             }
899         }
900         if (Flags.respectBleScanSetting()) {
901             if (SatelliteModeListener.isOn()) {
902                 return false;
903             }
904             return BleScanSettingListener.isScanAllowed();
905         }
906         try {
907             return Settings.Global.getInt(
908                             mContentResolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)
909                     != 0;
910         } catch (SettingNotFoundException e) {
911             // The settings is considered as false by default.
912             return false;
913         }
914     }
915 
isHearingAidProfileSupported()916     boolean isHearingAidProfileSupported() {
917         return mIsHearingAidProfileSupported;
918     }
919 
getCurrentUserContext()920     Context getCurrentUserContext() {
921         return mCurrentUserContext;
922     }
923 
isMediaProfileConnected()924     boolean isMediaProfileConnected() {
925         if (mAdapter == null || !mState.oneOf(STATE_ON)) {
926             return false;
927         }
928         return mAdapter.isMediaProfileConnected(mContext.getAttributionSource());
929     }
930 
931     // Monitor change of BLE scan only mode settings.
registerForBleScanModeChange()932     private void registerForBleScanModeChange() {
933         ContentObserver contentObserver =
934                 new ContentObserver(new Handler(mLooper)) {
935                     @Override
936                     public void onChange(boolean selfChange) {
937                         if (isBleScanAvailable()) {
938                             // Nothing to do
939                             return;
940                         }
941                         // BLE scan is not available.
942                         disableBleScanMode();
943                         clearBleApps();
944                         mAdapterLock.readLock().lock();
945                         try {
946                             if (mAdapter != null) {
947                                 addActiveLog(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, false);
948                                 mAdapter.stopBle(mContext.getAttributionSource());
949                             }
950                         } catch (RemoteException e) {
951                             Log.e(TAG, "error when disabling bluetooth", e);
952                         } finally {
953                             mAdapterLock.readLock().unlock();
954                         }
955                     }
956                 };
957 
958         mContentResolver.registerContentObserver(
959                 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE),
960                 false,
961                 contentObserver);
962     }
963 
964     // Disable ble scan only mode.
disableBleScanMode()965     private void disableBleScanMode() {
966         mAdapterLock.writeLock().lock();
967         try {
968             if (mAdapter != null && mState.oneOf(STATE_ON)) {
969                 Log.d(TAG, "disableBleScanMode: Resetting the mEnable flag for clean disable");
970                 mEnable = false;
971             }
972         } finally {
973             mAdapterLock.writeLock().unlock();
974         }
975     }
976 
updateBleAppCount(IBinder token, boolean enable, String packageName)977     private int updateBleAppCount(IBinder token, boolean enable, String packageName) {
978         String header = "updateBleAppCount(" + token + ", " + enable + ", " + packageName + ")";
979         ClientDeathRecipient r = mBleApps.get(token);
980         if (r == null && enable) {
981             ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
982             try {
983                 token.linkToDeath(deathRec, 0);
984             } catch (RemoteException ex) {
985                 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
986             }
987             mBleApps.put(token, deathRec);
988             Log.d(TAG, header + " linkToDeath");
989         } else if (!enable && r != null) {
990             // Unregister death recipient as the app goes away.
991             token.unlinkToDeath(r, 0);
992             mBleApps.remove(token);
993             Log.d(TAG, header + " unlinkToDeath");
994         }
995         int appCount = mBleApps.size();
996         Log.d(TAG, header + " Number of BLE app registered: appCount=" + appCount);
997         return appCount;
998     }
999 
enableBle(String packageName, IBinder token)1000     boolean enableBle(String packageName, IBinder token) {
1001         Log.i(
1002                 TAG,
1003                 ("enableBle(" + packageName + ", " + token + "):")
1004                         + (" mAdapter=" + mAdapter)
1005                         + (" isBinding=" + isBinding())
1006                         + (" mState=" + mState));
1007 
1008         if (Flags.airplaneModeXBleOn()) {
1009             if (AirplaneModeListener.isOn() && !mEnable) {
1010                 Log.d(TAG, "enableBle: not enabling - Airplane mode is ON on system");
1011                 return false;
1012             }
1013         } else {
1014             if (AirplaneModeListener.isOnOverrode()) {
1015                 Log.d(TAG, "enableBle: not enabling - Airplane mode is ON");
1016                 return false;
1017             }
1018         }
1019 
1020         if (isSatelliteModeOn()) {
1021             Log.d(TAG, "enableBle: not enabling - Satellite mode is on.");
1022             return false;
1023         }
1024 
1025         if (Flags.respectBleScanSetting() && !BleScanSettingListener.isScanAllowed()) {
1026             Log.d(TAG, "enableBle: not enabling - Scan mode is not allowed.");
1027             return false;
1028         }
1029 
1030         // TODO(b/262605980): enableBle/disableBle should be on handler thread
1031         updateBleAppCount(token, true, packageName);
1032 
1033         if (mState.oneOf(
1034                 STATE_ON,
1035                 STATE_BLE_ON,
1036                 STATE_TURNING_ON,
1037                 STATE_TURNING_OFF,
1038                 STATE_BLE_TURNING_ON)) {
1039             Log.i(TAG, "enableBle: Bluetooth is already in state" + mState);
1040             return true;
1041         }
1042         synchronized (mReceiver) {
1043             // waive WRITE_SECURE_SETTINGS permission check
1044             sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName, true);
1045         }
1046         return true;
1047     }
1048 
disableBle(String packageName, IBinder token)1049     boolean disableBle(String packageName, IBinder token) {
1050         Log.i(
1051                 TAG,
1052                 ("disableBle(" + packageName + ", " + token + "):")
1053                         + (" mAdapter=" + mAdapter)
1054                         + (" isBinding=" + isBinding())
1055                         + (" mState=" + mState));
1056 
1057         // Remove this with flag, preventing a "disable" make no sense, even in satellite mode
1058         if (!Flags.respectBleScanSetting() && isSatelliteModeOn()) {
1059             Log.d(TAG, "disableBle: not disabling - satellite mode is on.");
1060             return false;
1061         }
1062 
1063         if (mState.oneOf(STATE_OFF)) {
1064             Log.i(TAG, "disableBle: Already disabled");
1065             return false;
1066         }
1067         // TODO(b/262605980): enableBle/disableBle should be on handler thread
1068         updateBleAppCount(token, false, packageName);
1069 
1070         if (mState.oneOf(STATE_BLE_ON) && !isBleAppPresent()) {
1071             if (mEnable) {
1072                 disableBleScanMode();
1073             }
1074             if (!mEnableExternal) {
1075                 addActiveLog(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName, false, true);
1076                 sendBrEdrDownCallback();
1077             }
1078         }
1079         return true;
1080     }
1081 
1082     // Clear all apps using BLE scan only mode.
clearBleApps()1083     private void clearBleApps() {
1084         mBleApps.clear();
1085     }
1086 
isBleAppPresent()1087     private boolean isBleAppPresent() {
1088         Log.d(TAG, "isBleAppPresent(): Number of BLE app registered: " + mBleApps.size());
1089         return mBleApps.size() > 0;
1090     }
1091 
1092     /**
1093      * Will call startBrEdr() if bluetooth classic should be on and will call stopBle if bluetooth
1094      * BLE should be off
1095      */
continueFromBleOnState()1096     private void continueFromBleOnState() {
1097         mAdapterLock.readLock().lock();
1098         try {
1099             if (mAdapter == null) {
1100                 Log.e(TAG, "continueFromBleOnState: Adapter is null");
1101                 return;
1102             }
1103             if (!mEnableExternal && !isBleAppPresent()) {
1104                 // TODO(b/262605980): this code is unlikely to be trigger and will never be once
1105                 // enableBle & disableBle are executed on the handler
1106                 Log.i(TAG, "continueFromBleOnState: Disabled while enabling BLE, disable BLE now");
1107                 mEnable = false;
1108                 mAdapter.stopBle(mContext.getAttributionSource());
1109                 return;
1110             }
1111             if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
1112                 Log.i(TAG, "continueFromBleOnState: Starting br edr");
1113                 // This triggers transition to STATE_ON
1114                 mAdapter.startBrEdr(mContext.getAttributionSource());
1115                 setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH);
1116             } else {
1117                 Log.i(TAG, "continueFromBleOnState: Staying in BLE_ON");
1118             }
1119         } catch (RemoteException e) {
1120             Log.e(TAG, "Unable to call onServiceUp", e);
1121         } finally {
1122             mAdapterLock.readLock().unlock();
1123         }
1124     }
1125 
1126     /**
1127      * Inform BluetoothAdapter instances that BREDR part is down and turn off all service and stack
1128      * if no LE app needs it
1129      */
sendBrEdrDownCallback()1130     private void sendBrEdrDownCallback() {
1131         mAdapterLock.readLock().lock();
1132         try {
1133             if (mAdapter == null) {
1134                 Log.w(TAG, "sendBrEdrDownCallback: mAdapter is null");
1135                 return;
1136             }
1137             boolean airplaneDoesNotAllowBleOn =
1138                     Flags.airplaneModeXBleOn() && AirplaneModeListener.isOn();
1139             boolean scanIsAllowed =
1140                     !Flags.respectBleScanSetting() || BleScanSettingListener.isScanAllowed();
1141             if (!airplaneDoesNotAllowBleOn && isBleAppPresent() && scanIsAllowed) {
1142                 // Need to stay at BLE ON. Disconnect all Gatt connections
1143                 Log.i(TAG, "sendBrEdrDownCallback: Staying in BLE_ON");
1144                 mAdapter.unregAllGattClient(mContext.getAttributionSource());
1145             } else {
1146                 Log.i(TAG, "sendBrEdrDownCallback: Stopping ble");
1147                 mAdapter.stopBle(mContext.getAttributionSource());
1148             }
1149         } catch (RemoteException e) {
1150             Log.e(TAG, "sendBrEdrDownCallback: Call to mAdapter failed.", e);
1151         } finally {
1152             mAdapterLock.readLock().unlock();
1153         }
1154     }
1155 
enableFromAutoOn()1156     private Unit enableFromAutoOn() {
1157         if (isBluetoothDisallowed()) {
1158             Log.d(TAG, "Bluetooth is not allowed, preventing AutoOn");
1159             return Unit.INSTANCE;
1160         }
1161         Counter.logIncrement("bluetooth.value_auto_on_triggered");
1162         sendToggleNotification("auto_on_bt_enabled_notification");
1163         enable("BluetoothSystemServer/AutoOn");
1164         return Unit.INSTANCE;
1165     }
1166 
enableNoAutoConnect(String packageName)1167     boolean enableNoAutoConnect(String packageName) {
1168         if (isSatelliteModeOn()) {
1169             Log.d(TAG, "enableNoAutoConnect(" + packageName + "): Blocked by satellite mode");
1170             return false;
1171         }
1172 
1173         synchronized (mReceiver) {
1174             mQuietEnableExternal = true;
1175             mEnableExternal = true;
1176             sendEnableMsg(true, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
1177         }
1178         return true;
1179     }
1180 
enable(String packageName)1181     boolean enable(String packageName) {
1182         Log.d(
1183                 TAG,
1184                 ("enable(" + packageName + "):")
1185                         + (" mAdapter=" + mAdapter)
1186                         + (" isBinding=" + isBinding())
1187                         + (" mState=" + mState));
1188 
1189         if (isSatelliteModeOn()) {
1190             Log.d(TAG, "enable: not enabling - satellite mode is on.");
1191             return false;
1192         }
1193 
1194         synchronized (mReceiver) {
1195             mQuietEnableExternal = false;
1196             mEnableExternal = true;
1197             // TODO(b/288450479): Remove clearCallingIdentity when threading is fixed
1198             final long callingIdentity = Binder.clearCallingIdentity();
1199             try {
1200                 AirplaneModeListener.notifyUserToggledBluetooth(
1201                         mContentResolver, mCurrentUserContext, true);
1202             } finally {
1203                 Binder.restoreCallingIdentity(callingIdentity);
1204             }
1205             sendEnableMsg(false, ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
1206         }
1207         return true;
1208     }
1209 
disable(String packageName, boolean persist)1210     boolean disable(String packageName, boolean persist) {
1211         Log.d(
1212                 TAG,
1213                 ("disable(" + packageName + ", " + persist + "):")
1214                         + (" mAdapter=" + mAdapter)
1215                         + (" isBinding=" + isBinding())
1216                         + (" mState=" + mState));
1217 
1218         synchronized (mReceiver) {
1219             // TODO(b/288450479): Remove clearCallingIdentity when threading is fixed
1220             final long callingIdentity = Binder.clearCallingIdentity();
1221             try {
1222                 AirplaneModeListener.notifyUserToggledBluetooth(
1223                         mContentResolver, mCurrentUserContext, false);
1224             } finally {
1225                 Binder.restoreCallingIdentity(callingIdentity);
1226             }
1227 
1228             if (persist) {
1229                 setBluetoothPersistedState(BLUETOOTH_OFF);
1230             }
1231             mEnableExternal = false;
1232             sendDisableMsg(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
1233         }
1234         return true;
1235     }
1236 
unbindAndFinish()1237     void unbindAndFinish() {
1238         Log.d(TAG, "unbindAndFinish(): mAdapter=" + mAdapter + " isBinding=" + isBinding());
1239 
1240         mAdapterLock.writeLock().lock();
1241         try {
1242             mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1243             if (mAdapter == null) {
1244                 return;
1245             }
1246 
1247             try {
1248                 mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource());
1249             } catch (RemoteException e) {
1250                 Log.e(TAG, "Unable to unregister BluetoothCallback", e);
1251             }
1252 
1253             if (!Flags.explicitKillFromSystemServer()) {
1254                 mAdapter = null;
1255                 mContext.unbindService(mConnection);
1256                 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1257                 return;
1258             }
1259 
1260             CompletableFuture<Void> binderDead = new CompletableFuture<>();
1261             try {
1262                 mAdapter.getAdapterBinder()
1263                         .asBinder()
1264                         .linkToDeath(
1265                                 () -> {
1266                                     Log.i(TAG, "Successfully received Bluetooth death");
1267                                     binderDead.complete(null);
1268                                 },
1269                                 0);
1270             } catch (RemoteException e) {
1271                 Log.e(TAG, "Failed to linkToDeath", e);
1272                 binderDead.complete(null);
1273             }
1274 
1275             // Unbind first to avoid receiving unwanted "onServiceDisconnected"
1276             mContext.unbindService(mConnection);
1277 
1278             try {
1279                 // Force kill Bluetooth to make sure its process is not reused.
1280                 // Note: In a perfect world, we should be able to re-init the same process.
1281                 // Unfortunately, this requires an heavy rework of the Bluetooth app
1282                 // TODO: b/339501753 - Properly stop Bluetooth without killing it
1283                 mAdapter.killBluetoothProcess();
1284 
1285                 binderDead.get(1, TimeUnit.SECONDS);
1286             } catch (android.os.DeadObjectException e) {
1287                 // Reduce exception to info and skip waiting (Bluetooth is dead as wanted)
1288                 Log.i(TAG, "Bluetooth already dead ��");
1289             } catch (RemoteException e) {
1290                 Log.e(TAG, "Unexpected RemoteException when calling killBluetoothProcess", e);
1291             } catch (TimeoutException | InterruptedException | ExecutionException e) {
1292                 Log.e(TAG, "Bluetooth death not received correctly", e);
1293             }
1294 
1295             mAdapter = null;
1296             mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1297         } finally {
1298             mAdapterLock.writeLock().unlock();
1299         }
1300     }
1301 
1302     /**
1303      * Send enable message and set adapter name and address. Called when the boot phase becomes
1304      * PHASE_SYSTEM_SERVICES_READY.
1305      */
handleOnBootPhase(UserHandle userHandle)1306     void handleOnBootPhase(UserHandle userHandle) {
1307         mHandler.post(() -> internalHandleOnBootPhase(userHandle));
1308     }
1309 
1310     @VisibleForTesting
initialize(UserHandle userHandle)1311     void initialize(UserHandle userHandle) {
1312         mCurrentUserContext =
1313                 requireNonNull(
1314                         mContext.createContextAsUser(userHandle, 0),
1315                         "Current User Context cannot be null");
1316         AirplaneModeListener.initialize(
1317                 mLooper,
1318                 mContentResolver,
1319                 mState,
1320                 this::onAirplaneModeChanged,
1321                 this::sendToggleNotification,
1322                 this::isMediaProfileConnected,
1323                 this::getCurrentUserContext,
1324                 TimeSource.Monotonic.INSTANCE);
1325 
1326         SatelliteModeListener.initialize(mLooper, mContentResolver, this::onSatelliteModeChanged);
1327     }
1328 
internalHandleOnBootPhase(UserHandle userHandle)1329     private void internalHandleOnBootPhase(UserHandle userHandle) {
1330         Log.d(TAG, "internalHandleOnBootPhase(" + userHandle + "): Bluetooth boot completed");
1331 
1332         initialize(userHandle);
1333 
1334         final boolean isBluetoothDisallowed = isBluetoothDisallowed();
1335         if (isBluetoothDisallowed) {
1336             return;
1337         }
1338         final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
1339         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
1340             Log.i(TAG, "internalHandleOnBootPhase: Auto-enabling Bluetooth.");
1341             sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_SYSTEM_BOOT);
1342         } else if (!isNameAndAddressSet()) {
1343             Log.i(TAG, "internalHandleOnBootPhase: Getting adapter name and address");
1344             mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1345         } else {
1346             autoOnSetupTimer();
1347         }
1348     }
1349 
1350     /** Called when switching to a different foreground user. */
handleSwitchUser(UserHandle userHandle)1351     private void handleSwitchUser(UserHandle userHandle) {
1352         Log.d(TAG, "handleSwitchUser(" + userHandle + ")");
1353         mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle).sendToTarget();
1354     }
1355 
1356     /** Called when user is unlocked. */
handleOnUnlockUser(UserHandle userHandle)1357     void handleOnUnlockUser(UserHandle userHandle) {
1358         Log.d(TAG, "handleOnUnlockUser(" + userHandle + ")");
1359         mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle).sendToTarget();
1360     }
1361 
sendBluetoothOnCallback()1362     private void sendBluetoothOnCallback() {
1363         synchronized (mCallbacks) {
1364             try {
1365                 int n = mCallbacks.beginBroadcast();
1366                 Log.d(TAG, "Broadcasting onBluetoothOn() to " + n + " receivers.");
1367                 for (int i = 0; i < n; i++) {
1368                     try {
1369                         mCallbacks.getBroadcastItem(i).onBluetoothOn();
1370                     } catch (RemoteException e) {
1371                         Log.e(TAG, "Unable to call onBluetoothOn() on callback #" + i, e);
1372                     }
1373                 }
1374             } finally {
1375                 mCallbacks.finishBroadcast();
1376             }
1377         }
1378     }
1379 
sendBluetoothOffCallback()1380     private void sendBluetoothOffCallback() {
1381         synchronized (mCallbacks) {
1382             try {
1383                 int n = mCallbacks.beginBroadcast();
1384                 Log.d(TAG, "Broadcasting onBluetoothOff() to " + n + " receivers.");
1385                 for (int i = 0; i < n; i++) {
1386                     try {
1387                         mCallbacks.getBroadcastItem(i).onBluetoothOff();
1388                     } catch (RemoteException e) {
1389                         Log.e(TAG, "Unable to call onBluetoothOff() on callback #" + i, e);
1390                     }
1391                 }
1392             } finally {
1393                 mCallbacks.finishBroadcast();
1394             }
1395         }
1396     }
1397 
1398     /** Inform BluetoothAdapter instances that Adapter service is up */
sendBluetoothServiceUpCallback()1399     private void sendBluetoothServiceUpCallback() {
1400         synchronized (mCallbacks) {
1401             mAdapterLock.readLock().lock();
1402             try {
1403                 int n = mCallbacks.beginBroadcast();
1404                 Log.d(TAG, "sendBluetoothServiceUpCallback(): to " + n + " receivers");
1405                 for (int i = 0; i < n; i++) {
1406                     try {
1407                         mCallbacks
1408                                 .getBroadcastItem(i)
1409                                 .onBluetoothServiceUp(mAdapter.getAdapterBinder().asBinder());
1410                     } catch (RemoteException e) {
1411                         Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
1412                     }
1413                 }
1414             } finally {
1415                 mCallbacks.finishBroadcast();
1416                 mAdapterLock.readLock().unlock();
1417             }
1418         }
1419     }
1420 
1421     /** Inform BluetoothAdapter instances that Adapter service is down */
sendBluetoothServiceDownCallback()1422     private void sendBluetoothServiceDownCallback() {
1423         synchronized (mCallbacks) {
1424             try {
1425                 int n = mCallbacks.beginBroadcast();
1426                 Log.d(TAG, "sendBluetoothServiceDownCallback(): to " + n + " receivers");
1427                 for (int i = 0; i < n; i++) {
1428                     try {
1429                         mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
1430                     } catch (RemoteException e) {
1431                         Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
1432                     }
1433                 }
1434             } finally {
1435                 mCallbacks.finishBroadcast();
1436             }
1437         }
1438     }
1439 
getAddress()1440     String getAddress() {
1441         mAdapterLock.readLock().lock();
1442         try {
1443             if (mAdapter != null) {
1444                 return mAdapter.getAddress(mContext.getAttributionSource());
1445             }
1446         } catch (RemoteException e) {
1447             Log.e(
1448                     TAG,
1449                     "getAddress(): Unable to retrieve address remotely. Returning cached address",
1450                     e);
1451         } finally {
1452             mAdapterLock.readLock().unlock();
1453         }
1454 
1455         // mAddress is accessed from outside.
1456         // It is alright without a lock. Here, bluetooth is off, no other thread is
1457         // changing mAddress
1458         return mAddress;
1459     }
1460 
getName()1461     String getName() {
1462         mAdapterLock.readLock().lock();
1463         try {
1464             if (mAdapter != null) {
1465                 return mAdapter.getName(mContext.getAttributionSource());
1466             }
1467         } catch (RemoteException e) {
1468             Log.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1469         } finally {
1470             mAdapterLock.readLock().unlock();
1471         }
1472 
1473         // mName is accessed from outside.
1474         // It alright without a lock. Here, bluetooth is off, no other thread is
1475         // changing mName
1476         return mName;
1477     }
1478 
1479     @VisibleForTesting
1480     class BluetoothServiceConnection implements ServiceConnection {
onServiceConnected(ComponentName componentName, IBinder service)1481         public void onServiceConnected(ComponentName componentName, IBinder service) {
1482             String name = componentName.getClassName();
1483             Log.d(TAG, "ServiceConnection.onServiceConnected(" + name + ", " + service + ")");
1484             if (!name.equals("com.android.bluetooth.btservice.AdapterService")) {
1485                 Log.e(TAG, "Unknown service connected: " + name);
1486                 return;
1487             }
1488             mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED, service).sendToTarget();
1489         }
1490 
onServiceDisconnected(ComponentName componentName)1491         public void onServiceDisconnected(ComponentName componentName) {
1492             // Called if we unexpectedly disconnect.
1493             String name = componentName.getClassName();
1494             Log.d(TAG, "ServiceConnection.onServiceDisconnected(" + name + ")");
1495             if (!name.equals("com.android.bluetooth.btservice.AdapterService")) {
1496                 Log.e(TAG, "Unknown service disconnected: " + name);
1497                 return;
1498             }
1499             mHandler.sendEmptyMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
1500         }
1501     }
1502 
1503     private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1504     private int mWaitForEnableRetry;
1505     private int mWaitForDisableRetry;
1506 
1507     @VisibleForTesting
1508     class BluetoothHandler extends Handler {
1509         boolean mGetNameAddressOnly = false;
1510 
BluetoothHandler(Looper looper)1511         BluetoothHandler(Looper looper) {
1512             super(looper);
1513         }
1514 
1515         @Override
handleMessage(Message msg)1516         public void handleMessage(Message msg) {
1517             switch (msg.what) {
1518                 case MESSAGE_GET_NAME_AND_ADDRESS:
1519                     Log.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1520                     mAdapterLock.writeLock().lock();
1521                     try {
1522                         if (mAdapter == null && !isBinding()) {
1523                             Log.d(TAG, "Binding to service to get name and address");
1524                             mGetNameAddressOnly = true;
1525                             mHandler.sendEmptyMessageDelayed(MESSAGE_TIMEOUT_BIND, TIMEOUT_BIND_MS);
1526                             Intent i = new Intent(IBluetooth.class.getName());
1527                             if (!doBind(
1528                                     i,
1529                                     mConnection,
1530                                     Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1531                                     UserHandle.CURRENT)) {
1532                                 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1533                             }
1534                         } else if (mAdapter != null) {
1535                             try {
1536                                 storeNameAndAddress(
1537                                         mAdapter.getName(mContext.getAttributionSource()),
1538                                         mAdapter.getAddress(mContext.getAttributionSource()));
1539                             } catch (RemoteException e) {
1540                                 Log.e(TAG, "Unable to grab names", e);
1541                             }
1542                             if (mGetNameAddressOnly && !mEnable) {
1543                                 unbindAndFinish();
1544                             }
1545                             mGetNameAddressOnly = false;
1546                         }
1547                     } finally {
1548                         mAdapterLock.writeLock().unlock();
1549                     }
1550                     break;
1551 
1552                 case MESSAGE_ENABLE:
1553                     int quietEnable = msg.arg1;
1554                     int isBle = msg.arg2;
1555 
1556                     Log.d(
1557                             TAG,
1558                             ("MESSAGE_ENABLE(quietEnable=" + quietEnable + ", isBle=" + isBle + ")")
1559                                     + (": mAdapter=" + mAdapter));
1560 
1561                     handleEnableMessage(quietEnable, isBle);
1562 
1563                     break;
1564 
1565                 case MESSAGE_DISABLE:
1566                     Log.d(TAG, "MESSAGE_DISABLE: mAdapter=" + mAdapter);
1567 
1568                     handleDisableMessage();
1569                     break;
1570 
1571                 case MESSAGE_HANDLE_ENABLE_DELAYED:
1572                     // The Bluetooth is turning off, wait for STATE_OFF
1573                     if (!mState.oneOf(STATE_OFF)) {
1574                         if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
1575                             mWaitForEnableRetry++;
1576                             mHandler.sendEmptyMessageDelayed(
1577                                     MESSAGE_HANDLE_ENABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
1578                             break;
1579                         } else {
1580                             Log.e(TAG, "Wait for STATE_OFF timeout");
1581                         }
1582                     }
1583                     // Either state is changed to STATE_OFF or reaches the maximum retry, we
1584                     // should move forward to the next step.
1585                     mWaitForEnableRetry = 0;
1586                     mHandler.sendEmptyMessageDelayed(
1587                             MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
1588                     Log.d(TAG, "Handle enable is finished");
1589                     break;
1590 
1591                 case MESSAGE_HANDLE_DISABLE_DELAYED:
1592                     boolean disabling = (msg.arg1 == 1);
1593                     Log.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling);
1594                     if (!disabling) {
1595                         // The Bluetooth is turning on, wait for STATE_ON
1596                         if (!mState.oneOf(STATE_ON)) {
1597                             if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
1598                                 mWaitForDisableRetry++;
1599                                 mHandler.sendEmptyMessageDelayed(
1600                                         MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
1601                                 break;
1602                             } else {
1603                                 Log.e(TAG, "Wait for STATE_ON timeout");
1604                             }
1605                         }
1606                         // Either state is changed to STATE_ON or reaches the maximum retry, we
1607                         // should move forward to the next step.
1608                         mWaitForDisableRetry = 0;
1609                         mEnable = false;
1610                         handleDisable();
1611                         // Wait for state exiting STATE_ON
1612                         Message disableDelayedMsg =
1613                                 mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
1614                         mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
1615                     } else {
1616                         // The Bluetooth is turning off, wait for exiting STATE_ON
1617                         if (mState.oneOf(STATE_ON)) {
1618                             if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
1619                                 mWaitForDisableRetry++;
1620                                 Message disableDelayedMsg =
1621                                         mHandler.obtainMessage(
1622                                                 MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
1623                                 mHandler.sendMessageDelayed(
1624                                         disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
1625                                 break;
1626                             } else {
1627                                 Log.e(TAG, "Wait for exiting STATE_ON timeout");
1628                             }
1629                         }
1630                         // Either state is exited from STATE_ON or reaches the maximum retry, we
1631                         // should move forward to the next step.
1632                         Log.d(TAG, "Handle disable is finished");
1633                     }
1634                     break;
1635 
1636                 case MESSAGE_RESTORE_USER_SETTING:
1637                     if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1638                         Log.d(TAG, "MESSAGE_RESTORE_USER_SETTING: set Bluetooth state to disabled");
1639                         setBluetoothPersistedState(BLUETOOTH_OFF);
1640                         mEnableExternal = false;
1641                         sendDisableMsg(ENABLE_DISABLE_REASON_RESTORE_USER_SETTING);
1642                     } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1643                         Log.d(TAG, "MESSAGE_RESTORE_USER_SETTING: set Bluetooth state to enabled");
1644                         mQuietEnableExternal = false;
1645                         mEnableExternal = true;
1646                         sendEnableMsg(false, ENABLE_DISABLE_REASON_RESTORE_USER_SETTING);
1647                     } else {
1648                         Log.w(
1649                                 TAG,
1650                                 "MESSAGE_RESTORE_USER_SETTING: Unhandled."
1651                                         + (" mEnable=" + mEnable)
1652                                         + (" msg.arg1=" + msg.arg1));
1653                     }
1654                     break;
1655 
1656                 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
1657                     IBinder service = (IBinder) msg.obj;
1658                     Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: service=" + service);
1659 
1660                     mAdapterLock.writeLock().lock();
1661                     try {
1662                         // Remove timeout
1663                         mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1664 
1665                         mAdapter = BluetoothServerProxy.getInstance().createAdapterBinder(service);
1666 
1667                         int foregroundUserId = ActivityManager.getCurrentUser();
1668                         propagateForegroundUserId(foregroundUserId);
1669 
1670                         if (!isNameAndAddressSet()) {
1671                             mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1672                             if (mGetNameAddressOnly) {
1673                                 return;
1674                             }
1675                         }
1676 
1677                         // Register callback object
1678                         try {
1679                             mAdapter.registerCallback(
1680                                     mBluetoothCallback, mContext.getAttributionSource());
1681                         } catch (RemoteException e) {
1682                             Log.e(TAG, "Unable to register BluetoothCallback", e);
1683                         }
1684                         // Inform BluetoothAdapter instances that service is up
1685                         if (!Flags.fastBindToApp()) {
1686                             sendBluetoothServiceUpCallback();
1687                         }
1688 
1689                         // Do enable request
1690                         try {
1691                             mAdapter.enable(mQuietEnable, mContext.getAttributionSource());
1692                         } catch (RemoteException e) {
1693                             Log.e(TAG, "Unable to call enable()", e);
1694                         }
1695                         if (Flags.fastBindToApp()) {
1696                             sendBluetoothServiceUpCallback();
1697                         }
1698                     } finally {
1699                         mAdapterLock.writeLock().unlock();
1700                     }
1701 
1702                     if (!mEnable) {
1703                         waitForState(STATE_ON);
1704                         handleDisable();
1705                         waitForState(
1706                                 STATE_OFF,
1707                                 STATE_TURNING_ON,
1708                                 STATE_TURNING_OFF,
1709                                 STATE_BLE_TURNING_ON,
1710                                 STATE_BLE_ON,
1711                                 STATE_BLE_TURNING_OFF);
1712                     }
1713                     break;
1714 
1715                 case MESSAGE_BLUETOOTH_STATE_CHANGE:
1716                     int prevState = msg.arg1;
1717                     int newState = msg.arg2;
1718                     Log.d(
1719                             TAG,
1720                             "MESSAGE_BLUETOOTH_STATE_CHANGE:"
1721                                     + (" prevState=" + BluetoothAdapter.nameForState(prevState))
1722                                     + (" newState=" + BluetoothAdapter.nameForState(newState)));
1723                     mState.set(newState);
1724                     bluetoothStateChangeHandler(prevState, newState);
1725                     // handle error state transition case from TURNING_ON to OFF
1726                     // unbind and rebind bluetooth service and enable bluetooth
1727                     if ((prevState == STATE_BLE_TURNING_ON)
1728                             && (newState == STATE_OFF)
1729                             && (mAdapter != null)
1730                             && mEnable) {
1731                         recoverBluetoothServiceFromError(false);
1732                     }
1733                     if ((prevState == STATE_TURNING_ON)
1734                             && (newState == STATE_BLE_ON)
1735                             && (mAdapter != null)
1736                             && mEnable) {
1737                         recoverBluetoothServiceFromError(true);
1738                     }
1739                     // If we tried to enable BT while BT was in the process of shutting down,
1740                     // wait for the BT process to fully tear down and then force a restart
1741                     // here.  This is a bit of a hack (b/29363429).
1742                     if (prevState == STATE_BLE_TURNING_OFF && newState == STATE_OFF) {
1743                         if (mEnable) {
1744                             Log.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1745                             waitForState(STATE_OFF);
1746                             mHandler.sendEmptyMessageDelayed(
1747                                     MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
1748                         }
1749                     }
1750                     if (newState == STATE_ON || newState == STATE_BLE_ON) {
1751                         // bluetooth is working, reset the counter
1752                         if (mErrorRecoveryRetryCounter != 0) {
1753                             Log.w(TAG, "bluetooth is recovered from error");
1754                             mErrorRecoveryRetryCounter = 0;
1755                         }
1756                     }
1757                     break;
1758 
1759                 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
1760                     Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
1761                     mAdapterLock.writeLock().lock();
1762                     try {
1763                         // if service is unbinded already, do nothing and return
1764                         if (mAdapter == null) {
1765                             break;
1766                         }
1767                         mContext.unbindService(mConnection);
1768                         mAdapter = null;
1769                     } finally {
1770                         mAdapterLock.writeLock().unlock();
1771                     }
1772 
1773                     // log the unexpected crash
1774                     addCrashLog();
1775                     addActiveLog(ENABLE_DISABLE_REASON_CRASH, false);
1776                     if (mEnable) {
1777                         mEnable = false;
1778                         mHandler.sendEmptyMessageDelayed(
1779                                 MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
1780                     }
1781 
1782                     sendBluetoothServiceDownCallback();
1783 
1784                     // Send BT state broadcast to update
1785                     // the BT icon correctly
1786                     if (mState.oneOf(STATE_TURNING_ON, STATE_ON)) {
1787                         bluetoothStateChangeHandler(STATE_ON, STATE_TURNING_OFF);
1788                         mState.set(STATE_TURNING_OFF);
1789                     }
1790                     if (mState.oneOf(STATE_TURNING_OFF)) {
1791                         bluetoothStateChangeHandler(STATE_TURNING_OFF, STATE_OFF);
1792                     }
1793 
1794                     mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1795                     mState.set(STATE_OFF);
1796                     break;
1797 
1798                 case MESSAGE_RESTART_BLUETOOTH_SERVICE:
1799                     mErrorRecoveryRetryCounter++;
1800                     Log.d(
1801                             TAG,
1802                             "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
1803                                     + mErrorRecoveryRetryCounter);
1804                     if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
1805                         /* Enable without persisting the setting as
1806                          * it doesn't change when IBluetooth
1807                          * service restarts */
1808                         mEnable = true;
1809                         addActiveLog(ENABLE_DISABLE_REASON_RESTARTED, true);
1810                         handleEnable(mQuietEnable);
1811                     } else {
1812                         mAdapterLock.writeLock().lock();
1813                         mAdapter = null;
1814                         mAdapterLock.writeLock().unlock();
1815                         Log.e(TAG, "Reach maximum retry to restart Bluetooth!");
1816                     }
1817                     break;
1818 
1819                 case MESSAGE_TIMEOUT_BIND:
1820                     Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
1821                     // TODO(b/286082382): Timeout should be more than a log. We should at least call
1822                     // context.unbindService, eventually log a metric with it
1823                     break;
1824 
1825                 case MESSAGE_USER_SWITCHED:
1826                     UserHandle userTo = (UserHandle) msg.obj;
1827                     Log.d(TAG, "MESSAGE_USER_SWITCHED: userTo=" + userTo);
1828                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1829 
1830                     AutoOnFeature.pause();
1831 
1832                     mCurrentUserContext = mContext.createContextAsUser(userTo, 0);
1833 
1834                     /* disable and enable BT when detect a user switch */
1835                     if (mAdapter != null && mState.oneOf(STATE_ON)) {
1836                         restartForNewUser(userTo);
1837                     } else if (isBinding() || mAdapter != null) {
1838                         Message userMsg = Message.obtain(msg);
1839                         userMsg.arg1++;
1840                         // if user is switched when service is binding retry after a delay
1841                         mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
1842                         Log.d(
1843                                 TAG,
1844                                 "MESSAGE_USER_SWITCHED:"
1845                                         + (" userTo=" + userTo)
1846                                         + (" number of retry attempt=" + userMsg.arg1)
1847                                         + (" isBinding=" + isBinding())
1848                                         + (" mAdapter=" + mAdapter));
1849                     } else {
1850                         autoOnSetupTimer();
1851                     }
1852                     break;
1853 
1854                 case MESSAGE_USER_UNLOCKED:
1855                     Log.d(TAG, "MESSAGE_USER_UNLOCKED");
1856                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1857 
1858                     if (mEnable && !isBinding() && (mAdapter == null)) {
1859                         // We should be connected, but we gave up for some
1860                         // reason; maybe the Bluetooth service wasn't encryption
1861                         // aware, so try binding again.
1862                         Log.d(TAG, "Enabled but not bound; retrying after unlock");
1863                         handleEnable(mQuietEnable);
1864                     }
1865                     break;
1866             }
1867         }
1868 
restartForNewUser(UserHandle unusedNewUser)1869         private void restartForNewUser(UserHandle unusedNewUser) {
1870             mAdapterLock.readLock().lock();
1871             try {
1872                 if (mAdapter != null) {
1873                     mAdapter.unregisterCallback(
1874                             mBluetoothCallback, mContext.getAttributionSource());
1875                 }
1876             } catch (RemoteException e) {
1877                 Log.e(TAG, "Unable to unregister", e);
1878             } finally {
1879                 mAdapterLock.readLock().unlock();
1880             }
1881 
1882             // This method is always called while bluetooth is in STATE_ON
1883             assert (mState.oneOf(STATE_ON));
1884 
1885             // disable
1886             addActiveLog(ENABLE_DISABLE_REASON_USER_SWITCH, false);
1887             handleDisable();
1888             // Pbap service need receive STATE_TURNING_OFF intent to close
1889             bluetoothStateChangeHandler(STATE_ON, STATE_TURNING_OFF);
1890 
1891             boolean didDisableTimeout = !waitForState(STATE_OFF);
1892 
1893             bluetoothStateChangeHandler(STATE_TURNING_OFF, STATE_OFF);
1894 
1895             //
1896             // If disabling Bluetooth times out, wait for an
1897             // additional amount of time to ensure the process is
1898             // shut down completely before attempting to restart.
1899             //
1900             if (didDisableTimeout) {
1901                 SystemClock.sleep(3000);
1902             } else {
1903                 SystemClock.sleep(100);
1904             }
1905 
1906             mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1907             mState.set(STATE_OFF);
1908             // enable
1909             addActiveLog(ENABLE_DISABLE_REASON_USER_SWITCH, true);
1910             // mEnable flag could have been reset on stopBle. Reenable it.
1911             mEnable = true;
1912             handleEnable(mQuietEnable);
1913         }
1914     }
1915 
isBinding()1916     private boolean isBinding() {
1917         return mHandler.hasMessages(MESSAGE_TIMEOUT_BIND);
1918     }
1919 
handleEnableMessage(int quietEnable, int isBle)1920     private void handleEnableMessage(int quietEnable, int isBle) {
1921         if (mShutdownInProgress) {
1922             Log.d(TAG, "Skip Bluetooth Enable in device shutdown process");
1923             return;
1924         }
1925 
1926         if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
1927                 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
1928             // We are handling enable or disable right now, wait for it.
1929             mHandler.sendMessageDelayed(
1930                     mHandler.obtainMessage(MESSAGE_ENABLE, quietEnable, isBle),
1931                     ENABLE_DISABLE_DELAY_MS);
1932             return;
1933         }
1934 
1935         mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1936         mEnable = true;
1937 
1938         if (isBle == 0) {
1939             setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH);
1940         }
1941 
1942         // Use service interface to get the exact state
1943         mAdapterLock.readLock().lock();
1944         try {
1945             if (mAdapter != null) {
1946                 boolean isHandled = true;
1947                 switch (mState.get()) {
1948                     case STATE_BLE_ON:
1949                         if (isBle == 1) {
1950                             Log.i(TAG, "Already at BLE_ON State");
1951                         } else {
1952                             Log.w(TAG, "BT Enable in BLE_ON State, going to ON");
1953                             mAdapter.startBrEdr(mContext.getAttributionSource());
1954                         }
1955                         break;
1956                     case STATE_BLE_TURNING_ON:
1957                     case STATE_TURNING_ON:
1958                     case STATE_ON:
1959                         Log.i(TAG, "MESSAGE_ENABLE: already enabled");
1960                         break;
1961                     default:
1962                         isHandled = false;
1963                         break;
1964                 }
1965                 if (isHandled) return;
1966             }
1967         } catch (RemoteException e) {
1968             Log.e(TAG, "", e);
1969         } finally {
1970             mAdapterLock.readLock().unlock();
1971         }
1972 
1973         mQuietEnable = (quietEnable == 1);
1974         if (mAdapter == null) {
1975             handleEnable(mQuietEnable);
1976         } else {
1977             //
1978             // We need to wait until transitioned to STATE_OFF and
1979             // the previous Bluetooth process has exited. The
1980             // waiting period has three components:
1981             // (a) Wait until the local state is STATE_OFF. This
1982             //     is accomplished by sending delay a message
1983             //     MESSAGE_HANDLE_ENABLE_DELAYED
1984             // (b) Wait until the STATE_OFF state is updated to
1985             //     all components.
1986             // (c) Wait until the Bluetooth process exits, and
1987             //     ActivityManager detects it.
1988             // The waiting for (b) and (c) is accomplished by
1989             // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
1990             // message. The delay time is backed off if Bluetooth
1991             // continuously failed to turn on itself.
1992             //
1993             mWaitForEnableRetry = 0;
1994             mHandler.sendEmptyMessageDelayed(
1995                     MESSAGE_HANDLE_ENABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
1996         }
1997     }
1998 
handleDisableMessage()1999     private void handleDisableMessage() {
2000         if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
2001                 || isBinding()
2002                 || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
2003             // We are handling enable or disable right now, wait for it.
2004             mHandler.sendEmptyMessageDelayed(MESSAGE_DISABLE, ENABLE_DISABLE_DELAY_MS);
2005             return;
2006         }
2007 
2008         mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
2009 
2010         if (mEnable && mAdapter != null) {
2011             mWaitForDisableRetry = 0;
2012             mHandler.sendEmptyMessageDelayed(
2013                     MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
2014         } else {
2015             mEnable = false;
2016             handleDisable();
2017         }
2018     }
2019 
handleEnable(boolean quietMode)2020     private void handleEnable(boolean quietMode) {
2021         mQuietEnable = quietMode;
2022 
2023         mAdapterLock.writeLock().lock();
2024         try {
2025             if (mAdapter == null && !isBinding()) {
2026                 Log.d(TAG, "binding Bluetooth service");
2027                 // Start bind timeout and bind
2028                 mHandler.sendEmptyMessageDelayed(MESSAGE_TIMEOUT_BIND, TIMEOUT_BIND_MS);
2029                 Intent i = new Intent(IBluetooth.class.getName());
2030                 if (!doBind(
2031                         i,
2032                         mConnection,
2033                         Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
2034                         UserHandle.CURRENT)) {
2035                     mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
2036                 }
2037             } else if (!Flags.fastBindToApp() && mAdapter != null) {
2038                 // Enable bluetooth
2039                 try {
2040                     mAdapter.enable(mQuietEnable, mContext.getAttributionSource());
2041                 } catch (RemoteException e) {
2042                     Log.e(TAG, "Unable to call enable()", e);
2043                 }
2044             }
2045         } finally {
2046             mAdapterLock.writeLock().unlock();
2047         }
2048     }
2049 
doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user)2050     boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
2051         ComponentName comp = resolveSystemService(intent);
2052         intent.setComponent(comp);
2053         if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
2054             Log.e(TAG, "Fail to bind to: " + intent);
2055             return false;
2056         }
2057         return true;
2058     }
2059 
handleDisable()2060     private void handleDisable() {
2061         mAdapterLock.readLock().lock();
2062         try {
2063             if (mAdapter != null) {
2064                 Log.d(TAG, "handleDisable: Sending off request.");
2065                 mAdapter.disable(mContext.getAttributionSource());
2066             }
2067         } catch (RemoteException e) {
2068             Log.e(TAG, "Unable to call disable()", e);
2069         } finally {
2070             mAdapterLock.readLock().unlock();
2071         }
2072     }
2073 
broadcastIntentStateChange(String action, int prevState, int newState)2074     private void broadcastIntentStateChange(String action, int prevState, int newState) {
2075         Log.d(
2076                 TAG,
2077                 "broadcastIntentStateChange:"
2078                         + (" action=" + action.substring(action.lastIndexOf('.') + 1))
2079                         + (" prevState=" + BluetoothAdapter.nameForState(prevState))
2080                         + (" newState=" + BluetoothAdapter.nameForState(newState)));
2081         // Send broadcast message to everyone else
2082         Intent intent = new Intent(action);
2083         intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2084         intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2085         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2086         mContext.sendBroadcastAsUser(
2087                 intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions());
2088     }
2089 
isBleState(int state)2090     private boolean isBleState(int state) {
2091         switch (state) {
2092             case STATE_BLE_ON:
2093             case STATE_BLE_TURNING_ON:
2094             case STATE_BLE_TURNING_OFF:
2095                 return true;
2096         }
2097         return false;
2098     }
2099 
bluetoothStateChangeHandler(int prevState, int newState)2100     private void bluetoothStateChangeHandler(int prevState, int newState) {
2101         if (prevState == newState) { // No change. Nothing to do.
2102             return;
2103         }
2104 
2105         if (prevState == STATE_ON) {
2106             autoOnSetupTimer();
2107         }
2108 
2109         // Notify all proxy objects first of adapter state change
2110         if (newState == STATE_ON) {
2111             if (isAtLeastV() && mDeviceConfigAllowAutoOn) {
2112                 AutoOnFeature.notifyBluetoothOn(mCurrentUserContext);
2113             }
2114             sendBluetoothOnCallback();
2115         } else if (newState == STATE_OFF) {
2116             // If Bluetooth is off, send service down event to proxy objects, and unbind
2117             Log.d(TAG, "bluetoothStateChangeHandler: Bluetooth is OFF send Service Down");
2118             sendBluetoothServiceDownCallback();
2119             unbindAndFinish();
2120         } else if (newState == STATE_BLE_ON && prevState == STATE_BLE_TURNING_ON) {
2121             continueFromBleOnState();
2122         } // Nothing specific to do for STATE_TURNING_<X>
2123 
2124         broadcastIntentStateChange(BluetoothAdapter.ACTION_BLE_STATE_CHANGED, prevState, newState);
2125 
2126         // BLE state are shown as STATE_OFF for BrEdr users
2127         final int prevBrEdrState = isBleState(prevState) ? STATE_OFF : prevState;
2128         final int newBrEdrState = isBleState(newState) ? STATE_OFF : newState;
2129 
2130         if (prevBrEdrState != newBrEdrState) { // Only broadcast when there is a BrEdr state change.
2131             if (newBrEdrState == STATE_OFF) {
2132                 sendBluetoothOffCallback();
2133                 sendBrEdrDownCallback();
2134             }
2135             broadcastIntentStateChange(
2136                     BluetoothAdapter.ACTION_STATE_CHANGED, prevBrEdrState, newBrEdrState);
2137         }
2138     }
2139 
waitForManagerState(int state)2140     boolean waitForManagerState(int state) {
2141         return mState.waitForState(STATE_TIMEOUT, state);
2142     }
2143 
waitForState(int... states)2144     private boolean waitForState(int... states) {
2145         return mState.waitForState(STATE_TIMEOUT, states);
2146     }
2147 
sendDisableMsg(int reason)2148     private void sendDisableMsg(int reason) {
2149         sendDisableMsg(reason, mContext.getPackageName());
2150     }
2151 
sendDisableMsg(int reason, String packageName)2152     private void sendDisableMsg(int reason, String packageName) {
2153         mHandler.sendEmptyMessage(MESSAGE_DISABLE);
2154         addActiveLog(reason, packageName, false, false);
2155     }
2156 
sendEnableMsg(boolean quietMode, int reason)2157     private void sendEnableMsg(boolean quietMode, int reason) {
2158         sendEnableMsg(quietMode, reason, mContext.getPackageName());
2159     }
2160 
sendEnableMsg(boolean quietMode, int reason, String packageName)2161     private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
2162         sendEnableMsg(quietMode, reason, packageName, false);
2163     }
2164 
sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle)2165     private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
2166         mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, isBle ? 1 : 0).sendToTarget();
2167         addActiveLog(reason, packageName, true, isBle);
2168         mLastEnabledTime = SystemClock.elapsedRealtime();
2169     }
2170 
addActiveLog(int reason, boolean enable)2171     private void addActiveLog(int reason, boolean enable) {
2172         addActiveLog(reason, mContext.getPackageName(), enable, false);
2173     }
2174 
addActiveLog(int reason, String packageName, boolean enable, boolean isBle)2175     private void addActiveLog(int reason, String packageName, boolean enable, boolean isBle) {
2176         ActiveLog lastActiveLog = mActiveLogs.peekLast();
2177         synchronized (mActiveLogs) {
2178             if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
2179                 mActiveLogs.remove();
2180             }
2181             mActiveLogs.add(
2182                     new ActiveLog(reason, packageName, enable, isBle, System.currentTimeMillis()));
2183 
2184             int state =
2185                     enable
2186                             ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED
2187                             : BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2188 
2189             int lastState;
2190             long timeSinceLastChanged;
2191             if (lastActiveLog == null) {
2192                 lastState = BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN;
2193                 timeSinceLastChanged = 0;
2194             } else {
2195                 lastState =
2196                         lastActiveLog.getEnable()
2197                                 ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED
2198                                 : BluetoothStatsLog
2199                                         .BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2200                 timeSinceLastChanged = System.currentTimeMillis() - lastActiveLog.getTimestamp();
2201             }
2202 
2203             BluetoothStatsLog.write_non_chained(
2204                     BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
2205                     Binder.getCallingUid(),
2206                     null,
2207                     state,
2208                     reason,
2209                     packageName,
2210                     lastState,
2211                     timeSinceLastChanged);
2212         }
2213     }
2214 
addCrashLog()2215     private void addCrashLog() {
2216         synchronized (mCrashTimestamps) {
2217             if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
2218                 mCrashTimestamps.removeFirst();
2219             }
2220             mCrashTimestamps.add(System.currentTimeMillis());
2221             mCrashes++;
2222         }
2223     }
2224 
recoverBluetoothServiceFromError(boolean clearBle)2225     private void recoverBluetoothServiceFromError(boolean clearBle) {
2226         Log.e(TAG, "recoverBluetoothServiceFromError");
2227         boolean repeatAirplaneRunnable = false;
2228 
2229         // 0 means we are matching unset `what` since we are using a token instead
2230         if (mHandler.hasMessages(0, ON_AIRPLANE_MODE_CHANGED_TOKEN)) {
2231             mHandler.removeCallbacksAndMessages(ON_AIRPLANE_MODE_CHANGED_TOKEN);
2232             repeatAirplaneRunnable = true;
2233         }
2234         mAdapterLock.readLock().lock();
2235         try {
2236             if (mAdapter != null) {
2237                 // Unregister callback object
2238                 mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource());
2239             }
2240         } catch (RemoteException e) {
2241             Log.e(TAG, "Unable to unregister", e);
2242         } finally {
2243             mAdapterLock.readLock().unlock();
2244         }
2245 
2246         SystemClock.sleep(500);
2247 
2248         // disable
2249         addActiveLog(ENABLE_DISABLE_REASON_START_ERROR, false);
2250         handleDisable();
2251 
2252         waitForState(STATE_OFF);
2253 
2254         sendBluetoothServiceDownCallback();
2255 
2256         mAdapterLock.writeLock().lock();
2257         try {
2258             if (mAdapter != null) {
2259                 mAdapter = null;
2260                 // Unbind
2261                 mContext.unbindService(mConnection);
2262             }
2263         } finally {
2264             mAdapterLock.writeLock().unlock();
2265         }
2266 
2267         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2268         mState.set(STATE_OFF);
2269 
2270         if (clearBle) {
2271             clearBleApps();
2272         }
2273 
2274         mEnable = false;
2275 
2276         // Send a Bluetooth Restart message to reenable bluetooth
2277         mHandler.sendEmptyMessageDelayed(MESSAGE_RESTART_BLUETOOTH_SERVICE, ERROR_RESTART_TIME_MS);
2278 
2279         if (repeatAirplaneRunnable) {
2280             onAirplaneModeChanged(AirplaneModeListener.isOnOverrode());
2281         }
2282     }
2283 
isBluetoothDisallowed()2284     private boolean isBluetoothDisallowed() {
2285         final long callingIdentity = Binder.clearCallingIdentity();
2286         try {
2287             return mContext.getSystemService(UserManager.class)
2288                     .hasUserRestrictionForUser(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2289         } finally {
2290             Binder.restoreCallingIdentity(callingIdentity);
2291         }
2292     }
2293 
2294     /**
2295      * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
2296      * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2297      * state if Bluetooth is not disallowed.
2298      *
2299      * @param userHandle user to disable bluetooth sharing for
2300      * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
2301      */
updateOppLauncherComponentState( UserHandle userHandle, boolean bluetoothSharingDisallowed)2302     private void updateOppLauncherComponentState(
2303             UserHandle userHandle, boolean bluetoothSharingDisallowed) {
2304         try {
2305             int newState;
2306             if (bluetoothSharingDisallowed) {
2307                 newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
2308             } else if (BluetoothProperties.isProfileOppEnabled().orElse(false)) {
2309                 newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
2310             } else {
2311                 newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2312             }
2313 
2314             // Bluetooth OPP activities that should always be enabled,
2315             // even when Bluetooth is turned OFF.
2316             List<String> baseBluetoothOppActivities =
2317                     List.of(
2318                             // Base sharing activity
2319                             "com.android.bluetooth.opp.BluetoothOppLauncherActivity",
2320                             // BT enable activities
2321                             "com.android.bluetooth.opp.BluetoothOppBtEnableActivity",
2322                             "com.android.bluetooth.opp.BluetoothOppBtEnablingActivity",
2323                             "com.android.bluetooth.opp.BluetoothOppBtErrorActivity");
2324 
2325             PackageManager systemPackageManager = mContext.getPackageManager();
2326             PackageManager userPackageManager =
2327                     mContext.createContextAsUser(userHandle, 0).getPackageManager();
2328             var allPackages = systemPackageManager.getPackagesForUid(Process.BLUETOOTH_UID);
2329             for (String candidatePackage : allPackages) {
2330                 Log.v(TAG, "Searching package " + candidatePackage);
2331                 PackageInfo packageInfo;
2332                 try {
2333                     packageInfo =
2334                             systemPackageManager.getPackageInfo(
2335                                     candidatePackage,
2336                                     PackageManager.PackageInfoFlags.of(
2337                                             PackageManager.GET_ACTIVITIES
2338                                                     | PackageManager.MATCH_ANY_USER
2339                                                     | PackageManager.MATCH_UNINSTALLED_PACKAGES
2340                                                     | PackageManager.MATCH_DISABLED_COMPONENTS));
2341                 } catch (PackageManager.NameNotFoundException e) {
2342                     // ignore, try next package
2343                     Log.e(TAG, "Could not find package " + candidatePackage);
2344                     continue;
2345                 } catch (Exception e) {
2346                     Log.e(TAG, "Error while loading package" + e);
2347                     continue;
2348                 }
2349                 if (packageInfo.activities == null) {
2350                     continue;
2351                 }
2352                 for (var activity : packageInfo.activities) {
2353                     Log.v(TAG, "Checking activity " + activity.name);
2354                     if (baseBluetoothOppActivities.contains(activity.name)) {
2355                         for (String activityName : baseBluetoothOppActivities) {
2356                             userPackageManager.setComponentEnabledSetting(
2357                                     new ComponentName(candidatePackage, activityName),
2358                                     newState,
2359                                     PackageManager.DONT_KILL_APP);
2360                         }
2361                         return;
2362                     }
2363                 }
2364             }
2365 
2366             Log.e(
2367                     TAG,
2368                     "Cannot toggle Bluetooth OPP activities, could not find them in any package");
2369         } catch (Exception e) {
2370             Log.e(TAG, "updateOppLauncherComponentState failed: " + e);
2371         }
2372     }
2373 
getServiceRestartMs()2374     private int getServiceRestartMs() {
2375         return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
2376     }
2377 
dump(FileDescriptor fd, PrintWriter writer, String[] args)2378     void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2379         if ((args.length > 0) && args[0].startsWith("--proto")) {
2380             dumpProto(fd);
2381             return;
2382         }
2383         String errorMsg = null;
2384 
2385         writer.println("Bluetooth Status");
2386         writer.println("  enabled: " + isEnabled());
2387         writer.println("  state: " + mState);
2388         writer.println("  address: " + logAddress(mAddress));
2389         writer.println("  name: " + mName);
2390         if (mEnable) {
2391             long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
2392             String onDurationString =
2393                     String.format(
2394                             Locale.US,
2395                             "%02d:%02d:%02d.%03d",
2396                             (int) (onDuration / (1000 * 60 * 60)),
2397                             (int) ((onDuration / (1000 * 60)) % 60),
2398                             (int) ((onDuration / 1000) % 60),
2399                             (int) (onDuration % 1000));
2400             writer.println("  time since enabled: " + onDurationString);
2401         }
2402 
2403         if (mActiveLogs.size() == 0) {
2404             writer.println("\nBluetooth never enabled!");
2405         } else {
2406             writer.println("\nEnable log:");
2407             for (ActiveLog log : mActiveLogs) {
2408                 writer.println("  " + log);
2409             }
2410         }
2411 
2412         writer.println("\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2413         if (mCrashes == CRASH_LOG_MAX_SIZE) {
2414             writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2415         }
2416         for (Long time : mCrashTimestamps) {
2417             writer.println("  " + timeToLog(time));
2418         }
2419 
2420         writer.println(
2421                 "\n"
2422                         + mBleApps.size()
2423                         + " BLE app"
2424                         + (mBleApps.size() == 1 ? "" : "s")
2425                         + " registered");
2426         for (ClientDeathRecipient app : mBleApps.values()) {
2427             writer.println("  " + app.getPackageName());
2428         }
2429 
2430         writer.println("\nBluetoothManagerService:");
2431         writer.println("  mEnable:" + mEnable);
2432         writer.println("  mQuietEnable:" + mQuietEnable);
2433         writer.println("  mEnableExternal:" + mEnableExternal);
2434         writer.println("  mQuietEnableExternal:" + mQuietEnableExternal);
2435 
2436         writer.println("");
2437         writer.flush();
2438         if (args.length == 0) {
2439             // Add arg to produce output
2440             args = new String[1];
2441             args[0] = "--print";
2442         }
2443 
2444         try {
2445             dumpBluetoothFlags(writer);
2446         } catch (Exception e) {
2447             writer.println("Exception while dumping Bluetooth Flags");
2448         }
2449 
2450         if (mAdapter == null) {
2451             errorMsg = "Bluetooth Service not connected";
2452         } else {
2453             try {
2454                 mAdapter.getAdapterBinder().asBinder().dumpAsync(fd, args);
2455             } catch (RemoteException re) {
2456                 errorMsg = "RemoteException while dumping Bluetooth Service";
2457             }
2458         }
2459         if (errorMsg != null) {
2460             writer.println(errorMsg);
2461         }
2462     }
2463 
dumpBluetoothFlags(PrintWriter writer)2464     private void dumpBluetoothFlags(PrintWriter writer)
2465             throws IllegalAccessException, InvocationTargetException {
2466         writer.println("��Flag dump:");
2467 
2468         // maxLen is used to align the flag output
2469         int maxLen =
2470                 Arrays.stream(Flags.class.getDeclaredMethods())
2471                         .map(Method::getName)
2472                         .map(String::length)
2473                         .max(Integer::compare)
2474                         .get();
2475 
2476         String fmt = "\t%s: %-" + maxLen + "s %s";
2477 
2478         for (Method m : Flags.class.getDeclaredMethods()) {
2479             String flagStatus = ((Boolean) m.invoke(null)) ? "[■]" : "[ ]";
2480             String name = m.getName();
2481             String snakeCaseName = name.replaceAll("([A-Z])", "_$1").toLowerCase(Locale.US);
2482             writer.println(String.format(fmt, flagStatus, name, snakeCaseName));
2483         }
2484         writer.println("");
2485     }
2486 
dumpProto(FileDescriptor fd)2487     private void dumpProto(FileDescriptor fd) {
2488         final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
2489         proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled());
2490         proto.write(BluetoothManagerServiceDumpProto.STATE, mState.get());
2491         proto.write(
2492                 BluetoothManagerServiceDumpProto.STATE_NAME,
2493                 BluetoothAdapter.nameForState(mState.get()));
2494         proto.write(BluetoothManagerServiceDumpProto.ADDRESS, logAddress(mAddress));
2495         proto.write(BluetoothManagerServiceDumpProto.NAME, mName);
2496         if (mEnable) {
2497             proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime);
2498         }
2499         proto.write(
2500                 BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS, SystemClock.elapsedRealtime());
2501         for (ActiveLog log : mActiveLogs) {
2502             long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS);
2503             log.dump(proto);
2504             proto.end(token);
2505         }
2506         proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes);
2507         proto.write(
2508                 BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED, mCrashes == CRASH_LOG_MAX_SIZE);
2509         for (Long time : mCrashTimestamps) {
2510             proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time);
2511         }
2512         proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size());
2513         for (ClientDeathRecipient app : mBleApps.values()) {
2514             proto.write(
2515                     BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES, app.getPackageName());
2516         }
2517         proto.flush();
2518     }
2519 
getEnableDisableReasonString(int reason)2520     private static String getEnableDisableReasonString(int reason) {
2521         switch (reason) {
2522             case ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
2523                 return "APPLICATION_REQUEST";
2524             case ENABLE_DISABLE_REASON_AIRPLANE_MODE:
2525                 return "AIRPLANE_MODE";
2526             case ENABLE_DISABLE_REASON_DISALLOWED:
2527                 return "DISALLOWED";
2528             case ENABLE_DISABLE_REASON_RESTARTED:
2529                 return "RESTARTED";
2530             case ENABLE_DISABLE_REASON_START_ERROR:
2531                 return "START_ERROR";
2532             case ENABLE_DISABLE_REASON_SYSTEM_BOOT:
2533                 return "SYSTEM_BOOT";
2534             case ENABLE_DISABLE_REASON_CRASH:
2535                 return "CRASH";
2536             case ENABLE_DISABLE_REASON_USER_SWITCH:
2537                 return "USER_SWITCH";
2538             case ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
2539                 return "RESTORE_USER_SETTING";
2540             case ENABLE_DISABLE_REASON_FACTORY_RESET:
2541                 return "FACTORY_RESET";
2542             case ENABLE_DISABLE_REASON_SATELLITE_MODE:
2543                 return "SATELLITE MODE";
2544             default:
2545                 return "UNKNOWN[" + reason + "]";
2546         }
2547     }
2548 
getTempAllowlistBroadcastOptions()2549     static @NonNull Bundle getTempAllowlistBroadcastOptions() {
2550         final long duration = 10_000;
2551         final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
2552         bOptions.setTemporaryAppAllowlist(
2553                 duration,
2554                 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
2555                 PowerExemptionManager.REASON_BLUETOOTH_BROADCAST,
2556                 "");
2557         return bOptions.toBundle();
2558     }
2559 
resolveSystemService(@onNull Intent intent)2560     private ComponentName resolveSystemService(@NonNull Intent intent) {
2561         List<ResolveInfo> results = mContext.getPackageManager().queryIntentServices(intent, 0);
2562         if (results == null) {
2563             return null;
2564         }
2565         ComponentName comp = null;
2566         for (int i = 0; i < results.size(); i++) {
2567             ResolveInfo ri = results.get(i);
2568             if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
2569                 continue;
2570             }
2571             ComponentName foundComp =
2572                     new ComponentName(
2573                             ri.serviceInfo.applicationInfo.packageName, ri.serviceInfo.name);
2574             if (comp != null) {
2575                 throw new IllegalStateException(
2576                         "Multiple system services handle "
2577                                 + intent
2578                                 + ": "
2579                                 + comp
2580                                 + ", "
2581                                 + foundComp);
2582             }
2583             comp = foundComp;
2584         }
2585         return comp;
2586     }
2587 
setBtHciSnoopLogMode(int mode)2588     int setBtHciSnoopLogMode(int mode) {
2589         final BluetoothProperties.snoop_log_mode_values snoopMode;
2590 
2591         switch (mode) {
2592             case BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED:
2593                 snoopMode = BluetoothProperties.snoop_log_mode_values.DISABLED;
2594                 break;
2595             case BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED:
2596                 snoopMode = BluetoothProperties.snoop_log_mode_values.FILTERED;
2597                 break;
2598             case BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL:
2599                 snoopMode = BluetoothProperties.snoop_log_mode_values.FULL;
2600                 break;
2601             default:
2602                 Log.e(TAG, "setBtHciSnoopLogMode: Not a valid mode:" + mode);
2603                 return BluetoothStatusCodes.ERROR_BAD_PARAMETERS;
2604         }
2605         try {
2606             BluetoothProperties.snoop_log_mode(snoopMode);
2607         } catch (RuntimeException e) {
2608             Log.e(TAG, "setBtHciSnoopLogMode: Failed to set mode to " + mode + ": " + e);
2609             return BluetoothStatusCodes.ERROR_UNKNOWN;
2610         }
2611         return BluetoothStatusCodes.SUCCESS;
2612     }
2613 
getBtHciSnoopLogMode()2614     int getBtHciSnoopLogMode() {
2615         BluetoothProperties.snoop_log_mode_values mode =
2616                 BluetoothProperties.snoop_log_mode()
2617                         .orElse(BluetoothProperties.snoop_log_mode_values.DISABLED);
2618         if (mode == BluetoothProperties.snoop_log_mode_values.FILTERED) {
2619             return BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED;
2620         } else if (mode == BluetoothProperties.snoop_log_mode_values.FULL) {
2621             return BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL;
2622         }
2623         return BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED;
2624     }
2625 
2626     private final boolean mDeviceConfigAllowAutoOn;
2627 
autoOnSetupTimer()2628     private void autoOnSetupTimer() {
2629         if (!mDeviceConfigAllowAutoOn) {
2630             Log.d(TAG, "No support for AutoOn feature: Not creating a timer");
2631             return;
2632         }
2633         AutoOnFeature.resetAutoOnTimerForUser(
2634                 mLooper, mCurrentUserContext, mState, this::enableFromAutoOn);
2635     }
2636 
postAndWait(Callable<T> callable)2637     private <T> T postAndWait(Callable<T> callable) {
2638         FutureTask<T> task = new FutureTask(callable);
2639 
2640         mHandler.post(task);
2641         try {
2642             return task.get(1, TimeUnit.SECONDS);
2643         } catch (TimeoutException | InterruptedException e) {
2644             SneakyThrow.sneakyThrow(e);
2645         } catch (ExecutionException e) {
2646             SneakyThrow.sneakyThrow(e.getCause());
2647         }
2648         return null;
2649     }
2650 
isAutoOnSupported()2651     boolean isAutoOnSupported() {
2652         return mDeviceConfigAllowAutoOn
2653                 && postAndWait(
2654                         () ->
2655                                 AutoOnFeature.isUserSupported(
2656                                         mCurrentUserContext.getContentResolver()));
2657     }
2658 
isAutoOnEnabled()2659     boolean isAutoOnEnabled() {
2660         if (!mDeviceConfigAllowAutoOn) {
2661             throw new IllegalStateException("AutoOnFeature is not supported in current config");
2662         }
2663         return postAndWait(() -> AutoOnFeature.isUserEnabled(mCurrentUserContext));
2664     }
2665 
2666     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
setAutoOnEnabled(boolean status)2667     void setAutoOnEnabled(boolean status) {
2668         if (!mDeviceConfigAllowAutoOn) {
2669             throw new IllegalStateException("AutoOnFeature is not supported in current config");
2670         }
2671         postAndWait(
2672                 Executors.callable(
2673                         () ->
2674                                 AutoOnFeature.setUserEnabled(
2675                                         mLooper,
2676                                         mCurrentUserContext,
2677                                         mState,
2678                                         status,
2679                                         this::enableFromAutoOn)));
2680     }
2681 
2682     /**
2683      * Check if BLE is supported by this platform
2684      *
2685      * @param context current device context
2686      * @return true if BLE is supported, false otherwise
2687      */
isBleSupported(Context context)2688     private static boolean isBleSupported(Context context) {
2689         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
2690     }
2691 
2692     /**
2693      * Check if this is an automotive device
2694      *
2695      * @param context current device context
2696      * @return true if this Android device is an automotive device, false otherwise
2697      */
isAutomotive(Context context)2698     private static boolean isAutomotive(Context context) {
2699         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
2700     }
2701 
2702     /**
2703      * Check if this is a watch device
2704      *
2705      * @param context current device context
2706      * @return true if this Android device is a watch device, false otherwise
2707      */
isWatch(Context context)2708     private static boolean isWatch(Context context) {
2709         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
2710     }
2711 
2712     /**
2713      * Check if this is a TV device
2714      *
2715      * @param context current device context
2716      * @return true if this Android device is a TV device, false otherwise
2717      */
isTv(Context context)2718     private static boolean isTv(Context context) {
2719         PackageManager pm = context.getPackageManager();
2720         return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
2721                 || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
2722     }
2723 }
2724