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