BluetoothManagerService.java revision 55db646c4e43fd24386bf522aef13c0b3075593c
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 1940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.app.ActivityManager; 200f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.BluetoothAdapter; 210f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetooth; 22ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xieimport android.bluetooth.IBluetoothGatt; 23bf072a712f584ae1c01022835b0de21c40513d06fredcimport android.bluetooth.IBluetoothCallback; 240f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManager; 250f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManagerCallback; 260f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothStateChangeCallback; 270f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.BroadcastReceiver; 280f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ComponentName; 290f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ContentResolver; 300f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Context; 310f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Intent; 320f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.IntentFilter; 330f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ServiceConnection; 3432ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xieimport android.content.pm.PackageManager; 3540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Binder; 360f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Handler; 370f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.IBinder; 3840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Looper; 390f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Message; 4040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Process; 41d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredcimport android.os.RemoteCallbackList; 420f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.RemoteException; 4340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.SystemClock; 445ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 450f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.provider.Settings; 460f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.util.Log; 470f42037eb7b5118015c2caca635538324ccf0ccffredcclass BluetoothManagerService extends IBluetoothManager.Stub { 480f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String TAG = "BluetoothManagerService"; 490f42037eb7b5118015c2caca635538324ccf0ccffredc private static final boolean DBG = true; 500f42037eb7b5118015c2caca635538324ccf0ccffredc 510f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 520f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 530f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 540f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String EXTRA_ACTION="action"; 55d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 560f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 570f42037eb7b5118015c2caca635538324ccf0ccffredc private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 580f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 590f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 601223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M //Maximum msec to wait for service restart 611223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int SERVICE_RESTART_TIME_MS = 200; 62dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Maximum msec to wait for restart due to error 63dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private static final int ERROR_RESTART_TIME_MS = 3000; 6440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Maximum msec to delay MESSAGE_USER_SWITCHED 6540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int USER_SWITCHED_TIME_MS = 200; 660f42037eb7b5118015c2caca635538324ccf0ccffredc 670f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_ENABLE = 1; 680f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_DISABLE = 2; 69649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_ADAPTER = 20; 70649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 71649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 72649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 73649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 74649fe497cea2f19e937f84218d1080bdcefe47f2fredc private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 751223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 76bf072a712f584ae1c01022835b0de21c40513d06fredc private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; 770f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_TIMEOUT_BIND =100; 780f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_TIMEOUT_UNBIND =101; 790f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_GET_NAME_AND_ADDRESS=200; 800f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201; 8140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private static final int MESSAGE_USER_SWITCHED = 300; 820f42037eb7b5118015c2caca635538324ccf0ccffredc private static final int MAX_SAVE_RETRIES=3; 83dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private static final int MAX_ERROR_RESTART_RETRIES=6; 84dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 85401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is off 86401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_OFF=0; 87401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 88401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode won't affect Bluetooth state at start up 89401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_BLUETOOTH=1; 90401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // Bluetooth persisted setting is on 91401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // but Airplane mode will affect Bluetooth state at start up 92401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // and Airplane mode will have higher priority. 93401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private static final int BLUETOOTH_ON_AIRPLANE=2; 940f42037eb7b5118015c2caca635538324ccf0ccffredc 95ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTH = 1; 96ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int SERVICE_IBLUETOOTHGATT = 2; 97ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 980f42037eb7b5118015c2caca635538324ccf0ccffredc private final Context mContext; 99cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 100cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // Locks are not provided for mName and mAddress. 101cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // They are accessed in handler or broadcast receiver, same thread context. 1020f42037eb7b5118015c2caca635538324ccf0ccffredc private String mAddress; 1030f42037eb7b5118015c2caca635538324ccf0ccffredc private String mName; 1046fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final ContentResolver mContentResolver; 1056fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 1066fde3098074ab2551867d1cd919958383b15725fMatthew Xie private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 107649fe497cea2f19e937f84218d1080bdcefe47f2fredc private IBluetooth mBluetooth; 108ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private IBluetoothGatt mBluetoothGatt; 109649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mBinding; 110649fe497cea2f19e937f84218d1080bdcefe47f2fredc private boolean mUnbinding; 111401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 112fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta private boolean mQuietEnable = false; 113401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 114401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 115401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mQuietEnableExternal; 116401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // configuarion from external IBinder call which is used to 117401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // synchronize with broadcast receiver. 118401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private boolean mEnableExternal; 119401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // used inside handler thread 12040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean mEnable; 12140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private int mState; 12240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private final BluetoothHandler mHandler; 123dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private int mErrorRecoveryRetryCounter; 1240f42037eb7b5118015c2caca635538324ccf0ccffredc 125649fe497cea2f19e937f84218d1080bdcefe47f2fredc private void registerForAirplaneMode(IntentFilter filter) { 126649fe497cea2f19e937f84218d1080bdcefe47f2fredc final ContentResolver resolver = mContext.getContentResolver(); 127c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String airplaneModeRadios = Settings.Global.getString(resolver, 128c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_RADIOS); 129c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate final String toggleableRadios = Settings.Global.getString(resolver, 130c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 131649fe497cea2f19e937f84218d1080bdcefe47f2fredc boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 132c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 133649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (mIsAirplaneSensitive) { 134649fe497cea2f19e937f84218d1080bdcefe47f2fredc filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 135649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 136649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 1370f42037eb7b5118015c2caca635538324ccf0ccffredc 138bf072a712f584ae1c01022835b0de21c40513d06fredc private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 139bf072a712f584ae1c01022835b0de21c40513d06fredc @Override 140bf072a712f584ae1c01022835b0de21c40513d06fredc public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 141bf072a712f584ae1c01022835b0de21c40513d06fredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 142bf072a712f584ae1c01022835b0de21c40513d06fredc mHandler.sendMessage(msg); 143bf072a712f584ae1c01022835b0de21c40513d06fredc } 144bf072a712f584ae1c01022835b0de21c40513d06fredc }; 145bf072a712f584ae1c01022835b0de21c40513d06fredc 146bf072a712f584ae1c01022835b0de21c40513d06fredc private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1470f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 1480f42037eb7b5118015c2caca635538324ccf0ccffredc public void onReceive(Context context, Intent intent) { 1490f42037eb7b5118015c2caca635538324ccf0ccffredc String action = intent.getAction(); 150bf072a712f584ae1c01022835b0de21c40513d06fredc if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 1510f42037eb7b5118015c2caca635538324ccf0ccffredc String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 152a8c6df0d3a6b929cac3e59abde8309e8a45ea78aFred if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName); 1530f42037eb7b5118015c2caca635538324ccf0ccffredc if (newName != null) { 1540f42037eb7b5118015c2caca635538324ccf0ccffredc storeNameAndAddress(newName, null); 1550f42037eb7b5118015c2caca635538324ccf0ccffredc } 156649fe497cea2f19e937f84218d1080bdcefe47f2fredc } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 157401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 158401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 159401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 160401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 161401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else { 162401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 163401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 164401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 165401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isAirplaneModeOn()) { 166401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // disable without persisting the setting 167401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendDisableMsg(); 168401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else if (mEnableExternal) { 169401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // enable without persisting the setting 170401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(mQuietEnableExternal); 171401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 172649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 17340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { 17440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, 17540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); 176401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 177401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 178401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 179401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu //Enable 180401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); 181401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(mQuietEnableExternal); 182401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 183401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 184401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 185401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (!isNameAndAddressSet()) { 186401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu //Sync the Bluetooth name and address from the Bluetooth Adapter 187401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); 188401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu getNameAndAddress(); 189401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1900f42037eb7b5118015c2caca635538324ccf0ccffredc } 1910f42037eb7b5118015c2caca635538324ccf0ccffredc } 1920f42037eb7b5118015c2caca635538324ccf0ccffredc }; 1930f42037eb7b5118015c2caca635538324ccf0ccffredc 1940f42037eb7b5118015c2caca635538324ccf0ccffredc BluetoothManagerService(Context context) { 1958d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn mHandler = new BluetoothHandler(IoThread.get().getLooper()); 19640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1970f42037eb7b5118015c2caca635538324ccf0ccffredc mContext = context; 1980f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = null; 1990f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 2000f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = false; 20140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 20240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = BluetoothAdapter.STATE_OFF; 203401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 204401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 2050f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = null; 2060f42037eb7b5118015c2caca635538324ccf0ccffredc mName = null; 207dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 2080f42037eb7b5118015c2caca635538324ccf0ccffredc mContentResolver = context.getContentResolver(); 209d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 210d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 211401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 2126fde3098074ab2551867d1cd919958383b15725fMatthew Xie filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 21340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu filter.addAction(Intent.ACTION_USER_SWITCHED); 2146fde3098074ab2551867d1cd919958383b15725fMatthew Xie registerForAirplaneMode(filter); 2156fde3098074ab2551867d1cd919958383b15725fMatthew Xie mContext.registerReceiver(mReceiver, filter); 2160f42037eb7b5118015c2caca635538324ccf0ccffredc loadStoredNameAndAddress(); 217401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (isBluetoothPersistedStateOn()) { 218401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 2190f42037eb7b5118015c2caca635538324ccf0ccffredc } 2200f42037eb7b5118015c2caca635538324ccf0ccffredc } 2210f42037eb7b5118015c2caca635538324ccf0ccffredc 222649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 223649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if airplane mode is currently on 224649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 225649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isAirplaneModeOn() { 226c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate return Settings.Global.getInt(mContext.getContentResolver(), 227c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 228649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 229649fe497cea2f19e937f84218d1080bdcefe47f2fredc 230649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 231649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth saved state is "on" 232649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 233649fe497cea2f19e937f84218d1080bdcefe47f2fredc private final boolean isBluetoothPersistedStateOn() { 234bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown return Settings.Global.getInt(mContentResolver, 235401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; 236401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 237401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 238401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu /** 239401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 240401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu */ 241401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private final boolean isBluetoothPersistedStateOnBluetooth() { 242401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return Settings.Global.getInt(mContentResolver, 243401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; 244649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 245649fe497cea2f19e937f84218d1080bdcefe47f2fredc 246649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 247649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth on/off state 248649fe497cea2f19e937f84218d1080bdcefe47f2fredc * 249649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 250401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void persistBluetoothSetting(int value) { 251bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.putInt(mContext.getContentResolver(), 252bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown Settings.Global.BLUETOOTH_ON, 253401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu value); 254649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 255649fe497cea2f19e937f84218d1080bdcefe47f2fredc 256649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 257649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Returns true if the Bluetooth Adapter's name and address is 258649fe497cea2f19e937f84218d1080bdcefe47f2fredc * locally cached 259649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @return 260649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 2610f42037eb7b5118015c2caca635538324ccf0ccffredc private boolean isNameAndAddressSet() { 2620f42037eb7b5118015c2caca635538324ccf0ccffredc return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 2630f42037eb7b5118015c2caca635538324ccf0ccffredc } 2640f42037eb7b5118015c2caca635538324ccf0ccffredc 265649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 266649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Retrieve the Bluetooth Adapter's name and address and save it in 267649fe497cea2f19e937f84218d1080bdcefe47f2fredc * in the local cache 268649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 2690f42037eb7b5118015c2caca635538324ccf0ccffredc private void loadStoredNameAndAddress() { 2700f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "Loading stored name and address"); 271d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (mContext.getResources().getBoolean 272d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu (com.android.internal.R.bool.config_bluetooth_address_validation) && 273d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 274d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu // if the valid flag is not set, don't load the address and name 275d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (DBG) Log.d(TAG, "invalid bluetooth name and address stored"); 276d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu return; 277d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 2780f42037eb7b5118015c2caca635538324ccf0ccffredc mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 2790f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 280d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 2810f42037eb7b5118015c2caca635538324ccf0ccffredc } 2820f42037eb7b5118015c2caca635538324ccf0ccffredc 283649fe497cea2f19e937f84218d1080bdcefe47f2fredc /** 284649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Save the Bluetooth name and address in the persistent store. 285649fe497cea2f19e937f84218d1080bdcefe47f2fredc * Only non-null values will be saved. 286649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param name 287649fe497cea2f19e937f84218d1080bdcefe47f2fredc * @param address 288649fe497cea2f19e937f84218d1080bdcefe47f2fredc */ 2890f42037eb7b5118015c2caca635538324ccf0ccffredc private void storeNameAndAddress(String name, String address) { 2900f42037eb7b5118015c2caca635538324ccf0ccffredc if (name != null) { 2910f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 2920f42037eb7b5118015c2caca635538324ccf0ccffredc mName = name; 293649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (DBG) Log.d(TAG,"Stored Bluetooth name: " + 294649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 2950f42037eb7b5118015c2caca635538324ccf0ccffredc } 2960f42037eb7b5118015c2caca635538324ccf0ccffredc 2970f42037eb7b5118015c2caca635538324ccf0ccffredc if (address != null) { 2980f42037eb7b5118015c2caca635538324ccf0ccffredc Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 2990f42037eb7b5118015c2caca635538324ccf0ccffredc mAddress=address; 300649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + 301649fe497cea2f19e937f84218d1080bdcefe47f2fredc Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 3020f42037eb7b5118015c2caca635538324ccf0ccffredc } 303d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu 304d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if ((name != null) && (address != null)) { 305d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 306d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 3070f42037eb7b5118015c2caca635538324ccf0ccffredc } 3080f42037eb7b5118015c2caca635538324ccf0ccffredc 3090f42037eb7b5118015c2caca635538324ccf0ccffredc public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 31055db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 31155db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich Log.w(TAG, "Callback is null in registerAdapter"); 31255db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return null; 31355db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 3140f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 3150f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3160f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3170f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized(mConnection) { 3180f42037eb7b5118015c2caca635538324ccf0ccffredc return mBluetooth; 3190f42037eb7b5118015c2caca635538324ccf0ccffredc } 3200f42037eb7b5118015c2caca635538324ccf0ccffredc } 3210f42037eb7b5118015c2caca635538324ccf0ccffredc 3220f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterAdapter(IBluetoothManagerCallback callback) { 32355db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich if (callback == null) { 32455db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich Log.w(TAG, "Callback is null in unregisterAdapter"); 32555db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich return; 32655db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich } 3270f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 3280f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 3290f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 3300f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3310f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3320f42037eb7b5118015c2caca635538324ccf0ccffredc } 3330f42037eb7b5118015c2caca635538324ccf0ccffredc 3340f42037eb7b5118015c2caca635538324ccf0ccffredc public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 3350f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 3360f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 3370f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 3380f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3390f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3400f42037eb7b5118015c2caca635538324ccf0ccffredc } 3410f42037eb7b5118015c2caca635538324ccf0ccffredc 3420f42037eb7b5118015c2caca635538324ccf0ccffredc public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 3430f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 3440f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH permission"); 3450f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 3460f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = callback; 3470f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3480f42037eb7b5118015c2caca635538324ccf0ccffredc } 3490f42037eb7b5118015c2caca635538324ccf0ccffredc 3500f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean isEnabled() { 3516eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 3526eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 3536eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu Log.w(TAG,"isEnabled(): not allowed for non-active and non system user"); 35440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 35540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 35640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 3570f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized(mConnection) { 3580f42037eb7b5118015c2caca635538324ccf0ccffredc try { 3590f42037eb7b5118015c2caca635538324ccf0ccffredc return (mBluetooth != null && mBluetooth.isEnabled()); 3600f42037eb7b5118015c2caca635538324ccf0ccffredc } catch (RemoteException e) { 3610f42037eb7b5118015c2caca635538324ccf0ccffredc Log.e(TAG, "isEnabled()", e); 3620f42037eb7b5118015c2caca635538324ccf0ccffredc } 3630f42037eb7b5118015c2caca635538324ccf0ccffredc } 3640f42037eb7b5118015c2caca635538324ccf0ccffredc return false; 3650f42037eb7b5118015c2caca635538324ccf0ccffredc } 3660f42037eb7b5118015c2caca635538324ccf0ccffredc 3670f42037eb7b5118015c2caca635538324ccf0ccffredc public void getNameAndAddress() { 368f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 369cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth + 370cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 371f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 3720f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 3730f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 3740f42037eb7b5118015c2caca635538324ccf0ccffredc } 375fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta public boolean enableNoAutoConnect() 376fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta { 377fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 378fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta "Need BLUETOOTH ADMIN permission"); 37940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 380fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (DBG) { 381fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 382fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta " mBinding = " + mBinding); 383fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 3848385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 3858385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 3868385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen if (callingAppId != Process.NFC_UID) { 387fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta throw new SecurityException("no permission to enable Bluetooth quietly"); 388fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 3898385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen 390401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 391401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = true; 392401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 393401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(true); 394401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 395fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta return true; 396fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta 397fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 3980f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean enable() { 3996eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 4006eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 4016eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu Log.w(TAG,"enable(): not allowed for non-active and non system user"); 40240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 403f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 404f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 405401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 406401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu "Need BLUETOOTH ADMIN permission"); 407401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (DBG) { 408401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + 409401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu " mBinding = " + mBinding); 410401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 411401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 412401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 413401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mQuietEnableExternal = false; 414401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = true; 415401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // waive WRITE_SECURE_SETTINGS permission check 416401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 417401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 418401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Binder.restoreCallingIdentity(callingIdentity); 419401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendEnableMsg(false); 420401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 421401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu return true; 4220f42037eb7b5118015c2caca635538324ccf0ccffredc } 4230f42037eb7b5118015c2caca635538324ccf0ccffredc 4240f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean disable(boolean persist) { 4250f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 4260f42037eb7b5118015c2caca635538324ccf0ccffredc "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 42740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 4286eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 4296eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 4306eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu Log.w(TAG,"disable(): not allowed for non-active and non system user"); 43140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 43240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 43340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 434f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 435cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.d(TAG,"disable(): mBluetooth = " + mBluetooth + 436cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 437cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 438f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 439401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu synchronized(mReceiver) { 440401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu if (persist) { 441401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu // waive WRITE_SECURE_SETTINGS permission check 442401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 443401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu persistBluetoothSetting(BLUETOOTH_OFF); 444401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu Binder.restoreCallingIdentity(callingIdentity); 445401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 446401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mEnableExternal = false; 447401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu sendDisableMsg(); 448401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 4490f42037eb7b5118015c2caca635538324ccf0ccffredc return true; 4500f42037eb7b5118015c2caca635538324ccf0ccffredc } 4510f42037eb7b5118015c2caca635538324ccf0ccffredc 452649fe497cea2f19e937f84218d1080bdcefe47f2fredc public void unbindAndFinish() { 453f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 454cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.d(TAG,"unbindAndFinish(): " + mBluetooth + 455cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie " mBinding = " + mBinding); 456f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } 457f24588615efa6c781ad963f1a5bbdf47359e1b53fredc 4580f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized (mConnection) { 4590f42037eb7b5118015c2caca635538324ccf0ccffredc if (mUnbinding) return; 4600f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = true; 46140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 462bf072a712f584ae1c01022835b0de21c40513d06fredc if (!mConnection.isGetNameAddressOnly()) { 463bf072a712f584ae1c01022835b0de21c40513d06fredc //Unregister callback object 464bf072a712f584ae1c01022835b0de21c40513d06fredc try { 465bf072a712f584ae1c01022835b0de21c40513d06fredc mBluetooth.unregisterCallback(mBluetoothCallback); 466bf072a712f584ae1c01022835b0de21c40513d06fredc } catch (RemoteException re) { 46740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG, "Unable to unregister BluetoothCallback",re); 468bf072a712f584ae1c01022835b0de21c40513d06fredc } 469bf072a712f584ae1c01022835b0de21c40513d06fredc } 4700f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "Sending unbind request."); 471d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mBluetooth = null; 472d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc //Unbind 4730f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.unbindService(mConnection); 474d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mUnbinding = false; 47540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = false; 476f24588615efa6c781ad963f1a5bbdf47359e1b53fredc } else { 477f24588615efa6c781ad963f1a5bbdf47359e1b53fredc mUnbinding=false; 4780f42037eb7b5118015c2caca635538324ccf0ccffredc } 4790f42037eb7b5118015c2caca635538324ccf0ccffredc } 4800f42037eb7b5118015c2caca635538324ccf0ccffredc } 4810f42037eb7b5118015c2caca635538324ccf0ccffredc 482ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie public IBluetoothGatt getBluetoothGatt() { 483ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // sync protection 484ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return mBluetoothGatt; 485ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 486ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 487bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothStateCallback(boolean isUp) { 488bf072a712f584ae1c01022835b0de21c40513d06fredc int n = mStateChangeCallbacks.beginBroadcast(); 489a8c6df0d3a6b929cac3e59abde8309e8a45ea78aFred if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 490bf072a712f584ae1c01022835b0de21c40513d06fredc for (int i=0; i <n;i++) { 491bf072a712f584ae1c01022835b0de21c40513d06fredc try { 492bf072a712f584ae1c01022835b0de21c40513d06fredc mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 493bf072a712f584ae1c01022835b0de21c40513d06fredc } catch (RemoteException e) { 494bf072a712f584ae1c01022835b0de21c40513d06fredc Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 495bf072a712f584ae1c01022835b0de21c40513d06fredc } 496bf072a712f584ae1c01022835b0de21c40513d06fredc } 497bf072a712f584ae1c01022835b0de21c40513d06fredc mStateChangeCallbacks.finishBroadcast(); 498bf072a712f584ae1c01022835b0de21c40513d06fredc } 499bf072a712f584ae1c01022835b0de21c40513d06fredc 500bf072a712f584ae1c01022835b0de21c40513d06fredc /** 50140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * Inform BluetoothAdapter instances that Adapter service is up 50240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 50340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void sendBluetoothServiceUpCallback() { 50440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mConnection.isGetNameAddressOnly()) { 50540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks"); 50640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int n = mCallbacks.beginBroadcast(); 50740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 50840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu for (int i=0; i <n;i++) { 50940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 51040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 51140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } catch (RemoteException e) { 51240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 51340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 51440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 51540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mCallbacks.finishBroadcast(); 51640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 51740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 51840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 519bf072a712f584ae1c01022835b0de21c40513d06fredc * Inform BluetoothAdapter instances that Adapter service is down 520bf072a712f584ae1c01022835b0de21c40513d06fredc */ 521bf072a712f584ae1c01022835b0de21c40513d06fredc private void sendBluetoothServiceDownCallback() { 522d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc if (!mConnection.isGetNameAddressOnly()) { 523d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks"); 524d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc int n = mCallbacks.beginBroadcast(); 525d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 526d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc for (int i=0; i <n;i++) { 527d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc try { 528d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 529d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } catch (RemoteException e) { 530d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 531d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 532d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 533d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc mCallbacks.finishBroadcast(); 534d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 535d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc } 5360f42037eb7b5118015c2caca635538324ccf0ccffredc public String getAddress() { 537af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 538af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie "Need BLUETOOTH permission"); 53940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 5406eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 5416eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 5426eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu Log.w(TAG,"getAddress(): not allowed for non-active and non system user"); 5436eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 54440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 54540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 546116d1d4696ac8e300c83dd8a95e20e67717ef520fredc synchronized(mConnection) { 547116d1d4696ac8e300c83dd8a95e20e67717ef520fredc if (mBluetooth != null) { 548116d1d4696ac8e300c83dd8a95e20e67717ef520fredc try { 549116d1d4696ac8e300c83dd8a95e20e67717ef520fredc return mBluetooth.getAddress(); 550116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } catch (RemoteException e) { 551116d1d4696ac8e300c83dd8a95e20e67717ef520fredc Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); 552116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 553116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 554116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 555cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mAddress is accessed from outside. 556cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It is alright without a lock. Here, bluetooth is off, no other thread is 557cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mAddress 5580f42037eb7b5118015c2caca635538324ccf0ccffredc return mAddress; 5590f42037eb7b5118015c2caca635538324ccf0ccffredc } 560649fe497cea2f19e937f84218d1080bdcefe47f2fredc 5610f42037eb7b5118015c2caca635538324ccf0ccffredc public String getName() { 562af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 563af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie "Need BLUETOOTH permission"); 56440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 5656eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 5666eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu (!checkIfCallerIsForegroundUser())) { 5676eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu Log.w(TAG,"getName(): not allowed for non-active and non system user"); 5686eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu return null; 56940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 57040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 571116d1d4696ac8e300c83dd8a95e20e67717ef520fredc synchronized(mConnection) { 572116d1d4696ac8e300c83dd8a95e20e67717ef520fredc if (mBluetooth != null) { 573116d1d4696ac8e300c83dd8a95e20e67717ef520fredc try { 574116d1d4696ac8e300c83dd8a95e20e67717ef520fredc return mBluetooth.getName(); 575116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } catch (RemoteException e) { 576116d1d4696ac8e300c83dd8a95e20e67717ef520fredc Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); 577116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 578116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 579116d1d4696ac8e300c83dd8a95e20e67717ef520fredc } 580cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // mName is accessed from outside. 581cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // It alright without a lock. Here, bluetooth is off, no other thread is 582cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie // changing mName 5830f42037eb7b5118015c2caca635538324ccf0ccffredc return mName; 5840f42037eb7b5118015c2caca635538324ccf0ccffredc } 5850f42037eb7b5118015c2caca635538324ccf0ccffredc 5860f42037eb7b5118015c2caca635538324ccf0ccffredc private class BluetoothServiceConnection implements ServiceConnection { 5870f42037eb7b5118015c2caca635538324ccf0ccffredc 5880f42037eb7b5118015c2caca635538324ccf0ccffredc private boolean mGetNameAddressOnly; 5890f42037eb7b5118015c2caca635538324ccf0ccffredc 5900f42037eb7b5118015c2caca635538324ccf0ccffredc public void setGetNameAddressOnly(boolean getOnly) { 5910f42037eb7b5118015c2caca635538324ccf0ccffredc mGetNameAddressOnly = getOnly; 5920f42037eb7b5118015c2caca635538324ccf0ccffredc } 5930f42037eb7b5118015c2caca635538324ccf0ccffredc 5940f42037eb7b5118015c2caca635538324ccf0ccffredc public boolean isGetNameAddressOnly() { 5950f42037eb7b5118015c2caca635538324ccf0ccffredc return mGetNameAddressOnly; 5960f42037eb7b5118015c2caca635538324ccf0ccffredc } 5970f42037eb7b5118015c2caca635538324ccf0ccffredc 5980f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceConnected(ComponentName className, IBinder service) { 599ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 6000f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 601ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 602ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 603ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 604ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 605ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 606ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 607ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 608ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "Unknown service connected: " + className.getClassName()); 609ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 610ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 6110f42037eb7b5118015c2caca635538324ccf0ccffredc msg.obj = service; 6120f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 6130f42037eb7b5118015c2caca635538324ccf0ccffredc } 6140f42037eb7b5118015c2caca635538324ccf0ccffredc 6150f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceDisconnected(ComponentName className) { 6160f42037eb7b5118015c2caca635538324ccf0ccffredc // Called if we unexpected disconnected. 617ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " + 618ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie className.getClassName()); 6190f42037eb7b5118015c2caca635538324ccf0ccffredc Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 620ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 621ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTH; 622ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 623ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie msg.arg1 = SERVICE_IBLUETOOTHGATT; 624ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 625ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "Unknown service disconnected: " + className.getClassName()); 626ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return; 627ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 6280f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessage(msg); 6290f42037eb7b5118015c2caca635538324ccf0ccffredc } 6300f42037eb7b5118015c2caca635538324ccf0ccffredc } 6310f42037eb7b5118015c2caca635538324ccf0ccffredc 6320f42037eb7b5118015c2caca635538324ccf0ccffredc private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 6330f42037eb7b5118015c2caca635538324ccf0ccffredc 63440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private class BluetoothHandler extends Handler { 63540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu public BluetoothHandler(Looper looper) { 63640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu super(looper); 63740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 63840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 6390f42037eb7b5118015c2caca635538324ccf0ccffredc @Override 6400f42037eb7b5118015c2caca635538324ccf0ccffredc public void handleMessage(Message msg) { 6410f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d (TAG, "Message: " + msg.what); 6420f42037eb7b5118015c2caca635538324ccf0ccffredc switch (msg.what) { 6430f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_GET_NAME_AND_ADDRESS: { 644649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS"); 645cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie synchronized(mConnection) { 6460f42037eb7b5118015c2caca635538324ccf0ccffredc //Start bind request 64740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if ((mBluetooth == null) && (!mBinding)) { 6480f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "Binding to service to get name and address"); 6490f42037eb7b5118015c2caca635538324ccf0ccffredc mConnection.setGetNameAddressOnly(true); 6500f42037eb7b5118015c2caca635538324ccf0ccffredc //Start bind timeout and bind 6510f42037eb7b5118015c2caca635538324ccf0ccffredc Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 6520f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 6530f42037eb7b5118015c2caca635538324ccf0ccffredc Intent i = new Intent(IBluetooth.class.getName()); 654221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (!doBind(i, mConnection, 655221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { 6560f42037eb7b5118015c2caca635538324ccf0ccffredc mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 65740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 65840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = true; 6590f42037eb7b5118015c2caca635538324ccf0ccffredc } 6600f42037eb7b5118015c2caca635538324ccf0ccffredc } 661cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie else { 662cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 66340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu saveMsg.arg1 = 0; 66440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 66540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessage(saveMsg); 66640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 66740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // if enable is also called to bind the service 66840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // wait for MESSAGE_BLUETOOTH_SERVICE_CONNECTED 66940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(saveMsg, TIMEOUT_SAVE_MS); 67040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 671cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 6720f42037eb7b5118015c2caca635538324ccf0ccffredc } 673649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 674cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 6750f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_SAVE_NAME_AND_ADDRESS: { 676d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu boolean unbind = false; 677649fe497cea2f19e937f84218d1080bdcefe47f2fredc if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); 678cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie synchronized(mConnection) { 679d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (!mEnable && mBluetooth != null) { 680d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu try { 681d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu mBluetooth.enable(); 682d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } catch (RemoteException e) { 683d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Log.e(TAG,"Unable to call enable()",e); 684d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 685d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 686d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 687d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (mBluetooth != null) waitForOnOff(true, false); 688d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu synchronized(mConnection) { 689cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (mBluetooth != null) { 690cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie String name = null; 691cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie String address = null; 692cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 693cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie name = mBluetooth.getName(); 694cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie address = mBluetooth.getAddress(); 695cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException re) { 696cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG,"",re); 697cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 6980f42037eb7b5118015c2caca635538324ccf0ccffredc 699cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (name != null && address != null) { 700cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie storeNameAndAddress(name,address); 70140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mConnection.isGetNameAddressOnly()) { 702d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu unbind = true; 70340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 704cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } else { 705cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (msg.arg1 < MAX_SAVE_RETRIES) { 706cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 707cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie retryMsg.arg1= 1+msg.arg1; 708cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1); 709cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS); 710cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } else { 711cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.w(TAG,"Maximum name/address remote retrieval retry exceeded"); 71240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mConnection.isGetNameAddressOnly()) { 713d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu unbind = true; 71440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 715cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 7160f42037eb7b5118015c2caca635538324ccf0ccffredc } 717d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (!mEnable) { 718d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu try { 719d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu mBluetooth.disable(); 720d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } catch (RemoteException e) { 721d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu Log.e(TAG,"Unable to call disable()",e); 722d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 723d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 72440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 72540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // rebind service by Request GET NAME AND ADDRESS 72640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // if service is unbinded by disable or 72740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received 72840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 72940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessage(getMsg); 7300f42037eb7b5118015c2caca635538324ccf0ccffredc } 7310f42037eb7b5118015c2caca635538324ccf0ccffredc } 732d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (!mEnable && mBluetooth != null) waitForOnOff(false, true); 733d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu if (unbind) { 734d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu unbindAndFinish(); 735d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu } 736649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 737649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 738cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_ENABLE: 739f24588615efa6c781ad963f1a5bbdf47359e1b53fredc if (DBG) { 740cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 741649fe497cea2f19e937f84218d1080bdcefe47f2fredc } 74240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 74340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 744401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(msg.arg1 == 1); 745649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 7460f42037eb7b5118015c2caca635538324ccf0ccffredc 747cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie case MESSAGE_DISABLE: 74840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 74940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 75040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 75140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 752401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 75340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 75440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 75540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 756401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 75740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 7580f42037eb7b5118015c2caca635538324ccf0ccffredc break; 759cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 7600f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_ADAPTER: 7610f42037eb7b5118015c2caca635538324ccf0ccffredc { 7620f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 763d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc boolean added = mCallbacks.register(callback); 764d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc Log.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 7650f42037eb7b5118015c2caca635538324ccf0ccffredc } 7660f42037eb7b5118015c2caca635538324ccf0ccffredc break; 7670f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_ADAPTER: 7680f42037eb7b5118015c2caca635538324ccf0ccffredc { 7690f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 770d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc boolean removed = mCallbacks.unregister(callback); 771d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc Log.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 7720f42037eb7b5118015c2caca635538324ccf0ccffredc break; 773cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 7740f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 7750f42037eb7b5118015c2caca635538324ccf0ccffredc { 7760f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 7779b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (callback != null) { 7789b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mStateChangeCallbacks.register(callback); 7799b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 7800f42037eb7b5118015c2caca635538324ccf0ccffredc break; 781cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 7820f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 7830f42037eb7b5118015c2caca635538324ccf0ccffredc { 7840f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 7859b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (callback != null) { 7869b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mStateChangeCallbacks.unregister(callback); 7879b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 7880f42037eb7b5118015c2caca635538324ccf0ccffredc break; 789cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 7900f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 7910f42037eb7b5118015c2caca635538324ccf0ccffredc { 792ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 7930f42037eb7b5118015c2caca635538324ccf0ccffredc 7940f42037eb7b5118015c2caca635538324ccf0ccffredc IBinder service = (IBinder) msg.obj; 7950f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized(mConnection) { 796ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 797ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 798ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 799ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } // else must be SERVICE_IBLUETOOTH 800ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 801ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie //Remove timeout 802af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 803ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 8040f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 8050f42037eb7b5118015c2caca635538324ccf0ccffredc mBluetooth = IBluetooth.Stub.asInterface(service); 8060f42037eb7b5118015c2caca635538324ccf0ccffredc 807af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu try { 808af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 809af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 810af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 811af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu Log.e(TAG,"IBluetooth.configHciSnoopLog return false"); 812af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 813af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } catch (RemoteException e) { 814af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu Log.e(TAG,"Unable to call configHciSnoopLog", e); 815af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu } 816af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu 817cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (mConnection.isGetNameAddressOnly()) { 818cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Request GET NAME AND ADDRESS 819cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 820cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.sendMessage(getMsg); 82140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mEnable) return; 822cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 823bf072a712f584ae1c01022835b0de21c40513d06fredc 82440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mConnection.setGetNameAddressOnly(false); 825cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Register callback object 826cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 827cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mBluetooth.registerCallback(mBluetoothCallback); 828cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException re) { 829cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG, "Unable to register BluetoothCallback",re); 830cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 831cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Inform BluetoothAdapter instances that service is up 83240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceUpCallback(); 83340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 834cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Do enable request 835bf072a712f584ae1c01022835b0de21c40513d06fredc try { 836fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (mQuietEnable == false) { 837fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enable()) { 838fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta Log.e(TAG,"IBluetooth.enable() returned false"); 839fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 840fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 841fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta else 842fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta { 843fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enableNoAutoConnect()) { 844fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 845fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 846cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 847bf072a712f584ae1c01022835b0de21c40513d06fredc } catch (RemoteException e) { 848cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG,"Unable to call enable()",e); 8490f42037eb7b5118015c2caca635538324ccf0ccffredc } 850bf072a712f584ae1c01022835b0de21c40513d06fredc } 85140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 85240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mEnable) { 85340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 854401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 85540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, false); 85640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 857649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 858cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 859649fe497cea2f19e937f84218d1080bdcefe47f2fredc case MESSAGE_TIMEOUT_BIND: { 860649fe497cea2f19e937f84218d1080bdcefe47f2fredc Log.e(TAG, "MESSAGE_TIMEOUT_BIND"); 8610f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized(mConnection) { 8620f42037eb7b5118015c2caca635538324ccf0ccffredc mBinding = false; 8630f42037eb7b5118015c2caca635538324ccf0ccffredc } 864649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 865cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 866bf072a712f584ae1c01022835b0de21c40513d06fredc case MESSAGE_BLUETOOTH_STATE_CHANGE: 8670f42037eb7b5118015c2caca635538324ccf0ccffredc { 868bf072a712f584ae1c01022835b0de21c40513d06fredc int prevState = msg.arg1; 869bf072a712f584ae1c01022835b0de21c40513d06fredc int newState = msg.arg2; 870bf072a712f584ae1c01022835b0de21c40513d06fredc if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 87140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = newState; 87240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu bluetoothStateChangeHandler(prevState, newState); 873dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // handle error state transition case from TURNING_ON to OFF 874dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // unbind and rebind bluetooth service and enable bluetooth 875dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 876dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu (newState == BluetoothAdapter.STATE_OFF) && 877dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu (mBluetooth != null) && mEnable) { 878dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu recoverBluetoothServiceFromError(); 879dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 880dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (newState == BluetoothAdapter.STATE_ON) { 881dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // bluetooth is working, reset the counter 882dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter != 0) { 883dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Log.w(TAG, "bluetooth is recovered from error"); 884dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mErrorRecoveryRetryCounter = 0; 885dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 886dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 887649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 888cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 8890f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 8900f42037eb7b5118015c2caca635538324ccf0ccffredc { 891ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 8921223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M synchronized(mConnection) { 893ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (msg.arg1 == SERVICE_IBLUETOOTH) { 894ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // if service is unbinded already, do nothing and return 895ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mBluetooth == null) break; 896ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetooth = null; 897ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 898ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mBluetoothGatt = null; 899ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 900ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 901ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "Bad msg.arg1: " + msg.arg1); 902ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie break; 903ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 9041223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 90540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 90640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable) { 90740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = false; 90840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // Send a Bluetooth Restart message 90940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message restartMsg = mHandler.obtainMessage( 91040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 91140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(restartMsg, 91240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SERVICE_RESTART_TIME_MS); 91340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 91440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 91540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (!mConnection.isGetNameAddressOnly()) { 91640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceDownCallback(); 91740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 91840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // Send BT state broadcast to update 91940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // the BT icon correctly 9204e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 9214e22ad35045dc5861193526afe1565d52f983698Zhihai Xu (mState == BluetoothAdapter.STATE_ON)) { 9224e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 9234e22ad35045dc5861193526afe1565d52f983698Zhihai Xu BluetoothAdapter.STATE_TURNING_OFF); 9244e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_TURNING_OFF; 9254e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 9264e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 9274e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 9284e22ad35045dc5861193526afe1565d52f983698Zhihai Xu BluetoothAdapter.STATE_OFF); 9294e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 9304e22ad35045dc5861193526afe1565d52f983698Zhihai Xu 9314e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 93240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mState = BluetoothAdapter.STATE_OFF; 93340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 934649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 935cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 9361223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M case MESSAGE_RESTART_BLUETOOTH_SERVICE: 9371223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M { 9381223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 9391223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M +" Restart IBluetooth service"); 9401223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M /* Enable without persisting the setting as 9411223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M it doesnt change when IBluetooth 9421223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M service restarts */ 94340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mEnable = true; 944401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 9451223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M break; 9461223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M } 9471223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M 9480f42037eb7b5118015c2caca635538324ccf0ccffredc case MESSAGE_TIMEOUT_UNBIND: 9490f42037eb7b5118015c2caca635538324ccf0ccffredc { 950649fe497cea2f19e937f84218d1080bdcefe47f2fredc Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 9510f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized(mConnection) { 9520f42037eb7b5118015c2caca635538324ccf0ccffredc mUnbinding = false; 9530f42037eb7b5118015c2caca635538324ccf0ccffredc } 954649fe497cea2f19e937f84218d1080bdcefe47f2fredc break; 955cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 95640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 95740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu case MESSAGE_USER_SWITCHED: 95840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu { 95940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 96040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.d(TAG, "MESSAGE_USER_SWITCHED"); 96140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 96240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.removeMessages(MESSAGE_USER_SWITCHED); 96340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /* disable and enable BT when detect a user switch */ 96440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mEnable && mBluetooth != null) { 96540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu synchronized (mConnection) { 96640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 96740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Unregister callback object 96840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 96940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBluetooth.unregisterCallback(mBluetoothCallback); 97040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } catch (RemoteException re) { 97140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG, "Unable to unregister",re); 97240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 97340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 97440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 9754e22ad35045dc5861193526afe1565d52f983698Zhihai Xu 9764e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 9774e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 9784e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 9794e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 9804e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 9814e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_OFF) { 9824e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 9834e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_TURNING_ON; 9844e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 98540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 98640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(true, false); 98740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 9884e22ad35045dc5861193526afe1565d52f983698Zhihai Xu if (mState == BluetoothAdapter.STATE_TURNING_ON) { 9894e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 9904e22ad35045dc5861193526afe1565d52f983698Zhihai Xu } 99140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 99240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // disable 993401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleDisable(); 9944e22ad35045dc5861193526afe1565d52f983698Zhihai Xu // Pbap service need receive STATE_TURNING_OFF intent to close 9954e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 9964e22ad35045dc5861193526afe1565d52f983698Zhihai Xu BluetoothAdapter.STATE_TURNING_OFF); 99740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 99840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu waitForOnOff(false, true); 99940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 10004e22ad35045dc5861193526afe1565d52f983698Zhihai Xu bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 100140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu BluetoothAdapter.STATE_OFF); 100240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceDownCallback(); 100340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu synchronized (mConnection) { 100440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth != null) { 100540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBluetooth = null; 100640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Unbind 100740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mContext.unbindService(mConnection); 100840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 100940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 101040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(100); 101140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 10124e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 10134e22ad35045dc5861193526afe1565d52f983698Zhihai Xu mState = BluetoothAdapter.STATE_OFF; 101440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // enable 1015401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu handleEnable(mQuietEnable); 10168a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } else if (mBinding || mBluetooth != null) { 101740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 101840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu userMsg.arg2 = 1 + msg.arg2; 101940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // if user is switched when service is being binding 102040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // delay sending MESSAGE_USER_SWITCHED 102140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 102240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 102340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 102440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 10258a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock } 102640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu break; 102740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 10280f42037eb7b5118015c2caca635538324ccf0ccffredc } 10290f42037eb7b5118015c2caca635538324ccf0ccffredc } 103040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1031cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1032401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleEnable(boolean quietMode) { 1033fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta mQuietEnable = quietMode; 1034fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta 1035cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie synchronized(mConnection) { 103640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if ((mBluetooth == null) && (!mBinding)) { 1037cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Start bind timeout and bind 1038cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1039cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1040cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mConnection.setGetNameAddressOnly(false); 1041cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Intent i = new Intent(IBluetooth.class.getName()); 1042221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { 1043cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 104440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else { 104540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBinding = true; 1046cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 104740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else if (mBluetooth != null) { 104840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mConnection.isGetNameAddressOnly()) { 104940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // if GetNameAddressOnly is set, we can clear this flag, 105040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // so the service won't be unbind 105140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // after name and address are saved 105240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mConnection.setGetNameAddressOnly(false); 105340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Register callback object 105440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 105540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mBluetooth.registerCallback(mBluetoothCallback); 105640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } catch (RemoteException re) { 105740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG, "Unable to register BluetoothCallback",re); 105840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 105940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Inform BluetoothAdapter instances that service is up 106040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothServiceUpCallback(); 106140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 106240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1063cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie //Enable bluetooth 1064cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1065fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if (!mQuietEnable) { 1066fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enable()) { 1067fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta Log.e(TAG,"IBluetooth.enable() returned false"); 1068fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1069fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1070fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta else { 1071fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta if(!mBluetooth.enableNoAutoConnect()) { 1072fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1073fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta } 1074cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1075cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException e) { 1076cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG,"Unable to call enable()",e); 1077cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1078cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1079cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1080cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1081cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1082221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1083221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1084221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn intent.setComponent(comp); 1085221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1086221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Log.e(TAG, "Fail to bind to: " + intent); 1087221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return false; 1088221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1089221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return true; 1090221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 1091221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 1092401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void handleDisable() { 1093cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie synchronized(mConnection) { 109440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // don't need to disable if GetNameAddressOnly is set, 109540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu // service will be unbinded after Name and Address are saved 109640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if ((mBluetooth != null) && (!mConnection.isGetNameAddressOnly())) { 1097cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if (DBG) Log.d(TAG,"Sending off request."); 1098cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie 1099cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie try { 1100cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie if(!mBluetooth.disable()) { 1101cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG,"IBluetooth.disable() returned false"); 1102cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1103cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } catch (RemoteException e) { 1104cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie Log.e(TAG,"Unable to call disable()",e); 1105cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1106cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1107cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 1108cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie } 110940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 111040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean checkIfCallerIsForegroundUser() { 111140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int foregroundUser; 111240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int callingUser = UserHandle.getCallingUserId(); 11138385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingUid = Binder.getCallingUid(); 111440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu long callingIdentity = Binder.clearCallingIdentity(); 11158385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen int callingAppId = UserHandle.getAppId(callingUid); 111640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu boolean valid = false; 111740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 111840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu foregroundUser = ActivityManager.getCurrentUser(); 11198385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen valid = (callingUser == foregroundUser) || 11208385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen callingAppId == Process.NFC_UID; 112140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) { 112240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 112340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " callingUser=" + callingUser 112440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu + " foregroundUser=" + foregroundUser); 112540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 112640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } finally { 112740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Binder.restoreCallingIdentity(callingIdentity); 112840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 112940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return valid; 113040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 113140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 113240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private void bluetoothStateChangeHandler(int prevState, int newState) { 113340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (prevState != newState) { 113440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Notify all proxy objects first of adapter state change 113540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) { 113640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu boolean isUp = (newState==BluetoothAdapter.STATE_ON); 113740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu sendBluetoothStateCallback(isUp); 113840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 1139ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (isUp) { 1140ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // connect to GattService 114132ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xie if (mContext.getPackageManager().hasSystemFeature( 114232ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xie PackageManager.FEATURE_BLUETOOTH_LE)) { 114332ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xie Intent i = new Intent(IBluetoothGatt.class.getName()); 1144221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(i, mConnection, Context.BIND_AUTO_CREATE, UserHandle.CURRENT); 1145ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 1146ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 1147ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie //If Bluetooth is off, send service down event to proxy objects, and unbind 1148ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (!isUp && canUnbindBluetoothService()) { 1149ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie sendBluetoothServiceDownCallback(); 1150ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie unbindAndFinish(); 1151ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 115240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 115340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 115440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 115540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu //Send broadcast message to everyone else 115640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 115740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 115840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 115940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 116040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState); 116140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 116240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu BLUETOOTH_PERM); 116340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 116440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 116540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu 116640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu /** 116740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if on is true, wait for state become ON 116840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if off is true, wait for state become OFF 116940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu * if both on and off are false, wait for state not ON 117040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu */ 117140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu private boolean waitForOnOff(boolean on, boolean off) { 117240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu int i = 0; 117340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu while (i < 10) { 117440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu synchronized(mConnection) { 117540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu try { 117640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth == null) break; 117740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (on) { 117840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 117940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } else if (off) { 118040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1181665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } else { 118240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1183665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } 118440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } catch (RemoteException e) { 118540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG, "getState()", e); 118640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu break; 118740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 118840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 118940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu if (on || off) { 119040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(300); 1191665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } else { 119240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu SystemClock.sleep(50); 1193665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt } 119440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu i++; 119540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 119640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu Log.e(TAG,"waitForOnOff time out"); 119740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu return false; 119840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu } 1199681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu 1200401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendDisableMsg() { 1201401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1202401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1203401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 1204401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu private void sendEnableMsg(boolean quietMode) { 1205401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1206401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu quietMode ? 1 : 0, 0)); 1207401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu } 1208401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu 1209681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu private boolean canUnbindBluetoothService() { 1210681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu synchronized(mConnection) { 1211681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu //Only unbind with mEnable flag not set 1212681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu //For race condition: disable and enable back-to-back 1213681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu //Avoid unbind right after enable due to callback from disable 1214681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu //Only unbind with Bluetooth at OFF state 1215681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message 1216681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu try { 1217681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu if (mEnable || (mBluetooth == null)) return false; 1218681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; 1219681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); 1220681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu } catch (RemoteException e) { 1221681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu Log.e(TAG, "getState()", e); 1222681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu } 1223681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu } 1224681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu return false; 1225681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu } 1226dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1227dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu private void recoverBluetoothServiceFromError() { 1228dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Log.e(TAG,"recoverBluetoothServiceFromError"); 1229dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu synchronized (mConnection) { 1230dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mBluetooth != null) { 1231dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Unregister callback object 1232dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu try { 1233dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mBluetooth.unregisterCallback(mBluetoothCallback); 1234dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } catch (RemoteException re) { 1235dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Log.e(TAG, "Unable to unregister",re); 1236dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1237dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1238dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1239dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1240dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu SystemClock.sleep(500); 1241dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1242dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // disable 1243dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu handleDisable(); 1244dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1245dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu waitForOnOff(false, true); 1246dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1247dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu sendBluetoothServiceDownCallback(); 1248dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu synchronized (mConnection) { 1249dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mBluetooth != null) { 1250dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mBluetooth = null; 1251dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu //Unbind 1252dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mContext.unbindService(mConnection); 1253dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1254dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1255dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1256dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1257dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mState = BluetoothAdapter.STATE_OFF; 1258dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1259dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mEnable = false; 1260dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu 1261dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1262dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // Send a Bluetooth Restart message to reenable bluetooth 1263dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu Message restartMsg = mHandler.obtainMessage( 1264dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu MESSAGE_RESTART_BLUETOOTH_SERVICE); 1265dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1266dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } else { 1267dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu // todo: notify user to power down and power up phone to make bluetooth work. 1268dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 1269dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu } 12700f42037eb7b5118015c2caca635538324ccf0ccffredc} 1271