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