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