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