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