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