BluetoothManagerService.java revision fa63068deb3b42b1907c0c2214204e2f4e31bd0c
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; 38b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganovimport android.content.pm.ApplicationInfo; 3932ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xieimport android.content.pm.PackageManager; 40e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.content.pm.UserInfo; 41e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wangimport android.database.ContentObserver; 4240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Binder; 43b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganovimport android.os.Build; 440f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Handler; 450f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.IBinder; 4640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Looper; 470f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Message; 4840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Process; 49d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredcimport android.os.RemoteCallbackList; 500f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.RemoteException; 5140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.SystemClock; 525ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 53e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.UserManager; 540f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.provider.Settings; 5567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wangimport android.provider.Settings.SettingNotFoundException; 5667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkeyimport android.util.Slog; 57eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavovimport java.util.concurrent.locks.ReentrantReadWriteLock; 58726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood 59726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.FileDescriptor; 60726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.PrintWriter; 616689f33436140959097a4479f2622047952b0341Marie Janssenimport java.util.concurrent.ConcurrentHashMap; 62e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.HashMap; 63e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.Map; 64658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 650f42037eb7b5118015c2caca635538324ccf0ccffredcclass BluetoothManagerService extends IBluetoothManager.Stub { 660f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String TAG = "BluetoothManagerService"; 67414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov private static final boolean DBG = true; 680f42037eb7b5118015c2caca635538324ccf0ccffredc 690f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 700f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 710f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 720f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String EXTRA_ACTION="action"; 73d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 740f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 750f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 760f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 770f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 781223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M //Maximum msec to wait for service restart 791223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int SERVICE_RESTART_TIME_MS = 200; 80dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Maximum msec to wait for restart due to error 81dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private static final int ERROR_RESTART_TIME_MS = 3000; 8240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Maximum msec to delay MESSAGE_USER_SWITCHED 8340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int USER_SWITCHED_TIME_MS = 200; 84e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Delay for the addProxy function in msec 85e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int ADD_PROXY_DELAY_MS = 100; 860f42037eb7b5118015c2caca635538324ccf0ccffredc 870f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_ENABLE = 1; 880f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_DISABLE = 2; 89649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_ADAPTER = 20; 90649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 91649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 92649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 93649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 94649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 951223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 96aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; 97aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_TIMEOUT_BIND = 100; 98aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_TIMEOUT_UNBIND = 101; 994bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; 10040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int MESSAGE_USER_SWITCHED = 300; 101aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MESSAGE_USER_UNLOCKED = 301; 102e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 103e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 104ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen 105aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MAX_SAVE_RETRIES = 3; 106aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey private static final int MAX_ERROR_RESTART_RETRIES = 6; 107dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 108401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is off 109401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_OFF=0; 110401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 111401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode won't affect Bluetooth state at start up 112401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_BLUETOOTH=1; 113401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 114401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // but Airplane mode will affect Bluetooth state at start up 115401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode will have higher priority. 116401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_AIRPLANE=2; 1170f42037eb7b5118015c2caca635538324ccf0ccffredc 118ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTH = 1; 119ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTHGATT = 2; 120ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 1210f42037eb7b5118015c2caca635538324ccf0ccffredc private final Context mContext; 122cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 123cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // Locks are not provided for mName and mAddress. 124cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // They are accessed in handler or broadcast receiver, same thread context. 1250f42037eb7b5118015c2caca635538324ccf0ccffredc private String mAddress; 1260f42037eb7b5118015c2caca635538324ccf0ccffredc private String mName; 1276fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final ContentResolver mContentResolver; 1286fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 1296fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 1309db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen private IBinder mBluetoothBinder; 131649fe497cea2f19e937f84218d1080bdcefe47f2fredc private IBluetooth mBluetooth; 132ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private IBluetoothGatt mBluetoothGatt; 133eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov private final ReentrantReadWriteLock mBluetoothLock = 134eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov new ReentrantReadWriteLock(); 135649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mBinding; 136649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mUnbinding; 137401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 138fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta private boolean mQuietEnable = false; 139401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 140401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 141401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mQuietEnableExternal; 142401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 143401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 144401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mEnableExternal; 145401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 14640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean mEnable; 14740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private int mState; 14840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private final BluetoothHandler mHandler; 149dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private int mErrorRecoveryRetryCounter; 150bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos private final int mSystemUiUid; 1510f42037eb7b5118015c2caca635538324ccf0ccffredc 152e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Save a ProfileServiceConnections object for each of the bound 153e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // bluetooth profile services 154e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private final Map <Integer, ProfileServiceConnections> mProfileServices = 155e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new HashMap <Integer, ProfileServiceConnections>(); 156e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 157b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov private final boolean mPermissionReviewRequired; 158b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 159649fe497cea2f19e937f84218d1080bdcefe47f2fredc private void registerForAirplaneMode(IntentFilter filter) { 160649fe497cea2f19e937f84218d1080bdcefe47f2fredc final ContentResolver resolver = mContext.getContentResolver(); 161c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String airplaneModeRadios = Settings.Global.getString(resolver, 162c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_RADIOS); 163c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String toggleableRadios = Settings.Global.getString(resolver, 164c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 165649fe497cea2f19e937f84218d1080bdcefe47f2fredc boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 166c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 167649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (mIsAirplaneSensitive) { 168649fe497cea2f19e937f84218d1080bdcefe47f2fredc filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 169649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 170649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 1710f42037eb7b5118015c2caca635538324ccf0ccffredc 172bf072a712f584ae1c01022835b0de21c40513d06fredc private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 173bf072a712f584ae1c01022835b0de21c40513d06fredc @Override 174bf072a712f584ae1c01022835b0de21c40513d06fredc public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 175bf072a712f584ae1c01022835b0de21c40513d06fredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 176bf072a712f584ae1c01022835b0de21c40513d06fredc mHandler.sendMessage(msg); 177bf072a712f584ae1c01022835b0de21c40513d06fredc } 178bf072a712f584ae1c01022835b0de21c40513d06fredc }; 179bf072a712f584ae1c01022835b0de21c40513d06fredc 180bf072a712f584ae1c01022835b0de21c40513d06fredc private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1810f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 1820f42037eb7b5118015c2caca635538324ccf0ccffredc public void onReceive(Context context, Intent intent) { 1830f42037eb7b5118015c2caca635538324ccf0ccffredc String action = intent.getAction(); 184bf072a712f584ae1c01022835b0de21c40513d06fredc if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 1850f42037eb7b5118015c2caca635538324ccf0ccffredc String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 18667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); 1870f42037eb7b5118015c2caca635538324ccf0ccffredc if (newName != null) { 1880f42037eb7b5118015c2caca635538324ccf0ccffredc storeNameAndAddress(newName, null); 1890f42037eb7b5118015c2caca635538324ccf0ccffredc } 190649fe497cea2f19e937f84218d1080bdcefe47f2fredc } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 191401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 192401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 193401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 194401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 195401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else { 196401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 197401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 198401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 199d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 200d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora int st = BluetoothAdapter.STATE_OFF; 201eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 202eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 203eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) { 204d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora st = mBluetooth.getState(); 205d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 206eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 207eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to call getState", e); 208eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 209eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 210d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 211ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.d(TAG, "State " + BluetoothAdapter.nameForState(st)); 212d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 213401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 214d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Clear registered LE apps to force shut-off 2156689f33436140959097a4479f2622047952b0341Marie Janssen clearBleApps(); 216d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (st == BluetoothAdapter.STATE_BLE_ON) { 217d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora //if state is BLE_ON make sure you trigger disableBLE part 218d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 219eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 220d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (mBluetooth != null) { 221d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetooth.onBrEdrDown(); 222a80d745c656f1e09aa9331002f613883220ca029Marie Janssen mEnable = false; 223d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mEnableExternal = false; 224d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 225eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 22667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call onBrEdrDown", e); 227eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 2287ee53be300573c9bdc71607d32d4a642e4ad3dc8Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 229d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 230d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else if (st == BluetoothAdapter.STATE_ON){ 231d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // disable without persisting the setting 23267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Calling disable"); 233d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendDisableMsg(); 234d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 235401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else if (mEnableExternal) { 236401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // enable without persisting the setting 23767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Calling enable"); 238401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(mQuietEnableExternal); 239401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 240649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 2410f42037eb7b5118015c2caca635538324ccf0ccffredc } 2420f42037eb7b5118015c2caca635538324ccf0ccffredc } 2430f42037eb7b5118015c2caca635538324ccf0ccffredc }; 2440f42037eb7b5118015c2caca635538324ccf0ccffredc 2450f42037eb7b5118015c2caca635538324ccf0ccffredc BluetoothManagerService(Context context) { 2468d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn mHandler = new BluetoothHandler(IoThread.get().getLooper()); 24740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 2480f42037eb7b5118015c2caca635538324ccf0ccffredc mContext = context; 249b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 250b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED 251b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov || context.getResources().getBoolean( 252b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov com.android.internal.R.bool.config_permissionReviewRequired); 253b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 2540f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = null; 2559db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = null; 256d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetoothGatt = null; 2570f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 2580f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = false; 25940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 26040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = BluetoothAdapter.STATE_OFF; 261401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 262401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 2630f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = null; 2640f42037eb7b5118015c2caca635538324ccf0ccffredc mName = null; 265dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 2660f42037eb7b5118015c2caca635538324ccf0ccffredc mContentResolver = context.getContentResolver(); 267e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Observe BLE scan only mode settings change. 268e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang registerForBleScanModeChange(); 269d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 270d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 271658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 2726fde3098074ab2551867d1cd919958383b15725fMatthew Xie registerForAirplaneMode(filter); 273d83a096f299abd9c7fe5e441ef1bb169c314b575Dianne Hackborn filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 2746fde3098074ab2551867d1cd919958383b15725fMatthew Xie mContext.registerReceiver(mReceiver, filter); 2750f42037eb7b5118015c2caca635538324ccf0ccffredc loadStoredNameAndAddress(); 276401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 2779fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); 278401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 2790f42037eb7b5118015c2caca635538324ccf0ccffredc } 280bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos 281bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos int sysUiUid = -1; 282bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos try { 283e06b4d1d9f718b9fe02980fea794a36831a16db2Jeff Sharkey sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", 284c5967e9862489024c932b0c7fcb84ed0af2a7fd7Jeff Sharkey PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); 285bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos } catch (PackageManager.NameNotFoundException e) { 286acddf2b34965da479efe46bd87871234ac6a5aabJoe LaPenna // Some platforms, such as wearables do not have a system ui. 28767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); 288bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos } 289bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos mSystemUiUid = sysUiUid; 2900f42037eb7b5118015c2caca635538324ccf0ccffredc } 2910f42037eb7b5118015c2caca635538324ccf0ccffredc 292649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 293649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if airplane mode is currently on 294649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 295649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isAirplaneModeOn() { 296c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate return Settings.Global.getInt(mContext.getContentResolver(), 297c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 298649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 299649fe497cea2f19e937f84218d1080bdcefe47f2fredc 300649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 301649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth saved state is "on" 302649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 303649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isBluetoothPersistedStateOn() { 3049fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen int state = Settings.Global.getInt(mContentResolver, 3059fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen Settings.Global.BLUETOOTH_ON, -1); 3069fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen if (DBG) Slog.d(TAG, "Bluetooth persisted state: " + state); 3079fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen return state != BLUETOOTH_OFF; 308401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 309401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 310401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu /** 311401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 312401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu */ 313401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private final boolean isBluetoothPersistedStateOnBluetooth() { 314401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return Settings.Global.getInt(mContentResolver, 3158c18431be868e0960e80638c1a974d71a0df05b4Andre Eisenbach Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; 316649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 317649fe497cea2f19e937f84218d1080bdcefe47f2fredc 318649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 319649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth on/off state 320649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 321401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void persistBluetoothSetting(int value) { 3229fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value); 323fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen // waive WRITE_SECURE_SETTINGS permission check 324fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen long callingIdentity = Binder.clearCallingIdentity(); 325bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.putInt(mContext.getContentResolver(), 326bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.BLUETOOTH_ON, 327401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu value); 328fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen Binder.restoreCallingIdentity(callingIdentity); 329649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 330649fe497cea2f19e937f84218d1080bdcefe47f2fredc 331649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 332649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth Adapter's name and address is 333649fe497cea2f19e937f84218d1080bdcefe47f2fredc * locally cached 334649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @return 335649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3360f42037eb7b5118015c2caca635538324ccf0ccffredc private boolean isNameAndAddressSet() { 3370f42037eb7b5118015c2caca635538324ccf0ccffredc return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 3380f42037eb7b5118015c2caca635538324ccf0ccffredc } 3390f42037eb7b5118015c2caca635538324ccf0ccffredc 340649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 341649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Retrieve the Bluetooth Adapter's name and address and save it in 342649fe497cea2f19e937f84218d1080bdcefe47f2fredc * in the local cache 343649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3440f42037eb7b5118015c2caca635538324ccf0ccffredc private void loadStoredNameAndAddress() { 34567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Loading stored name and address"); 346d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (mContext.getResources().getBoolean 347d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu (com.android.internal.R.bool.config_bluetooth_address_validation) && 348d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 349d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu // if the valid flag is not set, don't load the address and name 35067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored"); 351d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu return; 352d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 3530f42037eb7b5118015c2caca635538324ccf0ccffredc mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 3540f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 35567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 3560f42037eb7b5118015c2caca635538324ccf0ccffredc } 3570f42037eb7b5118015c2caca635538324ccf0ccffredc 358649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 359649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth name and address in the persistent store. 360649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Only non-null values will be saved. 361649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param name 362649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param address 363649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 3640f42037eb7b5118015c2caca635538324ccf0ccffredc private void storeNameAndAddress(String name, String address) { 3650f42037eb7b5118015c2caca635538324ccf0ccffredc if (name != null) { 3660f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 3670f42037eb7b5118015c2caca635538324ccf0ccffredc mName = name; 36867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Stored Bluetooth name: " + 369649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 3700f42037eb7b5118015c2caca635538324ccf0ccffredc } 3710f42037eb7b5118015c2caca635538324ccf0ccffredc 3720f42037eb7b5118015c2caca635538324ccf0ccffredc if (address != null) { 3730f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 3740f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress=address; 37567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " + 376649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 3770f42037eb7b5118015c2caca635538324ccf0ccffredc } 378d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu 379d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if ((name != null) && (address != null)) { 380d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 381d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 3820f42037eb7b5118015c2caca635538324ccf0ccffredc } 3830f42037eb7b5118015c2caca635538324ccf0ccffredc 3840f42037eb7b5118015c2caca635538324ccf0ccffredc public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 38555db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 38667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Callback is null in registerAdapter"); 38755db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return null; 38855db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 3890f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 3900f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3910f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 392eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 393eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov return mBluetooth; 3940f42037eb7b5118015c2caca635538324ccf0ccffredc } 3950f42037eb7b5118015c2caca635538324ccf0ccffredc 3960f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterAdapter(IBluetoothManagerCallback callback) { 39755db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 39867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Callback is null in unregisterAdapter"); 39955db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return; 40055db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 4010f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 4020f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 4030f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 4040f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 4050f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 4060f42037eb7b5118015c2caca635538324ccf0ccffredc } 4070f42037eb7b5118015c2caca635538324ccf0ccffredc 4080f42037eb7b5118015c2caca635538324ccf0ccffredc public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 4090f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 4100f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 411ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (callback == null) { 412ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); 413ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen return; 414ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 4150f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 4160f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 4170f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 4180f42037eb7b5118015c2caca635538324ccf0ccffredc } 4190f42037eb7b5118015c2caca635538324ccf0ccffredc 4200f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 4210f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 4220f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 423ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (callback == null) { 424ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); 425ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen return; 426ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 4270f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 4280f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 4290f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 4300f42037eb7b5118015c2caca635538324ccf0ccffredc } 4310f42037eb7b5118015c2caca635538324ccf0ccffredc 4320f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean isEnabled() { 4336eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 4346eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 43567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user"); 43640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 43740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 43840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 439eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 440eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 441eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.isEnabled(); 442eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 443eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "isEnabled()", e); 444eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 445eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 4460f42037eb7b5118015c2caca635538324ccf0ccffredc } 4470f42037eb7b5118015c2caca635538324ccf0ccffredc return false; 4480f42037eb7b5118015c2caca635538324ccf0ccffredc } 4490f42037eb7b5118015c2caca635538324ccf0ccffredc 450995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom public int getState() { 451995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 452995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom (!checkIfCallerIsForegroundUser())) { 453ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.w(TAG, "getState(): report OFF for non-active and non system user"); 454995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom return BluetoothAdapter.STATE_OFF; 455995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom } 456995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom 457995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom try { 458995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom mBluetoothLock.readLock().lock(); 459995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom if (mBluetooth != null) return mBluetooth.getState(); 460995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom } catch (RemoteException e) { 461995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom Slog.e(TAG, "getState()", e); 462995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom } finally { 463995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom mBluetoothLock.readLock().unlock(); 464995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom } 465995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom return BluetoothAdapter.STATE_OFF; 466995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom } 467995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom 468d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora class ClientDeathRecipient implements IBinder.DeathRecipient { 469d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public void binderDied() { 470a80d745c656f1e09aa9331002f613883220ca029Marie Janssen if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); 4716689f33436140959097a4479f2622047952b0341Marie Janssen if (isBleAppPresent()) { 4726689f33436140959097a4479f2622047952b0341Marie Janssen // Nothing to do, another app is here. 4736689f33436140959097a4479f2622047952b0341Marie Janssen return; 4746689f33436140959097a4479f2622047952b0341Marie Janssen } 4756689f33436140959097a4479f2622047952b0341Marie Janssen if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); 4766689f33436140959097a4479f2622047952b0341Marie Janssen try { 4776689f33436140959097a4479f2622047952b0341Marie Janssen mBluetoothLock.readLock().lock(); 4786689f33436140959097a4479f2622047952b0341Marie Janssen if (mBluetooth != null && 4796689f33436140959097a4479f2622047952b0341Marie Janssen mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { 4806689f33436140959097a4479f2622047952b0341Marie Janssen mEnable = false; 4816689f33436140959097a4479f2622047952b0341Marie Janssen mBluetooth.onBrEdrDown(); 482d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 4836689f33436140959097a4479f2622047952b0341Marie Janssen } catch (RemoteException e) { 4846689f33436140959097a4479f2622047952b0341Marie Janssen Slog.e(TAG,"Unable to call onBrEdrDown", e); 4856689f33436140959097a4479f2622047952b0341Marie Janssen } finally { 4866689f33436140959097a4479f2622047952b0341Marie Janssen mBluetoothLock.readLock().unlock(); 487d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 488d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 489d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 490d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 491d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** Internal death rec list */ 4926689f33436140959097a4479f2622047952b0341Marie Janssen Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); 493d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 49467d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang @Override 49567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang public boolean isBleScanAlwaysAvailable() { 496a80d745c656f1e09aa9331002f613883220ca029Marie Janssen if (isAirplaneModeOn() && !mEnable) { 497a80d745c656f1e09aa9331002f613883220ca029Marie Janssen return false; 498a80d745c656f1e09aa9331002f613883220ca029Marie Janssen } 49967d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang try { 50067d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang return (Settings.Global.getInt(mContentResolver, 50167d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; 50267d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } catch (SettingNotFoundException e) { 50367d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } 50467d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang return false; 50567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang } 50667d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang 507e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Monitor change of BLE scan only mode settings. 508e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void registerForBleScanModeChange() { 509e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang ContentObserver contentObserver = new ContentObserver(null) { 510e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang @Override 511e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang public void onChange(boolean selfChange) { 5126689f33436140959097a4479f2622047952b0341Marie Janssen if (isBleScanAlwaysAvailable()) { 5136689f33436140959097a4479f2622047952b0341Marie Janssen // Nothing to do 5146689f33436140959097a4479f2622047952b0341Marie Janssen return; 5156689f33436140959097a4479f2622047952b0341Marie Janssen } 5166689f33436140959097a4479f2622047952b0341Marie Janssen // BLE scan is not available. 5176689f33436140959097a4479f2622047952b0341Marie Janssen disableBleScanMode(); 5186689f33436140959097a4479f2622047952b0341Marie Janssen clearBleApps(); 5196689f33436140959097a4479f2622047952b0341Marie Janssen try { 5206689f33436140959097a4479f2622047952b0341Marie Janssen mBluetoothLock.readLock().lock(); 5216689f33436140959097a4479f2622047952b0341Marie Janssen if (mBluetooth != null) mBluetooth.onBrEdrDown(); 5226689f33436140959097a4479f2622047952b0341Marie Janssen } catch (RemoteException e) { 5236689f33436140959097a4479f2622047952b0341Marie Janssen Slog.e(TAG, "error when disabling bluetooth", e); 5246689f33436140959097a4479f2622047952b0341Marie Janssen } finally { 5256689f33436140959097a4479f2622047952b0341Marie Janssen mBluetoothLock.readLock().unlock(); 526e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 527e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 528e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang }; 529e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 530e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mContentResolver.registerContentObserver( 531e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), 532e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang false, contentObserver); 533e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 534e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 535e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Disable ble scan only mode. 536e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void disableBleScanMode() { 537e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang try { 538eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 539e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { 54067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); 541e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang mEnable = false; 542e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 543e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } catch (RemoteException e) { 54467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "getState()", e); 545eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 546eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 547e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 548e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 549e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 550d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public int updateBleAppCount(IBinder token, boolean enable) { 551d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (enable) { 552d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient r = mBleApps.get(token); 553d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (r == null) { 554d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient deathRec = new ClientDeathRecipient(); 555d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 556d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora token.linkToDeath(deathRec, 0); 557d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } catch (RemoteException ex) { 558d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora throw new IllegalArgumentException("Wake lock is already dead."); 559d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 560d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBleApps.put(token, deathRec); 56167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Registered for death Notification"); 562d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 563d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 564d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } else { 565d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora ClientDeathRecipient r = mBleApps.get(token); 566d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (r != null) { 567e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Unregister death recipient as the app goes away. 568e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang token.unlinkToDeath(r, 0); 569d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBleApps.remove(token); 57067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Unregistered for death Notification"); 571d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 572d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 5736689f33436140959097a4479f2622047952b0341Marie Janssen int appCount = mBleApps.size(); 5746689f33436140959097a4479f2622047952b0341Marie Janssen if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); 5756689f33436140959097a4479f2622047952b0341Marie Janssen if (appCount == 0 && mEnable) { 576e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang disableBleScanMode(); 577d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 5786689f33436140959097a4479f2622047952b0341Marie Janssen return appCount; 579d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 580d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 581e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang // Clear all apps using BLE scan only mode. 582e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang private void clearBleApps() { 5836689f33436140959097a4479f2622047952b0341Marie Janssen mBleApps.clear(); 584e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang } 585e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang 586d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** @hide*/ 587d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora public boolean isBleAppPresent() { 5886689f33436140959097a4479f2622047952b0341Marie Janssen if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); 5896689f33436140959097a4479f2622047952b0341Marie Janssen return mBleApps.size() > 0; 590d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 591d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 592d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** 593fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen * Action taken when GattService is turned on 594d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora */ 595d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void onBluetoothGattServiceUp() { 59667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); 597eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 598eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 599fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen if (mBluetooth == null) { 600fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); 601fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen return; 602fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen } 603fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen int st = mBluetooth.getState(); 604fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen if (st != BluetoothAdapter.STATE_BLE_ON) { 605fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + 606fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen BluetoothAdapter.nameForState(st)); 607fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen return; 608fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen } 609fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { 610fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen // This triggers transition to STATE_ON 611d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetooth.onLeServiceUp(); 612d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 613d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 614eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 615eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"Unable to call onServiceUp", e); 616eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 617eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 618d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 619d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 620d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 621d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora /** 622d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora * Inform BluetoothAdapter instances that BREDR part is down 623d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora * and turn off all service and stack if no LE app needs it 624d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora */ 625d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void sendBrEdrDownCallback() { 62667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); 627bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora 628eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth == null) { 62967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Bluetooth handle is null"); 630bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora return; 631bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora } 632d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 633d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (isBleAppPresent() == false) { 634d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora try { 635eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 636eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) mBluetooth.onBrEdrDown(); 637eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 63867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Call to onBrEdrDown() failed.", e); 639eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 640eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 641d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 642bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora } else { 643bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora // Need to stay at BLE ON. Disconnect all Gatt connections 644eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 645bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora mBluetoothGatt.unregAll(); 646eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 64767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect all apps.", e); 648d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 649d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 650d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 651d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 652fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta public boolean enableNoAutoConnect() 653fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta { 654fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 655fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta "Need BLUETOOTH ADMIN permission"); 65640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 657fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (DBG) { 65867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 659fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta " mBinding = " + mBinding); 660fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6618385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 6628385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 6638385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen if (callingAppId != Process.NFC_UID) { 664fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta throw new SecurityException("no permission to enable Bluetooth quietly"); 665fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6668385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 667401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 668401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = true; 669401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 670401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(true); 671401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 672fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta return true; 673fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 6744bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 675b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov public boolean enable(String packageName) throws RemoteException { 676b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 677b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; 678b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 679b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (!callerSystem) { 680b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (!checkIfCallerIsForegroundUser()) { 681b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov Slog.w(TAG, "enable(): not allowed for non-active and non system user"); 682b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return false; 683b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 684b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 685b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 686b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov "Need BLUETOOTH ADMIN permission"); 687b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 688b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (!isEnabled() && mPermissionReviewRequired 689b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov && startConsentUiIfNeeded(packageName, callingUid, 690b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov BluetoothAdapter.ACTION_REQUEST_ENABLE)) { 691b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return false; 692b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 693f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 694f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 695401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (DBG) { 69667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + 697ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen " mBinding = " + mBinding + " mState = " + 698ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen BluetoothAdapter.nameForState(mState)); 699090bf551308e68b1b2a996c959b608cabd025c5cSanket Agarwal } 700401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 701401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 702401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 703401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 704401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // waive WRITE_SECURE_SETTINGS permission check 705401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(false); 706401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 70767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "enable returning"); 708401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return true; 7090f42037eb7b5118015c2caca635538324ccf0ccffredc } 7100f42037eb7b5118015c2caca635538324ccf0ccffredc 711b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov public boolean disable(String packageName, boolean persist) throws RemoteException { 712b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 713b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; 71440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 715b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (!callerSystem) { 716b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (!checkIfCallerIsForegroundUser()) { 717b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov Slog.w(TAG, "disable(): not allowed for non-active and non system user"); 718b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return false; 719b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 720b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 721b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 722b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov "Need BLUETOOTH ADMIN permission"); 723b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 724b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (isEnabled() && mPermissionReviewRequired 725b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov && startConsentUiIfNeeded(packageName, callingUid, 726b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov BluetoothAdapter.ACTION_REQUEST_DISABLE)) { 727b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return false; 728b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 72940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 73040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 731f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 73267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + 733cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 734cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 735f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 736401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 737401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (persist) { 738401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_OFF); 739401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 740401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 741401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendDisableMsg(); 742401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 7430f42037eb7b5118015c2caca635538324ccf0ccffredc return true; 7440f42037eb7b5118015c2caca635538324ccf0ccffredc } 7450f42037eb7b5118015c2caca635538324ccf0ccffredc 746b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov private boolean startConsentUiIfNeeded(String packageName, 747b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov int callingUid, String intentAction) throws RemoteException { 748b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov try { 749b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov // Validate the package only if we are going to use it 750b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov ApplicationInfo applicationInfo = mContext.getPackageManager() 751b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov .getApplicationInfoAsUser(packageName, 752b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 753b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov UserHandle.getUserId(callingUid)); 754b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (applicationInfo.uid != callingUid) { 755b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov throw new SecurityException("Package " + callingUid 756b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov + " not in uid " + callingUid); 757b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 758b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 759b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov // Legacy apps in permission review mode trigger a user prompt 760b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { 761b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov Intent intent = new Intent(intentAction); 762b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov mContext.startActivity(intent); 763b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return true; 764b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 765b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } catch (PackageManager.NameNotFoundException e) { 766b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov throw new RemoteException(e.getMessage()); 767b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 768b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov return false; 769b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov } 770b1e2da7c24613ce393bca871069d379cd4378c26Svetoslav Ganov 771649fe497cea2f19e937f84218d1080bdcefe47f2fredc public void unbindAndFinish() { 772f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 77367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + 774ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen " mBinding = " + mBinding + " mUnbinding = " + mUnbinding); 775f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 776f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 777eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 778eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 7790f42037eb7b5118015c2caca635538324ccf0ccffredc if (mUnbinding) return; 7800f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = true; 781e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 782c7dda10ee987377053781bf809e68c15e513cab0Pavlin Radoslavov mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); 78340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 784305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach //Unregister callback object 785305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 786305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mBluetooth.unregisterCallback(mBluetoothCallback); 787305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException re) { 78867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to unregister BluetoothCallback",re); 789bf072a712f584ae1c01022835b0de21c40513d06fredc } 7909db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = null; 791d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mBluetooth = null; 7920f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.unbindService(mConnection); 793d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mUnbinding = false; 79440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = false; 795f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } else { 796ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mUnbinding = false; 7970f42037eb7b5118015c2caca635538324ccf0ccffredc } 798d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mBluetoothGatt = null; 799eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 800eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 8010f42037eb7b5118015c2caca635538324ccf0ccffredc } 8020f42037eb7b5118015c2caca635538324ccf0ccffredc } 8030f42037eb7b5118015c2caca635538324ccf0ccffredc 804ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public IBluetoothGatt getBluetoothGatt() { 805ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // sync protection 806ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return mBluetoothGatt; 807ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 808ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 809e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 810e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public boolean bindBluetoothProfileService(int bluetoothProfile, 811e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy) { 812e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (!mEnable) { 813e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 81467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 815e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ", while Bluetooth was disabled"); 816e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 817e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return false; 818e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 819e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 820e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 821e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 822e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 82367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "Creating new ProfileServiceConnections object for" 824e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " profile: " + bluetoothProfile); 825e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 8265b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 8275b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 8285b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 8295b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz Intent intent = new Intent(IBluetoothHeadset.class.getName()); 830e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc = new ProfileServiceConnections(intent); 8315b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (!psc.bindService()) return false; 8325b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz 833e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProfileServices.put(new Integer(bluetoothProfile), psc); 834e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 835e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 836e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 837e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Introducing a delay to give the client app time to prepare 838e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 839e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz addProxyMsg.arg1 = bluetoothProfile; 840e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz addProxyMsg.obj = proxy; 841e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 842e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return true; 843e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 844e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 845e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 846e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void unbindBluetoothProfileService(int bluetoothProfile, 847e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy) { 848e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 849e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 850e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 851e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return; 852e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 853e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.removeProxy(proxy); 854e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 855e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 856e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 857e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void unbindAllBluetoothProfileServices() { 858e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mProfileServices) { 859e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz for (Integer i : mProfileServices.keySet()) { 860e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get(i); 8615b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz try { 8625b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz mContext.unbindService(psc); 8635b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz } catch (IllegalArgumentException e) { 86467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 8655b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz } 866e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.removeAllProxies(); 867e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 868e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProfileServices.clear(); 869e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 870e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 871e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 872e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz /** 873658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * Send enable message and set adapter name and address. Called when the boot phase becomes 874658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * PHASE_SYSTEM_SERVICES_READY. 875658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou */ 876658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou public void handleOnBootPhase() { 87767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Bluetooth boot completed"); 878658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 87967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); 880658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou sendEnableMsg(mQuietEnableExternal); 881bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker } else if (!isNameAndAddressSet()) { 882bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker if (DBG) Slog.d(TAG, "Getting adapter name and address"); 8834bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 8844bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessage(getMsg); 885658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 886658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 887658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 888658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou /** 889658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou * Called when switching to a different foreground user. 890658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou */ 891658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou public void handleOnSwitchUser(int userHandle) { 892aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); 893aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); 894aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 895aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 896aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey /** 897aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey * Called when user is unlocked. 898aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey */ 899aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey public void handleOnUnlockUser(int userHandle) { 900aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); 901aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); 902658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou } 903658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou 904658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou /** 905e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz * This class manages the clients connected to a given ProfileService 906e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz * and maintains the connection with that service. 907e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz */ 908e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz final private class ProfileServiceConnections implements ServiceConnection, 909e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBinder.DeathRecipient { 910e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 911e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 912e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBinder mService; 913e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ComponentName mClassName; 914e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Intent mIntent; 9153bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach boolean mInvokingProxyCallbacks = false; 916e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 917e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections(Intent intent) { 918e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = null; 919e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = null; 920e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mIntent = intent; 921e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 922e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 9235b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz private boolean bindService() { 9245b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz if (mIntent != null && mService == null && 9255b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 926e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 927e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 928e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 9295b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz return true; 930e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 93167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Unable to bind with intent: " + mIntent); 9325b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz return false; 933e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 934e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 935e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void addProxy(IBluetoothProfileServiceConnection proxy) { 936e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProxies.register(proxy); 937e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mService != null) { 938e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try{ 939e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz proxy.onServiceConnected(mClassName, mService); 940e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 94167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to connect to proxy", e); 942e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 943e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } else { 944e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 945e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 946e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 947e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessage(msg); 948e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 949e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 950e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 951e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 952e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void removeProxy(IBluetoothProfileServiceConnection proxy) { 953e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (proxy != null) { 954e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mProxies.unregister(proxy)) { 955e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 956e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz proxy.onServiceDisconnected(mClassName); 957e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 95867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect proxy", e); 959e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 960e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 961e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } else { 96267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Trying to remove a null proxy"); 963e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 964e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 965e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 966e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private void removeAllProxies() { 967e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz onServiceDisconnected(mClassName); 968e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mProxies.kill(); 969e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 970e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 971e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 972e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void onServiceConnected(ComponentName className, IBinder service) { 973e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // remove timeout message 974e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 975e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = service; 976e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = className; 977e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 978e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService.linkToDeath(this, 0); 979e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 98067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to linkToDeath", e); 981e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 9823bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 9833bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mInvokingProxyCallbacks) { 98467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Proxy callbacks already in progress."); 9853bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach return; 9863bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 9873bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = true; 9883bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 9893bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach final int n = mProxies.beginBroadcast(); 9903bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9913bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i = 0; i < n; i++) { 9923bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 9933bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.getBroadcastItem(i).onServiceConnected(className, service); 9943bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 99567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to connect to proxy", e); 9963bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 997e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 9983bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 9993bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.finishBroadcast(); 10003bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = false; 1001e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1002e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1003e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 1004e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 1005e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void onServiceDisconnected(ComponentName className) { 10063bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mService == null) return; 1007e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService.unlinkToDeath(this, 0); 1008e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mService = null; 1009e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mClassName = null; 10103bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 10113bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach if (mInvokingProxyCallbacks) { 101267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Proxy callbacks already in progress."); 10133bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach return; 10143bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 10153bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = true; 10163bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach 10173bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach final int n = mProxies.beginBroadcast(); 10183bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 10193bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i = 0; i < n; i++) { 10203bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 10213bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.getBroadcastItem(i).onServiceDisconnected(className); 10223bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 102367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to disconnect from proxy", e); 10243bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 1025e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 10263bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 10273bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mProxies.finishBroadcast(); 10283bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mInvokingProxyCallbacks = false; 1029e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1030e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1031e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 1032e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 1033e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void binderDied() { 1034e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (DBG) { 103567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "Profile service for profile: " + mClassName 1036e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " died."); 1037e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1038e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz onServiceDisconnected(mClassName); 1039e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz // Trigger rebind 1040e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 1041e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz msg.obj = this; 1042e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 1043e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1044e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1045e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 1046bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothStateCallback(boolean isUp) { 10473bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 10483bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach int n = mStateChangeCallbacks.beginBroadcast(); 104967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 10503bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach for (int i=0; i <n;i++) { 10513bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach try { 10523bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 10533bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } catch (RemoteException e) { 105467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 10553bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } 1056bf072a712f584ae1c01022835b0de21c40513d06fredc } 10573bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach } finally { 10583bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach mStateChangeCallbacks.finishBroadcast(); 1059bf072a712f584ae1c01022835b0de21c40513d06fredc } 1060bf072a712f584ae1c01022835b0de21c40513d06fredc } 1061bf072a712f584ae1c01022835b0de21c40513d06fredc 1062bf072a712f584ae1c01022835b0de21c40513d06fredc /** 106340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * Inform BluetoothAdapter instances that Adapter service is up 106440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 106540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void sendBluetoothServiceUpCallback() { 1066305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 1067305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach int n = mCallbacks.beginBroadcast(); 106867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 1069305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach for (int i=0; i <n;i++) { 1070305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 1071305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 1072305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException e) { 107367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 107440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 107540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1076305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } finally { 1077305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.finishBroadcast(); 107840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 107940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 108040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 1081bf072a712f584ae1c01022835b0de21c40513d06fredc * Inform BluetoothAdapter instances that Adapter service is down 1082bf072a712f584ae1c01022835b0de21c40513d06fredc */ 1083bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothServiceDownCallback() { 1084305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 1085305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach int n = mCallbacks.beginBroadcast(); 108667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 1087305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach for (int i=0; i <n;i++) { 1088305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach try { 1089305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 1090305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } catch (RemoteException e) { 109167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 1092d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1093d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1094305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } finally { 1095305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mCallbacks.finishBroadcast(); 1096d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1097d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 1098408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov 10990f42037eb7b5118015c2caca635538324ccf0ccffredc public String getAddress() { 1100af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1101408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov "Need BLUETOOTH permission"); 110240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 11036eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 1104408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov (!checkIfCallerIsForegroundUser())) { 110567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"getAddress(): not allowed for non-active and non system user"); 11066eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 110740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 110840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1109408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) 1110408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov != PackageManager.PERMISSION_GRANTED) { 1111408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov return BluetoothAdapter.DEFAULT_MAC_ADDRESS; 1112408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov } 1113408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov 1114eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1115eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1116eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.getAddress(); 1117eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1118eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); 1119eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1120eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1121116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 1122bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker 1123cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mAddress is accessed from outside. 1124cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It is alright without a lock. Here, bluetooth is off, no other thread is 1125cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mAddress 11260f42037eb7b5118015c2caca635538324ccf0ccffredc return mAddress; 11270f42037eb7b5118015c2caca635538324ccf0ccffredc } 1128649fe497cea2f19e937f84218d1080bdcefe47f2fredc 11290f42037eb7b5118015c2caca635538324ccf0ccffredc public String getName() { 1130af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1131af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie "Need BLUETOOTH permission"); 113240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 11336eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 11346eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 113567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG,"getName(): not allowed for non-active and non system user"); 11366eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 113740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 113840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1139eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1140eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1141eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth != null) return mBluetooth.getName(); 1142eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1143eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); 1144eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1145eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1146116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 1147eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1148cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mName is accessed from outside. 1149cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It alright without a lock. Here, bluetooth is off, no other thread is 1150cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mName 11510f42037eb7b5118015c2caca635538324ccf0ccffredc return mName; 11520f42037eb7b5118015c2caca635538324ccf0ccffredc } 11530f42037eb7b5118015c2caca635538324ccf0ccffredc 11540f42037eb7b5118015c2caca635538324ccf0ccffredc private class BluetoothServiceConnection implements ServiceConnection { 1155ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen public void onServiceConnected(ComponentName componentName, IBinder service) { 1156ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen String name = componentName.getClassName(); 1157ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name); 11580f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 1159ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 1160ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 1161ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 1162ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 1163ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 1164ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.e(TAG, "Unknown service connected: " + name); 1165ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 1166ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 11670f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = service; 11680f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 11690f42037eb7b5118015c2caca635538324ccf0ccffredc } 11700f42037eb7b5118015c2caca635538324ccf0ccffredc 1171ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen public void onServiceDisconnected(ComponentName componentName) { 1172ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // Called if we unexpectedly disconnect. 1173ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen String name = componentName.getClassName(); 1174ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); 11750f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 1176ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 1177ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 1178ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (name.equals("com.android.bluetooth.gatt.GattService")) { 1179ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 1180ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 1181ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.e(TAG, "Unknown service disconnected: " + name); 1182ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 1183ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 11840f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 11850f42037eb7b5118015c2caca635538324ccf0ccffredc } 11860f42037eb7b5118015c2caca635538324ccf0ccffredc } 11870f42037eb7b5118015c2caca635538324ccf0ccffredc 11880f42037eb7b5118015c2caca635538324ccf0ccffredc private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 11890f42037eb7b5118015c2caca635538324ccf0ccffredc 119040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private class BluetoothHandler extends Handler { 11914bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker boolean mGetNameAddressOnly = false; 11924bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 119340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu public BluetoothHandler(Looper looper) { 119440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu super(looper); 119540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 119640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 11970f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 11980f42037eb7b5118015c2caca635538324ccf0ccffredc public void handleMessage(Message msg) { 11990f42037eb7b5118015c2caca635538324ccf0ccffredc switch (msg.what) { 12004bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker case MESSAGE_GET_NAME_AND_ADDRESS: 12014bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); 1202eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1203eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 12044bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if ((mBluetooth == null) && (!mBinding)) { 12054bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (DBG) Slog.d(TAG, "Binding to service to get name and address"); 12064bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mGetNameAddressOnly = true; 12074bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 12084bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); 12094bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Intent i = new Intent(IBluetooth.class.getName()); 12104bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (!doBind(i, mConnection, 12114bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 12124bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker UserHandle.CURRENT)) { 12134bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 12144bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } else { 12154bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mBinding = true; 12164bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 12174bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } else if (mBluetooth != null) { 12184bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker try { 12194bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker storeNameAndAddress(mBluetooth.getName(), 12204bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mBluetooth.getAddress()); 12214bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } catch (RemoteException re) { 12224bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Slog.e(TAG, "Unable to grab names", re); 12234bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 12244bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (mGetNameAddressOnly && !mEnable) { 12254bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker unbindAndFinish(); 12264bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 12274bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mGetNameAddressOnly = false; 12284bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 1229eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1230eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 12314bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 12324bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker break; 12334bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 1234cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_ENABLE: 1235f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 1236ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); 1237649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 123840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 123940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 1240a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On 1241a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On // Use service interface to get the exact state 1242a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On try { 1243a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On mBluetoothLock.readLock().lock(); 1244a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On if (mBluetooth != null) { 1245a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On int state = mBluetooth.getState(); 1246a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On if (state == BluetoothAdapter.STATE_BLE_ON) { 1247a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On Slog.w(TAG, "BT is in BLE_ON State"); 1248a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On mBluetooth.onLeServiceUp(); 1249a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On break; 1250a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } 1251a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } 1252a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } catch (RemoteException e) { 1253a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On Slog.e(TAG, "", e); 1254a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } finally { 1255a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On mBluetoothLock.readLock().unlock(); 1256a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } 1257a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On 1258a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On mQuietEnable = (msg.arg1 == 1); 1259e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov if (mBluetooth == null) { 1260a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On handleEnable(mQuietEnable); 1261e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov } else { 1262e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // 1263e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // We need to wait until transitioned to STATE_OFF and 1264e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // the previous Bluetooth process has exited. The 1265e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // waiting period has three components: 1266e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (a) Wait until the local state is STATE_OFF. This 1267e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // is accomplished by "waitForOnOff(false, true)". 1268e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (b) Wait until the STATE_OFF state is updated to 1269e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // all components. 1270e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // (c) Wait until the Bluetooth process exits, and 1271e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // ActivityManager detects it. 1272e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // The waiting for (b) and (c) is accomplished by 1273e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE 1274e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // message. On slower devices, that delay needs to be 1275e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // on the order of (2 * SERVICE_RESTART_TIME_MS). 1276e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov // 1277e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov waitForOnOff(false, true); 1278e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov Message restartMsg = mHandler.obtainMessage( 1279e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov MESSAGE_RESTART_BLUETOOTH_SERVICE); 1280e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov mHandler.sendMessageDelayed(restartMsg, 1281e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov 2 * SERVICE_RESTART_TIME_MS); 1282e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov } 1283649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 12840f42037eb7b5118015c2caca635538324ccf0ccffredc 1285cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_DISABLE: 1286ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); 128740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 128840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 128940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 129040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 1291401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 129240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 129340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 129440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 1295401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 129640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 12970f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1298cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 12990f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_ADAPTER: 13000f42037eb7b5118015c2caca635538324ccf0ccffredc { 13010f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1302ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mCallbacks.register(callback); 13030f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1304ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 13050f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_ADAPTER: 13060f42037eb7b5118015c2caca635538324ccf0ccffredc { 13070f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 1308ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mCallbacks.unregister(callback); 13090f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1310cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 13110f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 13120f42037eb7b5118015c2caca635538324ccf0ccffredc { 13130f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1314ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mStateChangeCallbacks.register(callback); 13150f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1316cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 13170f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 13180f42037eb7b5118015c2caca635538324ccf0ccffredc { 13190f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1320ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mStateChangeCallbacks.unregister(callback); 13210f42037eb7b5118015c2caca635538324ccf0ccffredc break; 1322cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1323e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_ADD_PROXY_DELAYED: 1324e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz { 1325e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = mProfileServices.get( 1326e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz new Integer(msg.arg1)); 1327e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 1328e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1329e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1330e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz IBluetoothProfileServiceConnection proxy = 1331e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz (IBluetoothProfileServiceConnection) msg.obj; 1332e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.addProxy(proxy); 1333e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1334e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1335e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_BIND_PROFILE_SERVICE: 1336e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz { 1337e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1338e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1339e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (psc == null) { 1340e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1341e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 1342e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz psc.bindService(); 1343e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 1344e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 13450f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 13460f42037eb7b5118015c2caca635538324ccf0ccffredc { 134767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 13480f42037eb7b5118015c2caca635538324ccf0ccffredc 13490f42037eb7b5118015c2caca635538324ccf0ccffredc IBinder service = (IBinder) msg.obj; 1350eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1351eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1352ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1353ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1354d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora onBluetoothGattServiceUp(); 1355ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1356ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } // else must be SERVICE_IBLUETOOTH 1357ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 1358ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie //Remove timeout 1359af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1360ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 13610f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 13629db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen mBluetoothBinder = service; 13630f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = IBluetooth.Stub.asInterface(service); 13640f42037eb7b5118015c2caca635538324ccf0ccffredc 13654bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (!isNameAndAddressSet()) { 13664bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 13674bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker mHandler.sendMessage(getMsg); 13684bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker if (mGetNameAddressOnly) return; 13694bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker } 13704bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker 1371af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu try { 1372af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1373af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1374af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 137567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1376af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 1377af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } catch (RemoteException e) { 137867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call configHciSnoopLog", e); 1379af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 1380af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu 1381cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Register callback object 1382cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1383cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mBluetooth.registerCallback(mBluetoothCallback); 1384cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException re) { 138567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Unable to register BluetoothCallback",re); 1386cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1387cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Inform BluetoothAdapter instances that service is up 138840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceUpCallback(); 138940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1390cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Do enable request 1391bf072a712f584ae1c01022835b0de21c40513d06fredc try { 1392fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (mQuietEnable == false) { 1393ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (!mBluetooth.enable()) { 139467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enable() returned false"); 1395fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1396ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else { 1397ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (!mBluetooth.enableNoAutoConnect()) { 139867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1399fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1400cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1401bf072a712f584ae1c01022835b0de21c40513d06fredc } catch (RemoteException e) { 140267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call enable()",e); 14030f42037eb7b5118015c2caca635538324ccf0ccffredc } 1404eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1405eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1406bf072a712f584ae1c01022835b0de21c40513d06fredc } 140740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 140840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mEnable) { 140940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 1410401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 141140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 141240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1413649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1414cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1415bf072a712f584ae1c01022835b0de21c40513d06fredc case MESSAGE_BLUETOOTH_STATE_CHANGE: 14160f42037eb7b5118015c2caca635538324ccf0ccffredc { 1417bf072a712f584ae1c01022835b0de21c40513d06fredc int prevState = msg.arg1; 1418bf072a712f584ae1c01022835b0de21c40513d06fredc int newState = msg.arg2; 1419ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) { 1420ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(prevState) + " > " + 1421ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen BluetoothAdapter.nameForState(newState)); 1422ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 142340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = newState; 142440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu bluetoothStateChangeHandler(prevState, newState); 1425dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // handle error state transition case from TURNING_ON to OFF 1426dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // unbind and rebind bluetooth service and enable bluetooth 1427d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && 1428a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (newState == BluetoothAdapter.STATE_OFF) && 1429a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (mBluetooth != null) && mEnable) { 14306689f33436140959097a4479f2622047952b0341Marie Janssen recoverBluetoothServiceFromError(false); 1431dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1432d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1433a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (newState == BluetoothAdapter.STATE_BLE_ON) && 1434a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (mBluetooth != null) && mEnable) { 14356689f33436140959097a4479f2622047952b0341Marie Janssen recoverBluetoothServiceFromError(true); 1436d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1437a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On // If we tried to enable BT while BT was in the process of shutting down, 1438a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On // wait for the BT process to fully tear down and then force a restart 1439a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On // here. This is a bit of a hack (b/29363429). 1440a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && 1441a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (newState == BluetoothAdapter.STATE_OFF)) { 1442a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On if (mEnable) { 1443a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); 1444a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On waitForOnOff(false, true); 1445a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On Message restartMsg = mHandler.obtainMessage( 1446a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On MESSAGE_RESTART_BLUETOOTH_SERVICE); 1447a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); 1448a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } 1449a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On } 1450d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora if (newState == BluetoothAdapter.STATE_ON || 1451a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On newState == BluetoothAdapter.STATE_BLE_ON) { 1452dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // bluetooth is working, reset the counter 1453dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter != 0) { 145467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.w(TAG, "bluetooth is recovered from error"); 1455dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 1456dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1457dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1458649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1459cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 14600f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 14610f42037eb7b5118015c2caca635538324ccf0ccffredc { 1462ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); 1463eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1464eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1465ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTH) { 1466ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // if service is unbinded already, do nothing and return 1467ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mBluetooth == null) break; 1468ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetooth = null; 1469ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1470ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = null; 1471ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1472ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 1473ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.e(TAG, "Unknown argument for service disconnect!"); 1474ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 1475ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 1476eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1477eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 14781223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 147940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 148040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable) { 148140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 148240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // Send a Bluetooth Restart message 148340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message restartMsg = mHandler.obtainMessage( 148440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 148540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(restartMsg, 148640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SERVICE_RESTART_TIME_MS); 148740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 148840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1489305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach sendBluetoothServiceDownCallback(); 149040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1491305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach // Send BT state broadcast to update 1492305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach // the BT icon correctly 1493305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1494a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On (mState == BluetoothAdapter.STATE_ON)) { 1495305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1496305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach BluetoothAdapter.STATE_TURNING_OFF); 1497305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mState = BluetoothAdapter.STATE_TURNING_OFF; 149840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1499305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1500305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1501305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach BluetoothAdapter.STATE_OFF); 1502305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach } 1503305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach 1504305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1505305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach mState = BluetoothAdapter.STATE_OFF; 1506649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1507cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 15081223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M case MESSAGE_RESTART_BLUETOOTH_SERVICE: 15091223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M { 1510ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); 15111223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M /* Enable without persisting the setting as 15121223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M it doesnt change when IBluetooth 15131223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M service restarts */ 151440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 1515401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 15161223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M break; 15171223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 1518ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen case MESSAGE_TIMEOUT_BIND: { 1519ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1520ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mBluetoothLock.writeLock().lock(); 1521ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mBinding = false; 1522ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mBluetoothLock.writeLock().unlock(); 1523ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen break; 1524ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 15250f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_TIMEOUT_UNBIND: 15260f42037eb7b5118015c2caca635538324ccf0ccffredc { 152767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1528eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1529eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mUnbinding = false; 1530eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1531649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 1532cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 153340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1534aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey case MESSAGE_USER_SWITCHED: { 1535aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); 153640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1537aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 153840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /* disable and enable BT when detect a user switch */ 153940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 1540eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1541eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 154240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 1543eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetooth.unregisterCallback(mBluetoothCallback); 154440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1545eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException re) { 1546eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to unregister", re); 1547eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1548eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 154940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 15504e22ad35045dc5861193526afe1565d52f983698Zhihai Xu 15514e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 15524e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 15534e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 15544e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 15554e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 15564e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_OFF) { 15574e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 15584e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_TURNING_ON; 15594e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 156040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 156140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 156240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 15634e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_ON) { 15644e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 15654e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 156640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1567e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz unbindAllBluetoothProfileServices(); 156840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // disable 1569401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 15704e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // Pbap service need receive STATE_TURNING_OFF intent to close 15714e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 15724e22ad35045dc5861193526afe1565d52f983698Zhihai Xu BluetoothAdapter.STATE_TURNING_OFF); 157340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1574414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov boolean didDisableTimeout = !waitForOnOff(false, true); 157540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 15764e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 157740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu BluetoothAdapter.STATE_OFF); 157840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceDownCallback(); 1579eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1580e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov try { 1581e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1582e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov if (mBluetooth != null) { 1583e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetooth = null; 1584e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov // Unbind 1585e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mContext.unbindService(mConnection); 1586e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } 1587e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothGatt = null; 1588e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } finally { 1589e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 159040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1591eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1592414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov // 1593414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov // If disabling Bluetooth times out, wait for an 1594414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov // additional amount of time to ensure the process is 1595414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov // shut down completely before attempting to restart. 1596414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov // 1597414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov if (didDisableTimeout) { 1598414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov SystemClock.sleep(3000); 1599414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov } else { 1600414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov SystemClock.sleep(100); 1601414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov } 160240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 16034e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 16044e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 160540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // enable 1606401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 16078a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } else if (mBinding || mBluetooth != null) { 160840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 160940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu userMsg.arg2 = 1 + msg.arg2; 1610ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // if user is switched when service is binding retry after a delay 161140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 161240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 1613ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2); 161440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 16158a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } 161640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu break; 161740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1618aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey case MESSAGE_USER_UNLOCKED: { 1619aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); 1620aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1621aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey 1622eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mEnable && !mBinding && (mBluetooth == null)) { 1623eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // We should be connected, but we gave up for some 1624eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // reason; maybe the Bluetooth service wasn't encryption 1625eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov // aware, so try binding again. 1626eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); 1627eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov handleEnable(mQuietEnable); 1628aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 1629aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey } 16300f42037eb7b5118015c2caca635538324ccf0ccffredc } 16310f42037eb7b5118015c2caca635538324ccf0ccffredc } 163240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1633cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1634401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleEnable(boolean quietMode) { 1635fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mQuietEnable = quietMode; 1636fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta 1637eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1638eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 163940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if ((mBluetooth == null) && (!mBinding)) { 1640cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Start bind timeout and bind 1641cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1642cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1643cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Intent i = new Intent(IBluetooth.class.getName()); 1644ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1645ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn UserHandle.CURRENT)) { 1646cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 164740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 164840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = true; 1649cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 165040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else if (mBluetooth != null) { 1651cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Enable bluetooth 1652cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1653fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (!mQuietEnable) { 1654fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enable()) { 165567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enable() returned false"); 1656fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1657fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1658fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta else { 1659fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enableNoAutoConnect()) { 166067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1661fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1662cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1663cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException e) { 166467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"Unable to call enable()",e); 1665cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1666cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1667eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1668eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1669cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1670cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1671cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1672221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1673221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1674221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn intent.setComponent(comp); 1675221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 167667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG, "Fail to bind to: " + intent); 1677221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return false; 1678221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1679221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return true; 1680221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1681221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 1682401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleDisable() { 1683eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1684eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1685305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach if (mBluetooth != null) { 168667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey if (DBG) Slog.d(TAG,"Sending off request."); 1687eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (!mBluetooth.disable()) { 1688eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"IBluetooth.disable() returned false"); 1689cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1690cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1691eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1692eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG,"Unable to call disable()",e); 1693eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1694eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1695cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1696cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 169740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 169840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean checkIfCallerIsForegroundUser() { 169940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int foregroundUser; 170040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int callingUser = UserHandle.getCallingUserId(); 17018385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingUid = Binder.getCallingUid(); 170240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 1703e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1704e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz UserInfo ui = um.getProfileParent(callingUser); 1705e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 17068385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(callingUid); 170740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu boolean valid = false; 170840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 170940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu foregroundUser = ActivityManager.getCurrentUser(); 17108385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen valid = (callingUser == foregroundUser) || 1711e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz parentUser == foregroundUser || 1712bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos callingAppId == Process.NFC_UID || 1713bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos callingAppId == mSystemUiUid; 1714ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG && !valid) { 171567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 171640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " callingUser=" + callingUser 1717e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz + " parentUser=" + parentUser 171840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " foregroundUser=" + foregroundUser); 171940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 172040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } finally { 172140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Binder.restoreCallingIdentity(callingIdentity); 172240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 172340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return valid; 172440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 172540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1726d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora private void sendBleStateChanged(int prevState, int newState) { 1727ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + 1728ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen " > " + BluetoothAdapter.nameForState(newState)); 1729d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora // Send broadcast message to everyone else 1730d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); 1731d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1732d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1733d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1734d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 1735d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1736d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 173740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void bluetoothStateChangeHandler(int prevState, int newState) { 1738d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora boolean isStandardBroadcast = true; 1739ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (prevState == newState) { // No change. Nothing to do. 1740ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen return; 1741ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 1742ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // Notify all proxy objects first of adapter state change 1743ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (newState == BluetoothAdapter.STATE_BLE_ON || 1744ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen newState == BluetoothAdapter.STATE_OFF) { 1745ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF 1746ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen && newState == BluetoothAdapter.STATE_BLE_ON); 1747ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen 1748ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (newState == BluetoothAdapter.STATE_OFF) { 1749ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // If Bluetooth is off, send service down event to proxy objects, and unbind 1750ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down"); 1751ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBluetoothServiceDownCallback(); 1752ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen unbindAndFinish(); 1753d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1754ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // Don't broadcast as it has already been broadcast before 1755ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen isStandardBroadcast = false; 1756d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1757ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (!intermediate_off) { 1758ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // connect to GattService 1759ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); 1760ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (mBluetoothGatt != null) { 1761ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); 1762ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen onBluetoothGattServiceUp(); 1763ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else { 1764ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); 1765ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (mContext.getPackageManager().hasSystemFeature( 1766ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen PackageManager.FEATURE_BLUETOOTH_LE)) { 1767ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Intent i = new Intent(IBluetoothGatt.class.getName()); 1768ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); 1769ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 1770ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 1771d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1772ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen //Don't broadcase this as std intent 1773d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora isStandardBroadcast = false; 1774d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora 1775ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (intermediate_off) { 1776ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); 1777ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // For LE only mode, broadcast as is 1778d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora sendBleStateChanged(prevState, newState); 1779ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBluetoothStateCallback(false); // BT is OFF for general users 1780ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // Broadcast as STATE_OFF 1781ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen newState = BluetoothAdapter.STATE_OFF; 1782ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBrEdrDownCallback(); 178340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1784ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (newState == BluetoothAdapter.STATE_ON) { 1785ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen boolean isUp = (newState == BluetoothAdapter.STATE_ON); 1786ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBluetoothStateCallback(isUp); 1787ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBleStateChanged(prevState, newState); 178840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1789ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || 1790ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { 1791ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBleStateChanged(prevState, newState); 1792ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen isStandardBroadcast = false; 1793ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen 1794ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } else if (newState == BluetoothAdapter.STATE_TURNING_ON || 1795ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen newState == BluetoothAdapter.STATE_TURNING_OFF) { 1796ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen sendBleStateChanged(prevState, newState); 1797ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen } 1798ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen 1799ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (isStandardBroadcast) { 1800ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen if (prevState == BluetoothAdapter.STATE_BLE_ON) { 1801ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen // Show prevState of BLE_ON as OFF to standard users 1802ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen prevState = BluetoothAdapter.STATE_OFF; 1803d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora } 1804ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1805ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1806ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1807ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1808ffcf88f36ec8412bc274a51cad3bf03c11c614fbMarie Janssen mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); 180940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 181040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 181140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 181240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 181340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if on is true, wait for state become ON 181440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if off is true, wait for state become OFF 181540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if both on and off are false, wait for state not ON 181640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 181740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean waitForOnOff(boolean on, boolean off) { 181840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int i = 0; 181940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu while (i < 10) { 1820eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1821eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1822eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth == null) break; 1823eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (on) { 1824eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1825eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } else if (off) { 1826eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1827eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } else { 1828eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 182940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1830eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException e) { 1831eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "getState()", e); 1832eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov break; 1833eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1834eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 183540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 183640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (on || off) { 183740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(300); 1838665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } else { 183940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(50); 1840665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } 184140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu i++; 184240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 184367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"waitForOnOff time out"); 184440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 184540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1846681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu 1847401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendDisableMsg() { 1848401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1849401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1850401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 1851401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendEnableMsg(boolean quietMode) { 1852401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1853401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu quietMode ? 1 : 0, 0)); 1854401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1855401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 18566689f33436140959097a4479f2622047952b0341Marie Janssen private void recoverBluetoothServiceFromError(boolean clearBle) { 185767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey Slog.e(TAG,"recoverBluetoothServiceFromError"); 1858eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov try { 1859eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().lock(); 1860dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mBluetooth != null) { 1861dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Unregister callback object 1862eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetooth.unregisterCallback(mBluetoothCallback); 1863dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1864eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } catch (RemoteException re) { 1865eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov Slog.e(TAG, "Unable to unregister", re); 1866eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov } finally { 1867eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov mBluetoothLock.readLock().unlock(); 1868dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1869dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1870dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu SystemClock.sleep(500); 1871dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1872dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // disable 1873dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu handleDisable(); 1874dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1875dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu waitForOnOff(false, true); 1876dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1877dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu sendBluetoothServiceDownCallback(); 1878eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov 1879e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov try { 1880e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().lock(); 1881e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov if (mBluetooth != null) { 1882e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetooth = null; 1883e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov // Unbind 1884e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mContext.unbindService(mConnection); 1885e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } 1886e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothGatt = null; 1887e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov } finally { 1888e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov mBluetoothLock.writeLock().unlock(); 1889dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1890dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1891dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1892dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mState = BluetoothAdapter.STATE_OFF; 1893dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 18946689f33436140959097a4479f2622047952b0341Marie Janssen if (clearBle) { 18956689f33436140959097a4479f2622047952b0341Marie Janssen clearBleApps(); 18966689f33436140959097a4479f2622047952b0341Marie Janssen } 18976689f33436140959097a4479f2622047952b0341Marie Janssen 1898dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mEnable = false; 1899dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1900dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1901dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // Send a Bluetooth Restart message to reenable bluetooth 1902dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Message restartMsg = mHandler.obtainMessage( 1903dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 1904dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1905dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } else { 1906dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // todo: notify user to power down and power up phone to make bluetooth work. 1907dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1908dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1909726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood 1910726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood @Override 19116e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 19126e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 19136e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov String errorMsg = null; 19146e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if (mBluetoothBinder == null) { 19156e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov errorMsg = "Bluetooth Service not connected"; 19166e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } else { 19176e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov try { 19186e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov mBluetoothBinder.dump(fd, args); 19196e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } catch (RemoteException re) { 19206e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov errorMsg = "RemoteException while calling Bluetooth Service"; 19216e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } 19226e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov } 19236e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if (errorMsg != null) { 19246e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov // Silently return if we are extracting metrics in Protobuf format 19256e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov if ((args.length > 0) && args[0].startsWith("--proto")) 19266e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov return; 19276e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov writer.println(errorMsg); 1928726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood } 1929726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood } 19300f42037eb7b5118015c2caca635538324ccf0ccffredc} 1931