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