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