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