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