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