BluetoothManagerService.java revision 7ee53be300573c9bdc71607d32d4a642e4ad3dc8
10f42037eb7b5118015c2caca635538324ccf0ccffredc/* 2fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Copyright (C) 2012 The Android Open Source Project 3fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * 4fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * you may not use this file except in compliance with the License. 6fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * You may obtain a copy of the License at 7fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * 8fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * 10fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Unless required by applicable law or agreed to in writing, software 11fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * See the License for the specific language governing permissions and 14fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * limitations under the License. 150f42037eb7b5118015c2caca635538324ccf0ccffredc */ 160f42037eb7b5118015c2caca635538324ccf0ccffredc 170f42037eb7b5118015c2caca635538324ccf0ccffredcpackage com.android.server; 180f42037eb7b5118015c2caca635538324ccf0ccffredc 19408abf7f1bec3253675d0225300d7ee39481d286Svet Ganovimport android.Manifest; 2040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.app.ActivityManager; 210f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.BluetoothAdapter; 22e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.BluetoothProfile; 230f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetooth; 24bf072a712f584ae1c01022835b0de21c40513d06fredcimport android.bluetooth.IBluetoothCallback; 25e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wangimport android.bluetooth.IBluetoothGatt; 26e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.IBluetoothHeadset; 270f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManager; 280f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManagerCallback; 29e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.IBluetoothProfileServiceConnection; 300f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothStateChangeCallback; 310f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.BroadcastReceiver; 320f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ComponentName; 330f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ContentResolver; 340f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Context; 350f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Intent; 360f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.IntentFilter; 370f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ServiceConnection; 3832ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xieimport android.content.pm.PackageManager; 39e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.content.pm.UserInfo; 40e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wangimport android.database.ContentObserver; 4140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Binder; 420f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Handler; 430f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.IBinder; 4440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Looper; 450f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Message; 4640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Process; 47d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredcimport android.os.RemoteCallbackList; 480f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.RemoteException; 4940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.SystemClock; 505ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 51e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.UserManager; 520f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.provider.Settings; 5367d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wangimport android.provider.Settings.SettingNotFoundException; 5467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkeyimport android.util.Slog; 55eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavovimport java.util.concurrent.locks.ReentrantReadWriteLock; 56726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood 57726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.FileDescriptor; 58726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.PrintWriter; 59e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.HashMap; 60e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.Map; 61658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 620f42037eb7b5118015c2caca635538324ccf0ccffredcclass BluetoothManagerService extends IBluetoothManager.Stub { 630f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String TAG = "BluetoothManagerService"; 64b5a479c1f08c8ea41a1523695bc482c79ed4ea54Pavlin Radoslavov private static final boolean DBG = false; 650f42037eb7b5118015c2caca635538324ccf0ccffredc 660f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 670f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 680f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 690f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String EXTRA_ACTION="action"; 70d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 710f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 720f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 730f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 740f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 751223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M //Maximum msec to wait for service restart 761223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int SERVICE_RESTART_TIME_MS = 200; 77dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Maximum msec to wait for restart due to error 78dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private static final int ERROR_RESTART_TIME_MS = 3000; 7940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Maximum msec to delay MESSAGE_USER_SWITCHED 8040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int USER_SWITCHED_TIME_MS = 200; 81e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Delay for the addProxy function in msec 82e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int ADD_PROXY_DELAY_MS = 100; 830f42037eb7b5118015c2caca635538324ccf0ccffredc 840f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_ENABLE = 1; 850f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_DISABLE = 2; 86649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_ADAPTER = 20; 87649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 88649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 89649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 90649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 91649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 921223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 93aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; 94aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_TIMEOUT_BIND = 100; 95aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_TIMEOUT_UNBIND = 101; 964bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; 9740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int MESSAGE_USER_SWITCHED = 300; 98aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_USER_UNLOCKED = 301; 99e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 100e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 101aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MAX_SAVE_RETRIES = 3; 102aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MAX_ERROR_RESTART_RETRIES = 6; 103dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 104401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is off 105401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_OFF=0; 106401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 107401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode won't affect Bluetooth state at start up 108401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_BLUETOOTH=1; 109401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 110401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // but Airplane mode will affect Bluetooth state at start up 111401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode will have higher priority. 112401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_AIRPLANE=2; 1130f42037eb7b5118015c2caca635538324ccf0ccffredc 114ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTH = 1; 115ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTHGATT = 2; 116ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 1170f42037eb7b5118015c2caca635538324ccf0ccffredc private final Context mContext; 118d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private static int mBleAppCount = 0; 119cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 120cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // Locks are not provided for mName and mAddress. 121cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // They are accessed in handler or broadcast receiver, same thread context. 1220f42037eb7b5118015c2caca635538324ccf0ccffredc private String mAddress; 1230f42037eb7b5118015c2caca635538324ccf0ccffredc private String mName; 1246fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final ContentResolver mContentResolver; 1256fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 1266fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 1279db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen private IBinder mBluetoothBinder; 128649fe497cea2f19e937f84218d1080bdcefe47f2fredc private IBluetooth mBluetooth; 129ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private IBluetoothGatt mBluetoothGatt; 130eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov private final ReentrantReadWriteLock mBluetoothLock = 131eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov new ReentrantReadWriteLock(); 132649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mBinding; 133649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mUnbinding; 134401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 135fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta private boolean mQuietEnable = false; 136401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 137401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 138401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mQuietEnableExternal; 139401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 140401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 141401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mEnableExternal; 142401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 14340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean mEnable; 14440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private int mState; 14540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private final BluetoothHandler mHandler; 146dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private int mErrorRecoveryRetryCounter; 147bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos private final int mSystemUiUid; 1480f42037eb7b5118015c2caca635538324ccf0ccffredc 149e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Save a ProfileServiceConnections object for each of the bound 150e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // bluetooth profile services 151e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private final Map <Integer, ProfileServiceConnections> mProfileServices = 152e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new HashMap <Integer, ProfileServiceConnections>(); 153e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 154649fe497cea2f19e937f84218d1080bdcefe47f2fredc private void registerForAirplaneMode(IntentFilter filter) { 155649fe497cea2f19e937f84218d1080bdcefe47f2fredc final ContentResolver resolver = mContext.getContentResolver(); 156c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String airplaneModeRadios = Settings.Global.getString(resolver, 157c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_RADIOS); 158c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String toggleableRadios = Settings.Global.getString(resolver, 159c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 160649fe497cea2f19e937f84218d1080bdcefe47f2fredc boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 161c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 162649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (mIsAirplaneSensitive) { 163649fe497cea2f19e937f84218d1080bdcefe47f2fredc filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 164649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 165649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 1660f42037eb7b5118015c2caca635538324ccf0ccffredc 167bf072a712f584ae1c01022835b0de21c40513d06fredc private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 168bf072a712f584ae1c01022835b0de21c40513d06fredc @Override 169bf072a712f584ae1c01022835b0de21c40513d06fredc public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 170bf072a712f584ae1c01022835b0de21c40513d06fredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 171bf072a712f584ae1c01022835b0de21c40513d06fredc mHandler.sendMessage(msg); 172bf072a712f584ae1c01022835b0de21c40513d06fredc } 173bf072a712f584ae1c01022835b0de21c40513d06fredc }; 174bf072a712f584ae1c01022835b0de21c40513d06fredc 175bf072a712f584ae1c01022835b0de21c40513d06fredc private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1760f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 1770f42037eb7b5118015c2caca635538324ccf0ccffredc public void onReceive(Context context, Intent intent) { 1780f42037eb7b5118015c2caca635538324ccf0ccffredc String action = intent.getAction(); 179bf072a712f584ae1c01022835b0de21c40513d06fredc if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 1800f42037eb7b5118015c2caca635538324ccf0ccffredc String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 18167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); 1820f42037eb7b5118015c2caca635538324ccf0ccffredc if (newName != null) { 1830f42037eb7b5118015c2caca635538324ccf0ccffredc storeNameAndAddress(newName, null); 1840f42037eb7b5118015c2caca635538324ccf0ccffredc } 185649fe497cea2f19e937f84218d1080bdcefe47f2fredc } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 186401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 187401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 188401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 189401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 190401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else { 191401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 192401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 193401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 194d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 195d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora int st = BluetoothAdapter.STATE_OFF; 196eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 197eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 198eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) { 199d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora st = mBluetooth.getState(); 200d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 201eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 202eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to call getState", e); 203eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 204eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 205d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 20667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "state" + st); 207d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 208401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 209d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Clear registered LE apps to force shut-off 210d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora synchronized (this) { 211d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBleAppCount = 0; 21211f83882f2a4448b5a2bbbb9e23b700096ed7536Nitin Arora mBleApps.clear(); 213d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 214d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (st == BluetoothAdapter.STATE_BLE_ON) { 215d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora //if state is BLE_ON make sure you trigger disableBLE part 216d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 217eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 218d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBluetooth != null) { 219d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetooth.onBrEdrDown(); 220d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mEnableExternal = false; 221d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 222eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 22367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call onBrEdrDown", e); 224eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 2257ee53be300573c9bdc71607d32d4a642e4ad3dc8Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 226d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 227d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (st == BluetoothAdapter.STATE_ON){ 228d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // disable without persisting the setting 22967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Calling disable"); 230d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendDisableMsg(); 231d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 232401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else if (mEnableExternal) { 233401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // enable without persisting the setting 23467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Calling enable"); 235401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(mQuietEnableExternal); 236401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 237649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 2380f42037eb7b5118015c2caca635538324ccf0ccffredc } 2390f42037eb7b5118015c2caca635538324ccf0ccffredc } 2400f42037eb7b5118015c2caca635538324ccf0ccffredc }; 2410f42037eb7b5118015c2caca635538324ccf0ccffredc 2420f42037eb7b5118015c2caca635538324ccf0ccffredc BluetoothManagerService(Context context) { 2438d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn mHandler = new BluetoothHandler(IoThread.get().getLooper()); 24440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 2450f42037eb7b5118015c2caca635538324ccf0ccffredc mContext = context; 2460f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = null; 2479db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = null; 248d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetoothGatt = null; 2490f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 2500f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = false; 25140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 25240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = BluetoothAdapter.STATE_OFF; 253401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 254401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 2550f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = null; 2560f42037eb7b5118015c2caca635538324ccf0ccffredc mName = null; 257dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 2580f42037eb7b5118015c2caca635538324ccf0ccffredc mContentResolver = context.getContentResolver(); 259e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Observe BLE scan only mode settings change. 260e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang registerForBleScanModeChange(); 261d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 262d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 263658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 2646fde3098074ab2551867d1cd919958383b15725fMatthew Xie registerForAirplaneMode(filter); 265d83a096f299abd9c7fe5e441ef1bb169c314b575Dianne Hackborn filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 2666fde3098074ab2551867d1cd919958383b15725fMatthew Xie mContext.registerReceiver(mReceiver, filter); 2670f42037eb7b5118015c2caca635538324ccf0ccffredc loadStoredNameAndAddress(); 268401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 269401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 2700f42037eb7b5118015c2caca635538324ccf0ccffredc } 271bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos 272bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos int sysUiUid = -1; 273bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos try { 274e06b4d1d9f718b9fe02980fea794a36831a16db2Jeff Sharkey sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", 275c5967e9862489024c932b0c7fcb84ed0af2a7fd7Jeff Sharkey PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); 276bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos } catch (PackageManager.NameNotFoundException e) { 277acddf2b34965da479efe46bd87871234ac6a5aabJoe LaPenna // Some platforms, such as wearables do not have a system ui. 27867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); 279bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos } 280bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos mSystemUiUid = sysUiUid; 2810f42037eb7b5118015c2caca635538324ccf0ccffredc } 2820f42037eb7b5118015c2caca635538324ccf0ccffredc 283649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 284649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if airplane mode is currently on 285649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 286649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isAirplaneModeOn() { 287c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate return Settings.Global.getInt(mContext.getContentResolver(), 288c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 289649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 290649fe497cea2f19e937f84218d1080bdcefe47f2fredc 291649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 292649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth saved state is "on" 293649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 294649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isBluetoothPersistedStateOn() { 295bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown return Settings.Global.getInt(mContentResolver, 296401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; 297401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 298401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 299401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu /** 300401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 301401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu */ 302401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private final boolean isBluetoothPersistedStateOnBluetooth() { 303401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return Settings.Global.getInt(mContentResolver, 304401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; 305649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 306649fe497cea2f19e937f84218d1080bdcefe47f2fredc 307649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 308649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth on/off state 309649fe497cea2f19e937f84218d1080bdcefe47f2fredc * 310649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 311401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void persistBluetoothSetting(int value) { 312bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.putInt(mContext.getContentResolver(), 313bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.BLUETOOTH_ON, 314401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu value); 315649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 316649fe497cea2f19e937f84218d1080bdcefe47f2fredc 317649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 318649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth Adapter's name and address is 319649fe497cea2f19e937f84218d1080bdcefe47f2fredc * locally cached 320649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @return 321649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3220f42037eb7b5118015c2caca635538324ccf0ccffredc private boolean isNameAndAddressSet() { 3230f42037eb7b5118015c2caca635538324ccf0ccffredc return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 3240f42037eb7b5118015c2caca635538324ccf0ccffredc } 3250f42037eb7b5118015c2caca635538324ccf0ccffredc 326649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 327649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Retrieve the Bluetooth Adapter's name and address and save it in 328649fe497cea2f19e937f84218d1080bdcefe47f2fredc * in the local cache 329649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3300f42037eb7b5118015c2caca635538324ccf0ccffredc private void loadStoredNameAndAddress() { 33167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Loading stored name and address"); 332d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (mContext.getResources().getBoolean 333d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu (com.android.internal.R.bool.config_bluetooth_address_validation) && 334d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 335d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu // if the valid flag is not set, don't load the address and name 33667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored"); 337d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu return; 338d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 3390f42037eb7b5118015c2caca635538324ccf0ccffredc mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 3400f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 34167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 3420f42037eb7b5118015c2caca635538324ccf0ccffredc } 3430f42037eb7b5118015c2caca635538324ccf0ccffredc 344649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 345649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth name and address in the persistent store. 346649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Only non-null values will be saved. 347649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param name 348649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param address 349649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3500f42037eb7b5118015c2caca635538324ccf0ccffredc private void storeNameAndAddress(String name, String address) { 3510f42037eb7b5118015c2caca635538324ccf0ccffredc if (name != null) { 3520f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 3530f42037eb7b5118015c2caca635538324ccf0ccffredc mName = name; 35467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Stored Bluetooth name: " + 355649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 3560f42037eb7b5118015c2caca635538324ccf0ccffredc } 3570f42037eb7b5118015c2caca635538324ccf0ccffredc 3580f42037eb7b5118015c2caca635538324ccf0ccffredc if (address != null) { 3590f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 3600f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress=address; 36167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " + 362649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 3630f42037eb7b5118015c2caca635538324ccf0ccffredc } 364d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu 365d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if ((name != null) && (address != null)) { 366d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 367d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 3680f42037eb7b5118015c2caca635538324ccf0ccffredc } 3690f42037eb7b5118015c2caca635538324ccf0ccffredc 3700f42037eb7b5118015c2caca635538324ccf0ccffredc public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 37155db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 37267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Callback is null in registerAdapter"); 37355db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return null; 37455db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 3750f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 3760f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3770f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 378eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 379eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov return mBluetooth; 3800f42037eb7b5118015c2caca635538324ccf0ccffredc } 3810f42037eb7b5118015c2caca635538324ccf0ccffredc 3820f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterAdapter(IBluetoothManagerCallback callback) { 38355db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 38467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Callback is null in unregisterAdapter"); 38555db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return; 38655db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 3870f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 3880f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 3890f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 3900f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3910f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3920f42037eb7b5118015c2caca635538324ccf0ccffredc } 3930f42037eb7b5118015c2caca635538324ccf0ccffredc 3940f42037eb7b5118015c2caca635538324ccf0ccffredc public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 3950f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 3960f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 3970f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 3980f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3990f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 4000f42037eb7b5118015c2caca635538324ccf0ccffredc } 4010f42037eb7b5118015c2caca635538324ccf0ccffredc 4020f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 4030f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 4040f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 4050f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 4060f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 4070f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 4080f42037eb7b5118015c2caca635538324ccf0ccffredc } 4090f42037eb7b5118015c2caca635538324ccf0ccffredc 4100f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean isEnabled() { 4116eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 4126eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 41367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user"); 41440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 41540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 41640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 417eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 418eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 419eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.isEnabled(); 420eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 421eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "isEnabled()", e); 422eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 423eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 4240f42037eb7b5118015c2caca635538324ccf0ccffredc } 4250f42037eb7b5118015c2caca635538324ccf0ccffredc return false; 4260f42037eb7b5118015c2caca635538324ccf0ccffredc } 4270f42037eb7b5118015c2caca635538324ccf0ccffredc 428d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora class ClientDeathRecipient implements IBinder.DeathRecipient { 429d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public void binderDied() { 43067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); 431d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBleAppCount > 0) --mBleAppCount; 432d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 433d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBleAppCount == 0) { 43467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); 435d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 436eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 437d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBluetooth != null) { 438d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetooth.onBrEdrDown(); 439d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 440eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 44167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call onBrEdrDown", e); 442eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 443eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 444d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 445d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 446d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 447d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 448d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 449d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** Internal death rec list */ 450d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>(); 451d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 45267d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang @Override 45367d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang public boolean isBleScanAlwaysAvailable() { 45467d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang try { 45567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang return (Settings.Global.getInt(mContentResolver, 45667d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; 45767d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } catch (SettingNotFoundException e) { 45867d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } 45967d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang return false; 46067d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } 46167d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang 462e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Monitor change of BLE scan only mode settings. 463e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void registerForBleScanModeChange() { 464e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang ContentObserver contentObserver = new ContentObserver(null) { 465e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang @Override 466e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang public void onChange(boolean selfChange) { 467e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang if (!isBleScanAlwaysAvailable()) { 468e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang disableBleScanMode(); 469e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang clearBleApps(); 470e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang try { 471eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 472e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang if (mBluetooth != null) mBluetooth.onBrEdrDown(); 473e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } catch (RemoteException e) { 47467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "error when disabling bluetooth", e); 475eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 476eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 477e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 478e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 479e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 480e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang }; 481e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 482e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mContentResolver.registerContentObserver( 483e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), 484e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang false, contentObserver); 485e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 486e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 487e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Disable ble scan only mode. 488e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void disableBleScanMode() { 489e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang try { 490eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 491e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { 49267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); 493e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mEnable = false; 494e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 495e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } catch (RemoteException e) { 49667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "getState()", e); 497eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 498eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 499e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 500e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 501e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 502d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public int updateBleAppCount(IBinder token, boolean enable) { 503d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (enable) { 504d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient r = mBleApps.get(token); 505d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (r == null) { 506d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient deathRec = new ClientDeathRecipient(); 507d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 508d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora token.linkToDeath(deathRec, 0); 509d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } catch (RemoteException ex) { 510d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora throw new IllegalArgumentException("Wake lock is already dead."); 511d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 512d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBleApps.put(token, deathRec); 513d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora synchronized (this) { 514d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ++mBleAppCount; 515d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 51667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Registered for death Notification"); 517d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 518d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 519d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else { 520d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient r = mBleApps.get(token); 521d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (r != null) { 522e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Unregister death recipient as the app goes away. 523e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang token.unlinkToDeath(r, 0); 524d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBleApps.remove(token); 525d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora synchronized (this) { 526d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBleAppCount > 0) --mBleAppCount; 527d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 52867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Unregistered for death Notification"); 529d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 530d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 53167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); 532d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBleAppCount == 0 && mEnable) { 533e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang disableBleScanMode(); 534d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 535d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora return mBleAppCount; 536d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 537d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 538e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Clear all apps using BLE scan only mode. 539e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void clearBleApps() { 540e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang synchronized (this) { 541e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mBleApps.clear(); 542e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mBleAppCount = 0; 543e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 544e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 545e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 546d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** @hide*/ 547d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public boolean isBleAppPresent() { 54867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); 549d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora return (mBleAppCount > 0); 550d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 551d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 552d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** 553d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora * Action taken when GattService is turned off 554d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora */ 555d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void onBluetoothGattServiceUp() { 55667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); 557eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 558eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 559bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora if (isBleAppPresent() == false && mBluetooth != null 560bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { 561d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetooth.onLeServiceUp(); 562d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 563d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // waive WRITE_SECURE_SETTINGS permission check 564d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora long callingIdentity = Binder.clearCallingIdentity(); 565d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 566d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Binder.restoreCallingIdentity(callingIdentity); 567d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 568eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 569eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"Unable to call onServiceUp", e); 570eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 571eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 572d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 573d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 574d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 575d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** 576d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora * Inform BluetoothAdapter instances that BREDR part is down 577d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora * and turn off all service and stack if no LE app needs it 578d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora */ 579d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void sendBrEdrDownCallback() { 58067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); 581bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora 582eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth == null) { 58367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Bluetooth handle is null"); 584bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora return; 585bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora } 586d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 587d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (isBleAppPresent() == false) { 588d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 589eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 590eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) mBluetooth.onBrEdrDown(); 591eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 59267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Call to onBrEdrDown() failed.", e); 593eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 594eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 595d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 596bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora } else { 597bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora // Need to stay at BLE ON. Disconnect all Gatt connections 598eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 599bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora mBluetoothGatt.unregAll(); 600eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 60167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect all apps.", e); 602d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 603d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 604d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 605d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 606fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta public boolean enableNoAutoConnect() 607fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta { 608fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 609fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta "Need BLUETOOTH ADMIN permission"); 61040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 611fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (DBG) { 61267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 613fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta " mBinding = " + mBinding); 614fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6158385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 6168385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 6178385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen if (callingAppId != Process.NFC_UID) { 618fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta throw new SecurityException("no permission to enable Bluetooth quietly"); 619fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6208385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 621401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 622401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = true; 623401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 624401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(true); 625401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 626fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta return true; 627fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6284bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 6290f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean enable() { 6306eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 6316eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 63267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"enable(): not allowed for non-active and non system user"); 63340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 634f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 635f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 636401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 637401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu "Need BLUETOOTH ADMIN permission"); 638401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (DBG) { 63967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + 640090bf551308e68b1b2a996c959b608cabd025c5cSanket Agarwal " mBinding = " + mBinding + " mState = " + mState); 641090bf551308e68b1b2a996c959b608cabd025c5cSanket Agarwal } 642401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 643401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 644401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 645401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 646401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // waive WRITE_SECURE_SETTINGS permission check 647401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(false); 648401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 64967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "enable returning"); 650401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return true; 6510f42037eb7b5118015c2caca635538324ccf0ccffredc } 6520f42037eb7b5118015c2caca635538324ccf0ccffredc 6530f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean disable(boolean persist) { 6540f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 6550f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 65640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 6576eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 6586eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 65967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"disable(): not allowed for non-active and non system user"); 66040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 66140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 66240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 663f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 66467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + 665cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 666cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 667f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 668401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 669401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (persist) { 670401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // waive WRITE_SECURE_SETTINGS permission check 671401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 672401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_OFF); 673401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Binder.restoreCallingIdentity(callingIdentity); 674401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 675401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 676401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendDisableMsg(); 677401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 6780f42037eb7b5118015c2caca635538324ccf0ccffredc return true; 6790f42037eb7b5118015c2caca635538324ccf0ccffredc } 6800f42037eb7b5118015c2caca635538324ccf0ccffredc 681649fe497cea2f19e937f84218d1080bdcefe47f2fredc public void unbindAndFinish() { 682f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 68367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + 684cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 685f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 686f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 687eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 688eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 6890f42037eb7b5118015c2caca635538324ccf0ccffredc if (mUnbinding) return; 6900f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = true; 691e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 69240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 693305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach //Unregister callback object 694305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 695305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mBluetooth.unregisterCallback(mBluetoothCallback); 696305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException re) { 69767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to unregister BluetoothCallback",re); 698bf072a712f584ae1c01022835b0de21c40513d06fredc } 699305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach 70067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Sending unbind request."); 7019db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = null; 702d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mBluetooth = null; 703d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc //Unbind 7040f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.unbindService(mConnection); 705d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mUnbinding = false; 70640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = false; 707f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } else { 708f24588615efa6c781ad963f1a5bbdf47359e1b53fredc mUnbinding=false; 7090f42037eb7b5118015c2caca635538324ccf0ccffredc } 710d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetoothGatt = null; 711eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 712eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 7130f42037eb7b5118015c2caca635538324ccf0ccffredc } 7140f42037eb7b5118015c2caca635538324ccf0ccffredc } 7150f42037eb7b5118015c2caca635538324ccf0ccffredc 716ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public IBluetoothGatt getBluetoothGatt() { 717ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // sync protection 718ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return mBluetoothGatt; 719ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 720ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 721e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 722e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public boolean bindBluetoothProfileService(int bluetoothProfile, 723e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy) { 724e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (!mEnable) { 725e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 72667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 727e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ", while Bluetooth was disabled"); 728e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 729e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return false; 730e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 731e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 732e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 733e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 734e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 73567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Creating new ProfileServiceConnections object for" 736e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " profile: " + bluetoothProfile); 737e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 7385b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 7395b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 7405b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 7415b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz Intent intent = new Intent(IBluetoothHeadset.class.getName()); 742e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc = new ProfileServiceConnections(intent); 7435b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (!psc.bindService()) return false; 7445b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 745e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProfileServices.put(new Integer(bluetoothProfile), psc); 746e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 747e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 748e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 749e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Introducing a delay to give the client app time to prepare 750e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 751e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz addProxyMsg.arg1 = bluetoothProfile; 752e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz addProxyMsg.obj = proxy; 753e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 754e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return true; 755e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 756e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 757e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 758e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void unbindBluetoothProfileService(int bluetoothProfile, 759e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy) { 760e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 761e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 762e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 763e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return; 764e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 765e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.removeProxy(proxy); 766e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 767e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 768e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 769e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void unbindAllBluetoothProfileServices() { 770e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 771e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz for (Integer i : mProfileServices.keySet()) { 772e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(i); 7735b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz try { 7745b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz mContext.unbindService(psc); 7755b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz } catch (IllegalArgumentException e) { 77667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 7775b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz } 778e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.removeAllProxies(); 779e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 780e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProfileServices.clear(); 781e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 782e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 783e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 784e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz /** 785658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * Send enable message and set adapter name and address. Called when the boot phase becomes 786658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * PHASE_SYSTEM_SERVICES_READY. 787658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou */ 788658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou public void handleOnBootPhase() { 78967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth boot completed"); 790658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 79167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); 792658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou sendEnableMsg(mQuietEnableExternal); 793bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker } else if (!isNameAndAddressSet()) { 794bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker if (DBG) Slog.d(TAG, "Getting adapter name and address"); 7954bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 7964bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessage(getMsg); 797658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 798658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 799658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 800658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou /** 801658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * Called when switching to a different foreground user. 802658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou */ 803658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou public void handleOnSwitchUser(int userHandle) { 804aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); 805aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 806aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 807aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 808aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey /** 809aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey * Called when user is unlocked. 810aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey */ 811aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey public void handleOnUnlockUser(int userHandle) { 812aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); 813aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 814658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 815658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 816658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou /** 817e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz * This class manages the clients connected to a given ProfileService 818e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz * and maintains the connection with that service. 819e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz */ 820e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz final private class ProfileServiceConnections implements ServiceConnection, 821e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBinder.DeathRecipient { 822e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 823e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 824e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBinder mService; 825e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ComponentName mClassName; 826e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Intent mIntent; 8273bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach boolean mInvokingProxyCallbacks = false; 828e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 829e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections(Intent intent) { 830e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = null; 831e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = null; 832e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mIntent = intent; 833e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 834e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 8355b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz private boolean bindService() { 8365b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (mIntent != null && mService == null && 8375b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 838e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 839e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 840e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 8415b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz return true; 842e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 84367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Unable to bind with intent: " + mIntent); 8445b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz return false; 845e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 846e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 847e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void addProxy(IBluetoothProfileServiceConnection proxy) { 848e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProxies.register(proxy); 849e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mService != null) { 850e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try{ 851e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz proxy.onServiceConnected(mClassName, mService); 852e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 85367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to connect to proxy", e); 854e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 855e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } else { 856e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 857e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 858e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 859e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessage(msg); 860e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 861e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 862e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 863e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 864e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void removeProxy(IBluetoothProfileServiceConnection proxy) { 865e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (proxy != null) { 866e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mProxies.unregister(proxy)) { 867e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 868e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz proxy.onServiceDisconnected(mClassName); 869e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 87067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect proxy", e); 871e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 872e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 873e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } else { 87467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Trying to remove a null proxy"); 875e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 876e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 877e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 878e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void removeAllProxies() { 879e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz onServiceDisconnected(mClassName); 880e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProxies.kill(); 881e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 882e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 883e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 884e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void onServiceConnected(ComponentName className, IBinder service) { 885e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // remove timeout message 886e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 887e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = service; 888e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = className; 889e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 890e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService.linkToDeath(this, 0); 891e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 89267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to linkToDeath", e); 893e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 8943bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 8953bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mInvokingProxyCallbacks) { 89667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Proxy callbacks already in progress."); 8973bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach return; 8983bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 8993bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = true; 9003bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 9013bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach final int n = mProxies.beginBroadcast(); 9023bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9033bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i = 0; i < n; i++) { 9043bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9053bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.getBroadcastItem(i).onServiceConnected(className, service); 9063bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 90767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to connect to proxy", e); 9083bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 909e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 9103bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 9113bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.finishBroadcast(); 9123bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = false; 913e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 914e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 915e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 916e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 917e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void onServiceDisconnected(ComponentName className) { 9183bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mService == null) return; 919e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService.unlinkToDeath(this, 0); 920e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = null; 921e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = null; 9223bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 9233bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mInvokingProxyCallbacks) { 92467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Proxy callbacks already in progress."); 9253bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach return; 9263bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 9273bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = true; 9283bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 9293bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach final int n = mProxies.beginBroadcast(); 9303bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9313bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i = 0; i < n; i++) { 9323bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9333bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.getBroadcastItem(i).onServiceDisconnected(className); 9343bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 93567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect from proxy", e); 9363bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 937e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 9383bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 9393bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.finishBroadcast(); 9403bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = false; 941e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 942e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 943e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 944e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 945e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void binderDied() { 946e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 94767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Profile service for profile: " + mClassName 948e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " died."); 949e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 950e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz onServiceDisconnected(mClassName); 951e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Trigger rebind 952e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 953e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 954e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 955e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 956e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 957e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 958bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothStateCallback(boolean isUp) { 9593bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9603bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach int n = mStateChangeCallbacks.beginBroadcast(); 96167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 9623bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i=0; i <n;i++) { 9633bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9643bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 9653bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 96667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 9673bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 968bf072a712f584ae1c01022835b0de21c40513d06fredc } 9693bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 9703bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mStateChangeCallbacks.finishBroadcast(); 971bf072a712f584ae1c01022835b0de21c40513d06fredc } 972bf072a712f584ae1c01022835b0de21c40513d06fredc } 973bf072a712f584ae1c01022835b0de21c40513d06fredc 974bf072a712f584ae1c01022835b0de21c40513d06fredc /** 97540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * Inform BluetoothAdapter instances that Adapter service is up 97640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 97740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void sendBluetoothServiceUpCallback() { 97867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); 979305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 980305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach int n = mCallbacks.beginBroadcast(); 98167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 982305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach for (int i=0; i <n;i++) { 983305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 984305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 985305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException e) { 98667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 98740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 98840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 989305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } finally { 990305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.finishBroadcast(); 99140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 99240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 99340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 994bf072a712f584ae1c01022835b0de21c40513d06fredc * Inform BluetoothAdapter instances that Adapter service is down 995bf072a712f584ae1c01022835b0de21c40513d06fredc */ 996bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothServiceDownCallback() { 99767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); 998305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 999305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach int n = mCallbacks.beginBroadcast(); 100067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1001305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach for (int i=0; i <n;i++) { 1002305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 1003305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1004305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException e) { 100567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1006d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1007d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1008305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } finally { 1009305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.finishBroadcast(); 1010d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1011d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1012408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov 10130f42037eb7b5118015c2caca635538324ccf0ccffredc public String getAddress() { 1014af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1015408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov "Need BLUETOOTH permission"); 101640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 10176eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1018408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov (!checkIfCallerIsForegroundUser())) { 101967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"getAddress(): not allowed for non-active and non system user"); 10206eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 102140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 102240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1023408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1024408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov != PackageManager.PERMISSION_GRANTED) { 1025408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1026408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov } 1027408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov 1028eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1029eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1030eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.getAddress(); 1031eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1032eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); 1033eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1034eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1035116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 1036bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker 1037cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mAddress is accessed from outside. 1038cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It is alright without a lock. Here, bluetooth is off, no other thread is 1039cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mAddress 10400f42037eb7b5118015c2caca635538324ccf0ccffredc return mAddress; 10410f42037eb7b5118015c2caca635538324ccf0ccffredc } 1042649fe497cea2f19e937f84218d1080bdcefe47f2fredc 10430f42037eb7b5118015c2caca635538324ccf0ccffredc public String getName() { 1044af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1045af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie "Need BLUETOOTH permission"); 104640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 10476eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 10486eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 104967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"getName(): not allowed for non-active and non system user"); 10506eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 105140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 105240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1053eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1054eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1055eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.getName(); 1056eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1057eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1058eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1059eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1060116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 1061eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1062cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mName is accessed from outside. 1063cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It alright without a lock. Here, bluetooth is off, no other thread is 1064cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mName 10650f42037eb7b5118015c2caca635538324ccf0ccffredc return mName; 10660f42037eb7b5118015c2caca635538324ccf0ccffredc } 10670f42037eb7b5118015c2caca635538324ccf0ccffredc 10680f42037eb7b5118015c2caca635538324ccf0ccffredc private class BluetoothServiceConnection implements ServiceConnection { 10690f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceConnected(ComponentName className, IBinder service) { 107067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 10710f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1072ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 1073ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1074ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 1075ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 1076ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1077ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 1078ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 107967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unknown service connected: " + className.getClassName()); 1080ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 1081ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 10820f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = service; 10830f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 10840f42037eb7b5118015c2caca635538324ccf0ccffredc } 10850f42037eb7b5118015c2caca635538324ccf0ccffredc 10860f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceDisconnected(ComponentName className) { 10870f42037eb7b5118015c2caca635538324ccf0ccffredc // Called if we unexpected disconnected. 108867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + 1089ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie className.getClassName()); 10900f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1091ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 1092ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 1093ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 1094ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 1095ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 109667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); 1097ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 1098ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 10990f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 11000f42037eb7b5118015c2caca635538324ccf0ccffredc } 11010f42037eb7b5118015c2caca635538324ccf0ccffredc } 11020f42037eb7b5118015c2caca635538324ccf0ccffredc 11030f42037eb7b5118015c2caca635538324ccf0ccffredc private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 11040f42037eb7b5118015c2caca635538324ccf0ccffredc 110540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private class BluetoothHandler extends Handler { 11064bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker boolean mGetNameAddressOnly = false; 11074bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 110840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu public BluetoothHandler(Looper looper) { 110940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu super(looper); 111040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 111140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 11120f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 11130f42037eb7b5118015c2caca635538324ccf0ccffredc public void handleMessage(Message msg) { 111467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d (TAG, "Message: " + msg.what); 11150f42037eb7b5118015c2caca635538324ccf0ccffredc switch (msg.what) { 11164bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker case MESSAGE_GET_NAME_AND_ADDRESS: 11174bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1118eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1119eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 11204bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if ((mBluetooth == null) && (!mBinding)) { 11214bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (DBG) Slog.d(TAG, "Binding to service to get name and address"); 11224bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mGetNameAddressOnly = true; 11234bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 11244bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 11254bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Intent i = new Intent(IBluetooth.class.getName()); 11264bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (!doBind(i, mConnection, 11274bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 11284bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker UserHandle.CURRENT)) { 11294bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 11304bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } else { 11314bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mBinding = true; 11324bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 11334bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } else if (mBluetooth != null) { 11344bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker try { 11354bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker storeNameAndAddress(mBluetooth.getName(), 11364bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mBluetooth.getAddress()); 11374bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } catch (RemoteException re) { 11384bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Slog.e(TAG, "Unable to grab names", re); 11394bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 11404bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (mGetNameAddressOnly && !mEnable) { 11414bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker unbindAndFinish(); 11424bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 11434bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mGetNameAddressOnly = false; 11444bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 1145eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1146eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 11474bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 11484bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker break; 11494bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 1150cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_ENABLE: 1151f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 115267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 1153649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 115440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 115540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 1156e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov if (mBluetooth == null) { 1157e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov handleEnable(msg.arg1 == 1); 1158e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov } else { 1159e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // 1160e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // We need to wait until transitioned to STATE_OFF and 1161e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // the previous Bluetooth process has exited. The 1162e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // waiting period has three components: 1163e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (a) Wait until the local state is STATE_OFF. This 1164e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // is accomplished by "waitForOnOff(false, true)". 1165e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (b) Wait until the STATE_OFF state is updated to 1166e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // all components. 1167e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (c) Wait until the Bluetooth process exits, and 1168e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // ActivityManager detects it. 1169e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // The waiting for (b) and (c) is accomplished by 1170e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 1171e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // message. On slower devices, that delay needs to be 1172e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // on the order of (2 * SERVICE_RESTART_TIME_MS). 1173e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // 1174e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov waitForOnOff(false, true); 1175e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov mQuietEnable = (msg.arg1 == 1); 1176e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov Message restartMsg = mHandler.obtainMessage( 1177e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov MESSAGE_RESTART_BLUETOOTH_SERVICE); 1178e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov mHandler.sendMessageDelayed(restartMsg, 1179e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov 2 * SERVICE_RESTART_TIME_MS); 1180e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov } 1181649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 11820f42037eb7b5118015c2caca635538324ccf0ccffredc 1183cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_DISABLE: 118440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 118540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 118640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 118740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 1188401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 118940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 119040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 119140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 1192401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 119340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 11940f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1195cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 11960f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_ADAPTER: 11970f42037eb7b5118015c2caca635538324ccf0ccffredc { 11980f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1199d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc boolean added = mCallbacks.register(callback); 120067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 12010f42037eb7b5118015c2caca635538324ccf0ccffredc } 12020f42037eb7b5118015c2caca635538324ccf0ccffredc break; 12030f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_ADAPTER: 12040f42037eb7b5118015c2caca635538324ccf0ccffredc { 12050f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1206d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc boolean removed = mCallbacks.unregister(callback); 120767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 12080f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1209cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 12100f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 12110f42037eb7b5118015c2caca635538324ccf0ccffredc { 12120f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 12139b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (callback != null) { 12149b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mStateChangeCallbacks.register(callback); 12159b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 12160f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1217cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 12180f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 12190f42037eb7b5118015c2caca635538324ccf0ccffredc { 12200f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 12219b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (callback != null) { 12229b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mStateChangeCallbacks.unregister(callback); 12239b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 12240f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1225cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1226e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_ADD_PROXY_DELAYED: 1227e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz { 1228e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get( 1229e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new Integer(msg.arg1)); 1230e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 1231e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1232e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1233e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy = 1234e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz (IBluetoothProfileServiceConnection) msg.obj; 1235e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.addProxy(proxy); 1236e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1237e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1238e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_BIND_PROFILE_SERVICE: 1239e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz { 1240e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1241e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1242e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 1243e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1244e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1245e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.bindService(); 1246e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1247e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 12480f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 12490f42037eb7b5118015c2caca635538324ccf0ccffredc { 125067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 12510f42037eb7b5118015c2caca635538324ccf0ccffredc 12520f42037eb7b5118015c2caca635538324ccf0ccffredc IBinder service = (IBinder) msg.obj; 1253eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1254eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1255ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1256ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1257d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora onBluetoothGattServiceUp(); 1258ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1259ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } // else must be SERVICE_IBLUETOOTH 1260ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 1261ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie //Remove timeout 1262af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1263ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 12640f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 12659db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = service; 12660f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = IBluetooth.Stub.asInterface(service); 12670f42037eb7b5118015c2caca635538324ccf0ccffredc 12684bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (!isNameAndAddressSet()) { 12694bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 12704bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessage(getMsg); 12714bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (mGetNameAddressOnly) return; 12724bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 12734bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 1274af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu try { 1275af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1276af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1277af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 127867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1279af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 1280af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } catch (RemoteException e) { 128167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call configHciSnoopLog", e); 1282af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 1283af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu 1284cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Register callback object 1285cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1286cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mBluetooth.registerCallback(mBluetoothCallback); 1287cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException re) { 128867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to register BluetoothCallback",re); 1289cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1290cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Inform BluetoothAdapter instances that service is up 129140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceUpCallback(); 129240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1293cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Do enable request 1294bf072a712f584ae1c01022835b0de21c40513d06fredc try { 1295fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (mQuietEnable == false) { 1296fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enable()) { 129767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enable() returned false"); 1298fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1299fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1300fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta else 1301fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta { 1302fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enableNoAutoConnect()) { 130367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1304fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1305cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1306bf072a712f584ae1c01022835b0de21c40513d06fredc } catch (RemoteException e) { 130767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call enable()",e); 13080f42037eb7b5118015c2caca635538324ccf0ccffredc } 1309eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1310eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1311bf072a712f584ae1c01022835b0de21c40513d06fredc } 131240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 131340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mEnable) { 131440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 1315401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 131640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 131740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1318649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1319cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1320649fe497cea2f19e937f84218d1080bdcefe47f2fredc case MESSAGE_TIMEOUT_BIND: { 132167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1322eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1323eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBinding = false; 1324eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1325eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1326649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1327cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1328bf072a712f584ae1c01022835b0de21c40513d06fredc case MESSAGE_BLUETOOTH_STATE_CHANGE: 13290f42037eb7b5118015c2caca635538324ccf0ccffredc { 1330bf072a712f584ae1c01022835b0de21c40513d06fredc int prevState = msg.arg1; 1331bf072a712f584ae1c01022835b0de21c40513d06fredc int newState = msg.arg2; 133267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 133340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = newState; 133440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu bluetoothStateChangeHandler(prevState, newState); 1335dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // handle error state transition case from TURNING_ON to OFF 1336dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // unbind and rebind bluetooth service and enable bluetooth 1337d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && 1338dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu (newState == BluetoothAdapter.STATE_OFF) && 1339dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu (mBluetooth != null) && mEnable) { 1340dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu recoverBluetoothServiceFromError(); 1341dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1342d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1343d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora (newState == BluetoothAdapter.STATE_BLE_ON) && 1344d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora (mBluetooth != null) && mEnable) { 1345d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora recoverBluetoothServiceFromError(); 1346d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1347d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (newState == BluetoothAdapter.STATE_ON || 1348d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora newState == BluetoothAdapter.STATE_BLE_ON) { 1349dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // bluetooth is working, reset the counter 1350dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter != 0) { 135167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "bluetooth is recovered from error"); 1352dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 1353dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1354dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1355649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1356cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 13570f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 13580f42037eb7b5118015c2caca635538324ccf0ccffredc { 135967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 1360eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1361eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1362ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTH) { 1363ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // if service is unbinded already, do nothing and return 1364ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mBluetooth == null) break; 1365ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetooth = null; 1366ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1367ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = null; 1368ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1369ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 137067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); 1371ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1372ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 1373eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1374eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 13751223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 137640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 137740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable) { 137840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 137940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // Send a Bluetooth Restart message 138040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message restartMsg = mHandler.obtainMessage( 138140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 138240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(restartMsg, 138340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SERVICE_RESTART_TIME_MS); 138440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 138540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1386305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach sendBluetoothServiceDownCallback(); 138740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1388305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach // Send BT state broadcast to update 1389305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach // the BT icon correctly 1390305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1391305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach (mState == BluetoothAdapter.STATE_ON)) { 1392305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1393305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach BluetoothAdapter.STATE_TURNING_OFF); 1394305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mState = BluetoothAdapter.STATE_TURNING_OFF; 139540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1396305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1397305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1398305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach BluetoothAdapter.STATE_OFF); 1399305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } 1400305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach 1401305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1402305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mState = BluetoothAdapter.STATE_OFF; 1403649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1404cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 14051223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M case MESSAGE_RESTART_BLUETOOTH_SERVICE: 14061223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M { 140767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 14081223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M +" Restart IBluetooth service"); 14091223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M /* Enable without persisting the setting as 14101223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M it doesnt change when IBluetooth 14111223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M service restarts */ 141240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 1413401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 14141223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M break; 14151223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 14161223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M 14170f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_TIMEOUT_UNBIND: 14180f42037eb7b5118015c2caca635538324ccf0ccffredc { 141967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1420eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1421eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mUnbinding = false; 1422eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1423649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1424cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 142540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1426aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey case MESSAGE_USER_SWITCHED: { 1427aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 142840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1429aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 143040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /* disable and enable BT when detect a user switch */ 143140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 1432eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1433eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 143440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 1435eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetooth.unregisterCallback(mBluetoothCallback); 143640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1437eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException re) { 1438eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to unregister", re); 1439eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1440eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 144140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 14424e22ad35045dc5861193526afe1565d52f983698Zhihai Xu 14434e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 14444e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 14454e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 14464e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 14474e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 14484e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_OFF) { 14494e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 14504e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_TURNING_ON; 14514e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 145240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 145340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 145440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 14554e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_ON) { 14564e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 14574e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 145840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1459e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz unbindAllBluetoothProfileServices(); 146040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // disable 1461401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 14624e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // Pbap service need receive STATE_TURNING_OFF intent to close 14634e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 14644e22ad35045dc5861193526afe1565d52f983698Zhihai Xu BluetoothAdapter.STATE_TURNING_OFF); 146540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 146640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, true); 146740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 14684e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 146940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu BluetoothAdapter.STATE_OFF); 147040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceDownCallback(); 1471eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1472e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov try { 1473e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1474e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov if (mBluetooth != null) { 1475e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetooth = null; 1476e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov // Unbind 1477e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mContext.unbindService(mConnection); 1478e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } 1479e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothGatt = null; 1480e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } finally { 1481e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 148240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1483eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 148440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(100); 148540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 14864e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 14874e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 148840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // enable 1489401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 14908a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } else if (mBinding || mBluetooth != null) { 149140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 149240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu userMsg.arg2 = 1 + msg.arg2; 149340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // if user is switched when service is being binding 149440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // delay sending MESSAGE_USER_SWITCHED 149540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 149640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 149767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 149840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 14998a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } 150040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu break; 150140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1502aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey case MESSAGE_USER_UNLOCKED: { 1503aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1504aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1505aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 1506eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mEnable && !mBinding && (mBluetooth == null)) { 1507eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // We should be connected, but we gave up for some 1508eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // reason; maybe the Bluetooth service wasn't encryption 1509eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // aware, so try binding again. 1510eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1511eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov handleEnable(mQuietEnable); 1512aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 1513aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 15140f42037eb7b5118015c2caca635538324ccf0ccffredc } 15150f42037eb7b5118015c2caca635538324ccf0ccffredc } 151640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1517cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1518401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleEnable(boolean quietMode) { 1519fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mQuietEnable = quietMode; 1520fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta 1521eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1522eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 152340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if ((mBluetooth == null) && (!mBinding)) { 1524cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Start bind timeout and bind 1525cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1526cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1527cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Intent i = new Intent(IBluetooth.class.getName()); 1528ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1529ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn UserHandle.CURRENT)) { 1530cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 153140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 153240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = true; 1533cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 153440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else if (mBluetooth != null) { 1535cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Enable bluetooth 1536cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1537fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (!mQuietEnable) { 1538fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enable()) { 153967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enable() returned false"); 1540fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1541fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1542fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta else { 1543fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enableNoAutoConnect()) { 154467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1545fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1546cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1547cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException e) { 154867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call enable()",e); 1549cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1550cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1551eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1552eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1553cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1554cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1555cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1556221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1557221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1558221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn intent.setComponent(comp); 1559221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 156067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Fail to bind to: " + intent); 1561221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return false; 1562221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1563221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return true; 1564221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1565221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 1566401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleDisable() { 1567eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1568eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1569305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if (mBluetooth != null) { 157067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Sending off request."); 1571eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (!mBluetooth.disable()) { 1572eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"IBluetooth.disable() returned false"); 1573cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1574cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1575eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1576eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"Unable to call disable()",e); 1577eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1578eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1579cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1580cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 158140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 158240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean checkIfCallerIsForegroundUser() { 158340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int foregroundUser; 158440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int callingUser = UserHandle.getCallingUserId(); 15858385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingUid = Binder.getCallingUid(); 158640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 1587e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1588e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz UserInfo ui = um.getProfileParent(callingUser); 1589e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 15908385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(callingUid); 159140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu boolean valid = false; 159240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 159340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu foregroundUser = ActivityManager.getCurrentUser(); 15948385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen valid = (callingUser == foregroundUser) || 1595e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz parentUser == foregroundUser || 1596bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos callingAppId == Process.NFC_UID || 1597bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos callingAppId == mSystemUiUid; 159840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 159967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 160040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " callingUser=" + callingUser 1601e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " parentUser=" + parentUser 160240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " foregroundUser=" + foregroundUser); 160340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 160440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } finally { 160540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Binder.restoreCallingIdentity(callingIdentity); 160640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 160740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return valid; 160840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 160940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1610d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void sendBleStateChanged(int prevState, int newState) { 161167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); 1612d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Send broadcast message to everyone else 1613d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 1614d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1615d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1616d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1617d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1618d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1619d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 162040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void bluetoothStateChangeHandler(int prevState, int newState) { 1621d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora boolean isStandardBroadcast = true; 162240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (prevState != newState) { 162340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Notify all proxy objects first of adapter state change 1624d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (newState == BluetoothAdapter.STATE_BLE_ON 1625d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora || newState == BluetoothAdapter.STATE_OFF) { 1626d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 1627d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora && newState == BluetoothAdapter.STATE_BLE_ON); 1628d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1629d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (newState == BluetoothAdapter.STATE_OFF) { 1630d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // If Bluetooth is off, send service down event to proxy objects, and unbind 163167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); 1632e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov sendBluetoothServiceDownCallback(); 1633e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov unbindAndFinish(); 1634e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov sendBleStateChanged(prevState, newState); 1635e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // Don't broadcast as it has already been broadcast before 1636e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov isStandardBroadcast = false; 1637d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1638d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (!intermediate_off) { 1639d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // connect to GattService 164067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); 1641d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBluetoothGatt != null) { 164267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); 1643d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora onBluetoothGattServiceUp(); 1644d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else { 164567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); 1646d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mContext.getPackageManager().hasSystemFeature( 1647d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora PackageManager.FEATURE_BLUETOOTH_LE)) { 1648d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Intent i = new Intent(IBluetoothGatt.class.getName()); 1649d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); 1650d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1651d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1652d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1653d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora //Don't broadcase this as std intent 1654d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora isStandardBroadcast = false; 1655d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1656d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (intermediate_off){ 165767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); 1658d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // For LE only mode, broadcast as is 1659d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1660d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBluetoothStateCallback(false); // BT is OFF for general users 1661d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Broadcast as STATE_OFF 1662d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora newState = BluetoothAdapter.STATE_OFF; 1663d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBrEdrDownCallback(); 166440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1665d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (newState == BluetoothAdapter.STATE_ON) { 1666d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora boolean isUp = (newState==BluetoothAdapter.STATE_ON); 1667d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBluetoothStateCallback(isUp); 1668d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1669d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1670d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON 1671d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { 1672d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1673d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora isStandardBroadcast = false; 1674d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1675d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (newState == BluetoothAdapter.STATE_TURNING_ON 1676d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora || newState == BluetoothAdapter.STATE_TURNING_OFF) { 1677d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 167840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 167940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1680d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (isStandardBroadcast) { 1681d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (prevState == BluetoothAdapter.STATE_BLE_ON) { 1682d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Show prevState of BLE_ON as OFF to standard users 1683d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora prevState = BluetoothAdapter.STATE_OFF; 1684d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1685d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1686d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1687d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1688d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1689d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1690d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 169140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 169240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 169340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 169440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 169540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if on is true, wait for state become ON 169640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if off is true, wait for state become OFF 169740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if both on and off are false, wait for state not ON 169840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 169940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean waitForOnOff(boolean on, boolean off) { 170040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int i = 0; 170140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu while (i < 10) { 1702eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1703eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1704eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth == null) break; 1705eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (on) { 1706eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1707eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } else if (off) { 1708eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1709eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } else { 1710eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 171140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1712eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1713eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getState()", e); 1714eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov break; 1715eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1716eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 171740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 171840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (on || off) { 171940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(300); 1720665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } else { 172140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(50); 1722665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } 172340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu i++; 172440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 172567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"waitForOnOff time out"); 172640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 172740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1728681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu 1729401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendDisableMsg() { 1730401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1731401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1732401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 1733401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendEnableMsg(boolean quietMode) { 1734401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1735401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu quietMode ? 1 : 0, 0)); 1736401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1737401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 1738dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private void recoverBluetoothServiceFromError() { 173967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"recoverBluetoothServiceFromError"); 1740eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1741eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1742dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mBluetooth != null) { 1743dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Unregister callback object 1744eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetooth.unregisterCallback(mBluetoothCallback); 1745dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1746eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException re) { 1747eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to unregister", re); 1748eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1749eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1750dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1751dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1752dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu SystemClock.sleep(500); 1753dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1754dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // disable 1755dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu handleDisable(); 1756dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1757dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu waitForOnOff(false, true); 1758dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1759dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu sendBluetoothServiceDownCallback(); 1760eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1761e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov try { 1762e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1763e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov if (mBluetooth != null) { 1764e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetooth = null; 1765e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov // Unbind 1766e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mContext.unbindService(mConnection); 1767e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } 1768e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothGatt = null; 1769e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } finally { 1770e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1771dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1772dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1773dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1774dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mState = BluetoothAdapter.STATE_OFF; 1775dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1776dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mEnable = false; 1777dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1778dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1779dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // Send a Bluetooth Restart message to reenable bluetooth 1780dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Message restartMsg = mHandler.obtainMessage( 1781dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 1782dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1783dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } else { 1784dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // todo: notify user to power down and power up phone to make bluetooth work. 1785dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1786dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1787726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood 1788726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood @Override 17896e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 17906e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 17916e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov String errorMsg = null; 17926e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if (mBluetoothBinder == null) { 17936e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov errorMsg = "Bluetooth Service not connected"; 17946e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } else { 17956e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov try { 17966e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov mBluetoothBinder.dump(fd, args); 17976e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } catch (RemoteException re) { 17986e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov errorMsg = "RemoteException while calling Bluetooth Service"; 17996e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } 18006e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } 18016e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if (errorMsg != null) { 18026e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov // Silently return if we are extracting metrics in Protobuf format 18036e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if ((args.length > 0) && args[0].startsWith("--proto")) 18046e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov return; 18056e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov writer.println(errorMsg); 1806726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood } 1807726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood } 18080f42037eb7b5118015c2caca635538324ccf0ccffredc} 1809