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