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