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