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