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