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