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