blob: 188d6549486819311e027b3f6940878bbc101a80 [file] [log] [blame]
fredc0f420372012-04-12 00:02:00 -07001/*
Zhihai Xufa0fd392012-10-23 17:31:56 -07002 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
fredc0f420372012-04-12 00:02:00 -070015 */
16
17package com.android.server;
18
Svet Ganov408abf72015-05-12 19:13:36 -070019import android.Manifest;
Zhihai Xu40874a02012-10-08 17:57:03 -070020import android.app.ActivityManager;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010021import android.app.AppGlobals;
Jack Hea80cead2019-04-23 20:00:18 -070022import android.app.AppOpsManager;
fredc0f420372012-04-12 00:02:00 -070023import android.bluetooth.BluetoothAdapter;
Benjamin Franze8b98922014-11-12 15:57:54 +000024import android.bluetooth.BluetoothProfile;
Jack He8caab152018-03-02 13:08:36 -080025import android.bluetooth.BluetoothProtoEnums;
fredc0f420372012-04-12 00:02:00 -070026import android.bluetooth.IBluetooth;
fredcbf072a72012-05-09 16:52:50 -070027import android.bluetooth.IBluetoothCallback;
Wei Wange4a744b2015-06-11 17:50:29 -070028import android.bluetooth.IBluetoothGatt;
Benjamin Franze8b98922014-11-12 15:57:54 +000029import android.bluetooth.IBluetoothHeadset;
fredc0f420372012-04-12 00:02:00 -070030import android.bluetooth.IBluetoothManager;
31import android.bluetooth.IBluetoothManagerCallback;
Benjamin Franze8b98922014-11-12 15:57:54 +000032import android.bluetooth.IBluetoothProfileServiceConnection;
fredc0f420372012-04-12 00:02:00 -070033import android.bluetooth.IBluetoothStateChangeCallback;
Svet Ganov77df6f32016-08-17 11:46:34 -070034import android.content.ActivityNotFoundException;
fredc0f420372012-04-12 00:02:00 -070035import android.content.BroadcastReceiver;
36import android.content.ComponentName;
37import android.content.ContentResolver;
38import android.content.Context;
39import android.content.Intent;
40import android.content.IntentFilter;
41import android.content.ServiceConnection;
Svetoslav Ganovac69be52016-06-29 17:31:44 -070042import android.content.pm.ApplicationInfo;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010043import android.content.pm.IPackageManager;
Matthew Xie32ab77b2013-05-08 19:26:57 -070044import android.content.pm.PackageManager;
Benjamin Franze8b98922014-11-12 15:57:54 +000045import android.content.pm.UserInfo;
Wei Wange4a744b2015-06-11 17:50:29 -070046import android.database.ContentObserver;
Zhihai Xu40874a02012-10-08 17:57:03 -070047import android.os.Binder;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010048import android.os.Bundle;
fredc0f420372012-04-12 00:02:00 -070049import android.os.Handler;
fredc0f420372012-04-12 00:02:00 -070050import android.os.IBinder;
Zhihai Xu40874a02012-10-08 17:57:03 -070051import android.os.Looper;
fredc0f420372012-04-12 00:02:00 -070052import android.os.Message;
Zhihai Xu40874a02012-10-08 17:57:03 -070053import android.os.Process;
fredcd6883532012-04-25 17:46:13 -070054import android.os.RemoteCallbackList;
fredc0f420372012-04-12 00:02:00 -070055import android.os.RemoteException;
Zhihai Xu40874a02012-10-08 17:57:03 -070056import android.os.SystemClock;
Stanley Tngfe8c8332018-06-19 08:48:10 -070057import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070058import android.os.UserHandle;
Benjamin Franze8b98922014-11-12 15:57:54 +000059import android.os.UserManager;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010060import android.os.UserManagerInternal;
61import android.os.UserManagerInternal.UserRestrictionsListener;
fredc0f420372012-04-12 00:02:00 -070062import android.provider.Settings;
Wei Wang67d84162015-04-26 17:04:29 -070063import android.provider.Settings.SettingNotFoundException;
Stanley Tngfe8c8332018-06-19 08:48:10 -070064import android.text.TextUtils;
65import android.util.FeatureFlagUtils;
66import android.util.Log;
Jeff Sharkey67609c72016-03-05 14:29:13 -070067import android.util.Slog;
Tej Singhd8e7cc62018-03-22 18:30:31 +000068import android.util.StatsLog;
Mike Lockwood726d4de2014-10-28 14:06:28 -070069
Arthur Hsuf3f95a92018-01-11 16:46:22 -080070import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060071import com.android.internal.util.DumpUtils;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010072import com.android.server.pm.UserRestrictionsUtils;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +010073
Mike Lockwood726d4de2014-10-28 14:06:28 -070074import java.io.FileDescriptor;
75import java.io.PrintWriter;
Benjamin Franze8b98922014-11-12 15:57:54 +000076import java.util.HashMap;
Marie Janssen59804562016-12-28 14:13:21 -080077import java.util.LinkedList;
Myles Watsonb5cd11a2017-11-27 16:42:11 -080078import java.util.Locale;
Benjamin Franze8b98922014-11-12 15:57:54 +000079import java.util.Map;
Chienyuan177156b2018-12-18 10:40:25 +080080import java.util.NoSuchElementException;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010081import java.util.concurrent.ConcurrentHashMap;
82import java.util.concurrent.locks.ReentrantReadWriteLock;
Miao Chou658bf2f2015-06-26 17:14:35 -070083
Marie Janssen59804562016-12-28 14:13:21 -080084
fredc0f420372012-04-12 00:02:00 -070085class BluetoothManagerService extends IBluetoothManager.Stub {
86 private static final String TAG = "BluetoothManagerService";
Pavlin Radoslavov41401112016-06-27 15:25:18 -070087 private static final boolean DBG = true;
fredc0f420372012-04-12 00:02:00 -070088
fredc0f420372012-04-12 00:02:00 -070089 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
90 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
Marie Janssene54b4222017-03-16 18:10:59 -070091
Myles Watsonb5cd11a2017-11-27 16:42:11 -080092 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
93 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
94 private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name";
Marie Janssene54b4222017-03-16 18:10:59 -070095
96 private static final int ACTIVE_LOG_MAX_SIZE = 20;
97 private static final int CRASH_LOG_MAX_SIZE = 100;
Marie Janssene54b4222017-03-16 18:10:59 -070098
fredc0f420372012-04-12 00:02:00 -070099 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530100 //Maximum msec to wait for service restart
101 private static final int SERVICE_RESTART_TIME_MS = 200;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800102 //Maximum msec to wait for restart due to error
103 private static final int ERROR_RESTART_TIME_MS = 3000;
Zhihai Xu40874a02012-10-08 17:57:03 -0700104 //Maximum msec to delay MESSAGE_USER_SWITCHED
105 private static final int USER_SWITCHED_TIME_MS = 200;
Benjamin Franze8b98922014-11-12 15:57:54 +0000106 // Delay for the addProxy function in msec
107 private static final int ADD_PROXY_DELAY_MS = 100;
fredc0f420372012-04-12 00:02:00 -0700108
109 private static final int MESSAGE_ENABLE = 1;
110 private static final int MESSAGE_DISABLE = 2;
fredc649fe492012-04-19 01:07:18 -0700111 private static final int MESSAGE_REGISTER_ADAPTER = 20;
112 private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
113 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
114 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
115 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
116 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530117 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700118 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
119 private static final int MESSAGE_TIMEOUT_BIND = 100;
120 private static final int MESSAGE_TIMEOUT_UNBIND = 101;
Ajay Panicker4bb48302016-03-31 14:14:27 -0700121 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
Zhihai Xu40874a02012-10-08 17:57:03 -0700122 private static final int MESSAGE_USER_SWITCHED = 300;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700123 private static final int MESSAGE_USER_UNLOCKED = 301;
Benjamin Franze8b98922014-11-12 15:57:54 +0000124 private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
125 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
Stanley Tng873b5702017-05-01 21:27:31 -0700126 private static final int MESSAGE_RESTORE_USER_SETTING = 500;
127
128 private static final int RESTORE_SETTING_TO_ON = 1;
129 private static final int RESTORE_SETTING_TO_OFF = 0;
Marie Janssencb21ad72016-12-13 10:51:02 -0800130
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700131 private static final int MAX_ERROR_RESTART_RETRIES = 6;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800132
Zhihai Xu401202b2012-12-03 11:36:21 -0800133 // Bluetooth persisted setting is off
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800134 private static final int BLUETOOTH_OFF = 0;
Zhihai Xu401202b2012-12-03 11:36:21 -0800135 // Bluetooth persisted setting is on
136 // and Airplane mode won't affect Bluetooth state at start up
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800137 private static final int BLUETOOTH_ON_BLUETOOTH = 1;
Zhihai Xu401202b2012-12-03 11:36:21 -0800138 // Bluetooth persisted setting is on
139 // but Airplane mode will affect Bluetooth state at start up
140 // and Airplane mode will have higher priority.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800141 private static final int BLUETOOTH_ON_AIRPLANE = 2;
fredc0f420372012-04-12 00:02:00 -0700142
Matthew Xieddf7e472013-03-01 18:41:02 -0800143 private static final int SERVICE_IBLUETOOTH = 1;
144 private static final int SERVICE_IBLUETOOTHGATT = 2;
145
fredc0f420372012-04-12 00:02:00 -0700146 private final Context mContext;
Matthew Xiecdce0b92012-07-12 19:06:15 -0700147
148 // Locks are not provided for mName and mAddress.
149 // They are accessed in handler or broadcast receiver, same thread context.
fredc0f420372012-04-12 00:02:00 -0700150 private String mAddress;
151 private String mName;
Matthew Xie6fde3092012-07-11 17:10:07 -0700152 private final ContentResolver mContentResolver;
153 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
154 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800155 private IBinder mBluetoothBinder;
fredc649fe492012-04-19 01:07:18 -0700156 private IBluetooth mBluetooth;
Matthew Xieddf7e472013-03-01 18:41:02 -0800157 private IBluetoothGatt mBluetoothGatt;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800158 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
fredc649fe492012-04-19 01:07:18 -0700159 private boolean mBinding;
160 private boolean mUnbinding;
Marie Janssen59804562016-12-28 14:13:21 -0800161
Zhihai Xu401202b2012-12-03 11:36:21 -0800162 // used inside handler thread
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700163 private boolean mQuietEnable = false;
Marie Janssen59804562016-12-28 14:13:21 -0800164 private boolean mEnable;
165
Jack He8caab152018-03-02 13:08:36 -0800166 private static CharSequence timeToLog(long timestamp) {
Marie Janssene54b4222017-03-16 18:10:59 -0700167 return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
168 }
169
Marie Janssen59804562016-12-28 14:13:21 -0800170 /**
171 * Used for tracking apps that enabled / disabled Bluetooth.
172 */
173 private class ActiveLog {
Jack He8caab152018-03-02 13:08:36 -0800174 private int mReason;
Marie Janssen59804562016-12-28 14:13:21 -0800175 private String mPackageName;
176 private boolean mEnable;
177 private long mTimestamp;
178
Jack He8caab152018-03-02 13:08:36 -0800179 ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
180 mReason = reason;
Marie Janssen59804562016-12-28 14:13:21 -0800181 mPackageName = packageName;
182 mEnable = enable;
183 mTimestamp = timestamp;
184 }
185
Marie Janssen59804562016-12-28 14:13:21 -0800186 public String toString() {
Jack He8caab152018-03-02 13:08:36 -0800187 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
188 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
Marie Janssen59804562016-12-28 14:13:21 -0800189 }
190
191 }
192
Jack He8caab152018-03-02 13:08:36 -0800193 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
194 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
Marie Janssene54b4222017-03-16 18:10:59 -0700195 private int mCrashes;
Marie Janssen12a35012017-06-26 07:21:03 -0700196 private long mLastEnabledTime;
Marie Janssen59804562016-12-28 14:13:21 -0800197
198 // configuration from external IBinder call which is used to
Zhihai Xu401202b2012-12-03 11:36:21 -0800199 // synchronize with broadcast receiver.
200 private boolean mQuietEnableExternal;
Zhihai Xu401202b2012-12-03 11:36:21 -0800201 private boolean mEnableExternal;
Marie Janssen59804562016-12-28 14:13:21 -0800202
203 // Map of apps registered to keep BLE scanning on.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800204 private Map<IBinder, ClientDeathRecipient> mBleApps =
205 new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
Marie Janssen59804562016-12-28 14:13:21 -0800206
Zhihai Xu40874a02012-10-08 17:57:03 -0700207 private int mState;
Zhihai Xu40874a02012-10-08 17:57:03 -0700208 private final BluetoothHandler mHandler;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800209 private int mErrorRecoveryRetryCounter;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200210 private final int mSystemUiUid;
fredc0f420372012-04-12 00:02:00 -0700211
Stanley Tng61dbd812019-01-13 16:04:31 -0800212 private boolean mIsHearingAidProfileSupported;
213
Jack Hea80cead2019-04-23 20:00:18 -0700214 private AppOpsManager mAppOps;
215
Benjamin Franze8b98922014-11-12 15:57:54 +0000216 // Save a ProfileServiceConnections object for each of the bound
217 // bluetooth profile services
Jack He8caab152018-03-02 13:08:36 -0800218 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
Benjamin Franze8b98922014-11-12 15:57:54 +0000219
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700220 private final boolean mWirelessConsentRequired;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700221
Marie Janssen59804562016-12-28 14:13:21 -0800222 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
fredcbf072a72012-05-09 16:52:50 -0700223 @Override
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800224 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
225 Message msg =
226 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
fredcbf072a72012-05-09 16:52:50 -0700227 mHandler.sendMessage(msg);
228 }
229 };
230
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100231 private final UserRestrictionsListener mUserRestrictionsListener =
232 new UserRestrictionsListener() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800233 @Override
234 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
235 Bundle prevRestrictions) {
Myles Watson6291fae2017-06-29 03:12:02 -0700236
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800237 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
238 UserManager.DISALLOW_BLUETOOTH_SHARING)) {
239 updateOppLauncherComponentState(userId,
240 newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
241 }
Pavel Grafov4f4f6f82017-03-28 13:44:04 +0100242
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800243 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
244 if (userId == UserHandle.USER_SYSTEM
245 && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
246 newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
247 if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
248 UserManager.DISALLOW_BLUETOOTH)) {
249 updateOppLauncherComponentState(userId, true); // Sharing disallowed
Jack He8caab152018-03-02 13:08:36 -0800250 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
251 mContext.getPackageName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800252 } else {
253 updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
254 UserManager.DISALLOW_BLUETOOTH_SHARING));
255 }
256 }
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100257 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800258 };
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100259
Ajay Panicker467bc042017-02-22 12:23:15 -0800260 private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
261 @Override
262 public void onChange(boolean unused) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800263 synchronized (this) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800264 if (isBluetoothPersistedStateOn()) {
265 if (isAirplaneModeOn()) {
266 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
267 } else {
268 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
269 }
270 }
271
272 int st = BluetoothAdapter.STATE_OFF;
273 try {
274 mBluetoothLock.readLock().lock();
275 if (mBluetooth != null) {
276 st = mBluetooth.getState();
277 }
278 } catch (RemoteException e) {
279 Slog.e(TAG, "Unable to call getState", e);
280 return;
281 } finally {
282 mBluetoothLock.readLock().unlock();
283 }
284
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800285 Slog.d(TAG,
286 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState(
Rene Mayrhofer7d6c8e52018-11-28 11:32:40 -0800287 st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
Ajay Panicker467bc042017-02-22 12:23:15 -0800288
289 if (isAirplaneModeOn()) {
290 // Clear registered LE apps to force shut-off
291 clearBleApps();
292
293 // If state is BLE_ON make sure we trigger disableBLE
294 if (st == BluetoothAdapter.STATE_BLE_ON) {
295 try {
296 mBluetoothLock.readLock().lock();
297 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700298 addActiveLog(
299 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
300 mContext.getPackageName(), false);
Ajay Panicker467bc042017-02-22 12:23:15 -0800301 mBluetooth.onBrEdrDown();
302 mEnable = false;
303 mEnableExternal = false;
304 }
305 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800306 Slog.e(TAG, "Unable to call onBrEdrDown", e);
Ajay Panicker467bc042017-02-22 12:23:15 -0800307 } finally {
308 mBluetoothLock.readLock().unlock();
309 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800310 } else if (st == BluetoothAdapter.STATE_ON) {
Jack He8caab152018-03-02 13:08:36 -0800311 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
312 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800313 }
314 } else if (mEnableExternal) {
Jack He8caab152018-03-02 13:08:36 -0800315 sendEnableMsg(mQuietEnableExternal,
316 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
317 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800318 }
319 }
320 }
321 };
322
fredcbf072a72012-05-09 16:52:50 -0700323 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
fredc0f420372012-04-12 00:02:00 -0700324 @Override
325 public void onReceive(Context context, Intent intent) {
326 String action = intent.getAction();
fredcbf072a72012-05-09 16:52:50 -0700327 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
fredc0f420372012-04-12 00:02:00 -0700328 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800329 if (DBG) {
330 Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
331 }
fredc0f420372012-04-12 00:02:00 -0700332 if (newName != null) {
333 storeNameAndAddress(newName, null);
334 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700335 } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
336 String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
337 if (newAddress != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800338 if (DBG) {
339 Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
340 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700341 storeNameAndAddress(null, newAddress);
342 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800343 if (DBG) {
344 Slog.e(TAG, "No Bluetooth Adapter address parameter found");
345 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700346 }
Stanley Tng873b5702017-05-01 21:27:31 -0700347 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
348 final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
349 if (Settings.Global.BLUETOOTH_ON.equals(name)) {
350 // The Bluetooth On state may be changed during system restore.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800351 final String prevValue =
352 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
353 final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
Stanley Tng873b5702017-05-01 21:27:31 -0700354
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800355 if (DBG) {
356 Slog.d(TAG,
357 "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue
358 + ", newValue=" + newValue);
359 }
Stanley Tng873b5702017-05-01 21:27:31 -0700360
361 if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
362 Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800363 newValue.equals("0") ? RESTORE_SETTING_TO_OFF
364 : RESTORE_SETTING_TO_ON, 0);
Stanley Tng873b5702017-05-01 21:27:31 -0700365 mHandler.sendMessage(msg);
366 }
367 }
fredc0f420372012-04-12 00:02:00 -0700368 }
369 }
370 };
371
372 BluetoothManagerService(Context context) {
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700373 mHandler = new BluetoothHandler(IoThread.get().getLooper());
Zhihai Xu40874a02012-10-08 17:57:03 -0700374
fredc0f420372012-04-12 00:02:00 -0700375 mContext = context;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700376
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700377 mWirelessConsentRequired = context.getResources()
378 .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700379
Marie Janssene54b4222017-03-16 18:10:59 -0700380 mCrashes = 0;
fredc0f420372012-04-12 00:02:00 -0700381 mBluetooth = null;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800382 mBluetoothBinder = null;
Nitin Arorad055adb2015-03-02 15:03:51 -0800383 mBluetoothGatt = null;
fredc0f420372012-04-12 00:02:00 -0700384 mBinding = false;
385 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -0700386 mEnable = false;
387 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800388 mQuietEnableExternal = false;
389 mEnableExternal = false;
fredc0f420372012-04-12 00:02:00 -0700390 mAddress = null;
391 mName = null;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800392 mErrorRecoveryRetryCounter = 0;
fredc0f420372012-04-12 00:02:00 -0700393 mContentResolver = context.getContentResolver();
Wei Wange4a744b2015-06-11 17:50:29 -0700394 // Observe BLE scan only mode settings change.
395 registerForBleScanModeChange();
fredcd6883532012-04-25 17:46:13 -0700396 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
397 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
Stanley Tng873b5702017-05-01 21:27:31 -0700398
Stanley Tng61dbd812019-01-13 16:04:31 -0800399 mIsHearingAidProfileSupported = context.getResources()
400 .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);
401
Stanley Tngfe8c8332018-06-19 08:48:10 -0700402 // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
Stanley Tngfe8c8332018-06-19 08:48:10 -0700403 String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
404 if (!TextUtils.isEmpty(value)) {
Stanley Tng61dbd812019-01-13 16:04:31 -0800405 boolean isHearingAidEnabled = Boolean.parseBoolean(value);
Stanley Tngfe8c8332018-06-19 08:48:10 -0700406 Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
407 FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
Stanley Tng61dbd812019-01-13 16:04:31 -0800408 if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
409 // Overwrite to enable support by FeatureFlag
410 mIsHearingAidProfileSupported = true;
411 }
Stanley Tngfe8c8332018-06-19 08:48:10 -0700412 }
413
Stanley Tng873b5702017-05-01 21:27:31 -0700414 IntentFilter filter = new IntentFilter();
415 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
416 filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
417 filter.addAction(Intent.ACTION_SETTING_RESTORED);
Dianne Hackbornd83a0962014-05-02 16:28:33 -0700418 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Matthew Xie6fde3092012-07-11 17:10:07 -0700419 mContext.registerReceiver(mReceiver, filter);
Stanley Tng873b5702017-05-01 21:27:31 -0700420
fredc0f420372012-04-12 00:02:00 -0700421 loadStoredNameAndAddress();
Zhihai Xu401202b2012-12-03 11:36:21 -0800422 if (isBluetoothPersistedStateOn()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800423 if (DBG) {
424 Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
425 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800426 mEnableExternal = true;
fredc0f420372012-04-12 00:02:00 -0700427 }
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200428
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800429 String airplaneModeRadios =
430 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
431 if (airplaneModeRadios == null || airplaneModeRadios.contains(
432 Settings.Global.RADIO_BLUETOOTH)) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800433 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800434 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
435 mAirplaneModeObserver);
Ajay Panicker467bc042017-02-22 12:23:15 -0800436 }
437
Marie Janssen59804562016-12-28 14:13:21 -0800438 int systemUiUid = -1;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200439 try {
Arthur Hsuf3f95a92018-01-11 16:46:22 -0800440 // Check if device is configured with no home screen, which implies no SystemUI.
441 boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
442 if (!noHome) {
443 systemUiUid = mContext.getPackageManager()
444 .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
445 UserHandle.USER_SYSTEM);
446 }
447 Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200448 } catch (PackageManager.NameNotFoundException e) {
Joe LaPennaacddf2b2015-09-04 12:52:42 -0700449 // Some platforms, such as wearables do not have a system ui.
Jeff Sharkey67609c72016-03-05 14:29:13 -0700450 Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200451 }
Marie Janssen59804562016-12-28 14:13:21 -0800452 mSystemUiUid = systemUiUid;
fredc0f420372012-04-12 00:02:00 -0700453 }
454
fredc649fe492012-04-19 01:07:18 -0700455 /**
456 * Returns true if airplane mode is currently on
457 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800458 private boolean isAirplaneModeOn() {
Christopher Tatec09cdce2012-09-10 16:50:14 -0700459 return Settings.Global.getInt(mContext.getContentResolver(),
460 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
fredc649fe492012-04-19 01:07:18 -0700461 }
462
Arthur Hsu2433baf2018-01-11 11:05:11 -0800463 private boolean supportBluetoothPersistedState() {
464 return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
465 }
466
fredc649fe492012-04-19 01:07:18 -0700467 /**
468 * Returns true if the Bluetooth saved state is "on"
469 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800470 private boolean isBluetoothPersistedStateOn() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800471 if (!supportBluetoothPersistedState()) {
472 return false;
473 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800474 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
475 if (DBG) {
476 Slog.d(TAG, "Bluetooth persisted state: " + state);
477 }
Marie Janssen9fa24912016-10-18 10:04:24 -0700478 return state != BLUETOOTH_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800479 }
480
481 /**
482 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
483 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800484 private boolean isBluetoothPersistedStateOnBluetooth() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800485 if (!supportBluetoothPersistedState()) {
486 return false;
487 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800488 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
489 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
fredc649fe492012-04-19 01:07:18 -0700490 }
491
492 /**
493 * Save the Bluetooth on/off state
fredc649fe492012-04-19 01:07:18 -0700494 */
Zhihai Xu401202b2012-12-03 11:36:21 -0800495 private void persistBluetoothSetting(int value) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800496 if (DBG) {
497 Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
498 }
Marie Janssenfa630682016-12-15 13:51:30 -0800499 // waive WRITE_SECURE_SETTINGS permission check
500 long callingIdentity = Binder.clearCallingIdentity();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800501 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value);
Marie Janssenfa630682016-12-15 13:51:30 -0800502 Binder.restoreCallingIdentity(callingIdentity);
fredc649fe492012-04-19 01:07:18 -0700503 }
504
505 /**
506 * Returns true if the Bluetooth Adapter's name and address is
507 * locally cached
508 * @return
509 */
fredc0f420372012-04-12 00:02:00 -0700510 private boolean isNameAndAddressSet() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800511 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
fredc0f420372012-04-12 00:02:00 -0700512 }
513
fredc649fe492012-04-19 01:07:18 -0700514 /**
515 * Retrieve the Bluetooth Adapter's name and address and save it in
516 * in the local cache
517 */
fredc0f420372012-04-12 00:02:00 -0700518 private void loadStoredNameAndAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800519 if (DBG) {
520 Slog.d(TAG, "Loading stored name and address");
521 }
522 if (mContext.getResources()
523 .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
524 && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0)
525 == 0) {
Zhihai Xud31c3222012-10-31 16:08:57 -0700526 // if the valid flag is not set, don't load the address and name
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800527 if (DBG) {
528 Slog.d(TAG, "invalid bluetooth name and address stored");
529 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700530 return;
531 }
fredc0f420372012-04-12 00:02:00 -0700532 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
533 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800534 if (DBG) {
535 Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
536 }
fredc0f420372012-04-12 00:02:00 -0700537 }
538
fredc649fe492012-04-19 01:07:18 -0700539 /**
540 * Save the Bluetooth name and address in the persistent store.
541 * Only non-null values will be saved.
542 * @param name
543 * @param address
544 */
fredc0f420372012-04-12 00:02:00 -0700545 private void storeNameAndAddress(String name, String address) {
546 if (name != null) {
547 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
fredc0f420372012-04-12 00:02:00 -0700548 mName = name;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800549 if (DBG) {
550 Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver,
551 SECURE_SETTINGS_BLUETOOTH_NAME));
552 }
fredc0f420372012-04-12 00:02:00 -0700553 }
554
555 if (address != null) {
556 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800557 mAddress = address;
558 if (DBG) {
559 Slog.d(TAG,
560 "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver,
561 SECURE_SETTINGS_BLUETOOTH_ADDRESS));
562 }
fredc0f420372012-04-12 00:02:00 -0700563 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700564
565 if ((name != null) && (address != null)) {
566 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
567 }
fredc0f420372012-04-12 00:02:00 -0700568 }
569
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800570 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700571 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700572 Slog.w(TAG, "Callback is null in registerAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700573 return null;
574 }
fredc0f420372012-04-12 00:02:00 -0700575 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
576 msg.obj = callback;
577 mHandler.sendMessage(msg);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700578
579 return mBluetooth;
fredc0f420372012-04-12 00:02:00 -0700580 }
581
582 public void unregisterAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700583 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700584 Slog.w(TAG, "Callback is null in unregisterAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700585 return;
586 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800587 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
fredc0f420372012-04-12 00:02:00 -0700588 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
589 msg.obj = callback;
590 mHandler.sendMessage(msg);
591 }
592
593 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800594 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800595 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800596 Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
597 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800598 }
fredc0f420372012-04-12 00:02:00 -0700599 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
600 msg.obj = callback;
601 mHandler.sendMessage(msg);
602 }
603
604 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800605 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800606 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800607 Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
608 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800609 }
fredc0f420372012-04-12 00:02:00 -0700610 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
611 msg.obj = callback;
612 mHandler.sendMessage(msg);
613 }
614
615 public boolean isEnabled() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800616 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
617 Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user");
Zhihai Xu40874a02012-10-08 17:57:03 -0700618 return false;
619 }
620
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700621 try {
622 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800623 if (mBluetooth != null) {
624 return mBluetooth.isEnabled();
625 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700626 } catch (RemoteException e) {
627 Slog.e(TAG, "isEnabled()", e);
628 } finally {
629 mBluetoothLock.readLock().unlock();
fredc0f420372012-04-12 00:02:00 -0700630 }
631 return false;
632 }
633
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700634 public int getState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800635 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
Marie Janssencb21ad72016-12-13 10:51:02 -0800636 Slog.w(TAG, "getState(): report OFF for non-active and non system user");
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700637 return BluetoothAdapter.STATE_OFF;
638 }
639
640 try {
641 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800642 if (mBluetooth != null) {
643 return mBluetooth.getState();
644 }
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700645 } catch (RemoteException e) {
646 Slog.e(TAG, "getState()", e);
647 } finally {
648 mBluetoothLock.readLock().unlock();
649 }
650 return BluetoothAdapter.STATE_OFF;
651 }
652
Nitin Arorad055adb2015-03-02 15:03:51 -0800653 class ClientDeathRecipient implements IBinder.DeathRecipient {
Marie Janssen59804562016-12-28 14:13:21 -0800654 private String mPackageName;
655
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800656 ClientDeathRecipient(String packageName) {
Marie Janssen59804562016-12-28 14:13:21 -0800657 mPackageName = packageName;
658 }
659
Nitin Arorad055adb2015-03-02 15:03:51 -0800660 public void binderDied() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800661 if (DBG) {
662 Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
Marie Janssen2977c3e2016-11-09 12:01:24 -0800663 }
Stanley Tng2c5fd282018-03-19 13:06:45 -0700664
665 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
666 IBinder token = entry.getKey();
667 ClientDeathRecipient deathRec = entry.getValue();
668 if (deathRec.equals(this)) {
Stanley Tng600109c2018-03-20 16:54:27 -0700669 updateBleAppCount(token, false, mPackageName);
Stanley Tng2c5fd282018-03-19 13:06:45 -0700670 break;
671 }
672 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800673 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800674
Marie Janssen59804562016-12-28 14:13:21 -0800675 public String getPackageName() {
676 return mPackageName;
677 }
678 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800679
Wei Wang67d84162015-04-26 17:04:29 -0700680 @Override
681 public boolean isBleScanAlwaysAvailable() {
Marie Janssena80d7452016-10-25 10:47:51 -0700682 if (isAirplaneModeOn() && !mEnable) {
683 return false;
684 }
Wei Wang67d84162015-04-26 17:04:29 -0700685 try {
Jack He8caab152018-03-02 13:08:36 -0800686 return Settings.Global.getInt(mContentResolver,
687 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
Wei Wang67d84162015-04-26 17:04:29 -0700688 } catch (SettingNotFoundException e) {
689 }
690 return false;
691 }
692
Stanley Tng61dbd812019-01-13 16:04:31 -0800693 @Override
694 public boolean isHearingAidProfileSupported() {
695 return mIsHearingAidProfileSupported;
696 }
697
Wei Wange4a744b2015-06-11 17:50:29 -0700698 // Monitor change of BLE scan only mode settings.
699 private void registerForBleScanModeChange() {
700 ContentObserver contentObserver = new ContentObserver(null) {
701 @Override
702 public void onChange(boolean selfChange) {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800703 if (isBleScanAlwaysAvailable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800704 // Nothing to do
705 return;
Marie Janssen2977c3e2016-11-09 12:01:24 -0800706 }
707 // BLE scan is not available.
708 disableBleScanMode();
709 clearBleApps();
710 try {
711 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800712 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700713 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
714 mContext.getPackageName(), false);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800715 mBluetooth.onBrEdrDown();
716 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800717 } catch (RemoteException e) {
718 Slog.e(TAG, "error when disabling bluetooth", e);
719 } finally {
720 mBluetoothLock.readLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700721 }
722 }
723 };
724
725 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800726 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
727 contentObserver);
Wei Wange4a744b2015-06-11 17:50:29 -0700728 }
729
730 // Disable ble scan only mode.
731 private void disableBleScanMode() {
732 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700733 mBluetoothLock.writeLock().lock();
Wei Wange4a744b2015-06-11 17:50:29 -0700734 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800735 if (DBG) {
736 Slog.d(TAG, "Reseting the mEnable flag for clean disable");
737 }
Wei Wange4a744b2015-06-11 17:50:29 -0700738 mEnable = false;
739 }
740 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700741 Slog.e(TAG, "getState()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700742 } finally {
743 mBluetoothLock.writeLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700744 }
745 }
746
Marie Janssen59804562016-12-28 14:13:21 -0800747 public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
Jack Hea80cead2019-04-23 20:00:18 -0700748 // Check if packageName belongs to callingUid
749 final int callingUid = Binder.getCallingUid();
750 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
751 if (!isCallerSystem) {
752 checkPackage(callingUid, packageName);
753 }
Marie Janssen59804562016-12-28 14:13:21 -0800754 ClientDeathRecipient r = mBleApps.get(token);
755 if (r == null && enable) {
756 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
757 try {
758 token.linkToDeath(deathRec, 0);
759 } catch (RemoteException ex) {
760 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
Nitin Arorad055adb2015-03-02 15:03:51 -0800761 }
Marie Janssen59804562016-12-28 14:13:21 -0800762 mBleApps.put(token, deathRec);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800763 if (DBG) {
764 Slog.d(TAG, "Registered for death of " + packageName);
765 }
Marie Janssen59804562016-12-28 14:13:21 -0800766 } else if (!enable && r != null) {
767 // Unregister death recipient as the app goes away.
768 token.unlinkToDeath(r, 0);
769 mBleApps.remove(token);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800770 if (DBG) {
771 Slog.d(TAG, "Unregistered for death of " + packageName);
772 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800773 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800774 int appCount = mBleApps.size();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800775 if (DBG) {
776 Slog.d(TAG, appCount + " registered Ble Apps");
777 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800778 if (appCount == 0 && mEnable) {
Wei Wange4a744b2015-06-11 17:50:29 -0700779 disableBleScanMode();
Nitin Arorad055adb2015-03-02 15:03:51 -0800780 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800781 if (appCount == 0 && !mEnableExternal) {
782 sendBrEdrDownCallback();
783 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800784 return appCount;
Nitin Arorad055adb2015-03-02 15:03:51 -0800785 }
786
Wei Wange4a744b2015-06-11 17:50:29 -0700787 // Clear all apps using BLE scan only mode.
788 private void clearBleApps() {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800789 mBleApps.clear();
Wei Wange4a744b2015-06-11 17:50:29 -0700790 }
791
Marie Janssen59804562016-12-28 14:13:21 -0800792 /** @hide */
Nitin Arorad055adb2015-03-02 15:03:51 -0800793 public boolean isBleAppPresent() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800794 if (DBG) {
795 Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
796 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800797 return mBleApps.size() > 0;
Nitin Arorad055adb2015-03-02 15:03:51 -0800798 }
799
800 /**
Myles Watson304ebf22018-05-11 08:47:24 -0700801 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
Nitin Arorad055adb2015-03-02 15:03:51 -0800802 */
Myles Watson304ebf22018-05-11 08:47:24 -0700803 private void continueFromBleOnState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800804 if (DBG) {
Myles Watson304ebf22018-05-11 08:47:24 -0700805 Slog.d(TAG, "continueFromBleOnState()");
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800806 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700807 try {
808 mBluetoothLock.readLock().lock();
Marie Janssenfa630682016-12-15 13:51:30 -0800809 if (mBluetooth == null) {
Myles Watson304ebf22018-05-11 08:47:24 -0700810 Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
Marie Janssenfa630682016-12-15 13:51:30 -0800811 return;
812 }
813 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
814 // This triggers transition to STATE_ON
Nitin Arorad055adb2015-03-02 15:03:51 -0800815 mBluetooth.onLeServiceUp();
Nitin Arorad055adb2015-03-02 15:03:51 -0800816 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Nitin Arorad055adb2015-03-02 15:03:51 -0800817 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700818 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800819 Slog.e(TAG, "Unable to call onServiceUp", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700820 } finally {
821 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800822 }
823 }
824
825 /**
826 * Inform BluetoothAdapter instances that BREDR part is down
827 * and turn off all service and stack if no LE app needs it
828 */
829 private void sendBrEdrDownCallback() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800830 if (DBG) {
831 Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
832 }
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700833
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700834 if (mBluetooth == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700835 Slog.w(TAG, "Bluetooth handle is null");
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700836 return;
837 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800838
Martin Brabhamc2b06222017-02-27 16:55:07 -0800839 if (isBleAppPresent()) {
840 // Need to stay at BLE ON. Disconnect all Gatt connections
841 try {
842 mBluetoothGatt.unregAll();
843 } catch (RemoteException e) {
844 Slog.e(TAG, "Unable to disconnect all apps.", e);
845 }
846 } else {
Nitin Arorad055adb2015-03-02 15:03:51 -0800847 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700848 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800849 if (mBluetooth != null) {
850 mBluetooth.onBrEdrDown();
851 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700852 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700853 Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700854 } finally {
855 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800856 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800857 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800858
Nitin Arorad055adb2015-03-02 15:03:51 -0800859 }
860
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800861 public boolean enableNoAutoConnect(String packageName) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100862 if (isBluetoothDisallowed()) {
863 if (DBG) {
864 Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
865 }
866 return false;
867 }
868
Jack Hea80cead2019-04-23 20:00:18 -0700869 // Check if packageName belongs to callingUid
870 final int callingUid = Binder.getCallingUid();
871 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
872 if (!isCallerSystem) {
873 checkPackage(callingUid, packageName);
874 }
875
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700876 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800877 "Need BLUETOOTH ADMIN permission");
Zhihai Xu40874a02012-10-08 17:57:03 -0700878
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700879 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800880 Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = "
881 + mBinding);
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700882 }
Jack Hea80cead2019-04-23 20:00:18 -0700883 int callingAppId = UserHandle.getAppId(callingUid);
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800884
885 if (callingAppId != Process.NFC_UID) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700886 throw new SecurityException("no permission to enable Bluetooth quietly");
887 }
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800888
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800889 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800890 mQuietEnableExternal = true;
891 mEnableExternal = true;
Jack He8caab152018-03-02 13:08:36 -0800892 sendEnableMsg(true,
893 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800894 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700895 return true;
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700896 }
Ajay Panicker4bb48302016-03-31 14:14:27 -0700897
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700898 public boolean enable(String packageName) throws RemoteException {
899 final int callingUid = Binder.getCallingUid();
900 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
901
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100902 if (isBluetoothDisallowed()) {
903 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800904 Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100905 }
906 return false;
907 }
908
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700909 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700910 // Check if packageName belongs to callingUid
911 checkPackage(callingUid, packageName);
912
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700913 if (!checkIfCallerIsForegroundUser()) {
914 Slog.w(TAG, "enable(): not allowed for non-active and non system user");
915 return false;
916 }
917
918 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
919 "Need BLUETOOTH ADMIN permission");
920
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700921 if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800922 callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700923 return false;
924 }
fredcf2458862012-04-16 15:18:27 -0700925 }
926
Zhihai Xu401202b2012-12-03 11:36:21 -0800927 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800928 Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
929 + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
Sanket Agarwal090bf552016-04-21 14:10:55 -0700930 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800931
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800932 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800933 mQuietEnableExternal = false;
934 mEnableExternal = true;
935 // waive WRITE_SECURE_SETTINGS permission check
Jack He8caab152018-03-02 13:08:36 -0800936 sendEnableMsg(false,
937 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800938 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800939 if (DBG) {
940 Slog.d(TAG, "enable returning");
941 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800942 return true;
fredc0f420372012-04-12 00:02:00 -0700943 }
944
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700945 public boolean disable(String packageName, boolean persist) throws RemoteException {
946 final int callingUid = Binder.getCallingUid();
947 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
Zhihai Xu40874a02012-10-08 17:57:03 -0700948
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700949 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700950 // Check if packageName belongs to callingUid
951 checkPackage(callingUid, packageName);
952
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700953 if (!checkIfCallerIsForegroundUser()) {
954 Slog.w(TAG, "disable(): not allowed for non-active and non system user");
955 return false;
956 }
957
958 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
959 "Need BLUETOOTH ADMIN permission");
960
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700961 if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800962 callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700963 return false;
964 }
Zhihai Xu40874a02012-10-08 17:57:03 -0700965 }
966
fredcf2458862012-04-16 15:18:27 -0700967 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800968 Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
Matthew Xiecdce0b92012-07-12 19:06:15 -0700969 }
fredcf2458862012-04-16 15:18:27 -0700970
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800971 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800972 if (persist) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800973 persistBluetoothSetting(BLUETOOTH_OFF);
Zhihai Xu401202b2012-12-03 11:36:21 -0800974 }
975 mEnableExternal = false;
Jack He8caab152018-03-02 13:08:36 -0800976 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
977 packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800978 }
fredc0f420372012-04-12 00:02:00 -0700979 return true;
980 }
981
baishengf62d8692018-01-25 18:07:24 +0800982 private boolean startConsentUiIfNeeded(String packageName,
983 int callingUid, String intentAction) throws RemoteException {
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700984 if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
baishengf62d8692018-01-25 18:07:24 +0800985 return false;
986 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700987 try {
988 // Validate the package only if we are going to use it
989 ApplicationInfo applicationInfo = mContext.getPackageManager()
990 .getApplicationInfoAsUser(packageName,
991 PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
992 UserHandle.getUserId(callingUid));
993 if (applicationInfo.uid != callingUid) {
baishengf62d8692018-01-25 18:07:24 +0800994 throw new SecurityException("Package " + packageName
995 + " not in uid " + callingUid);
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700996 }
997
Ivan Podogovd2d32b12016-12-05 16:46:52 +0000998 Intent intent = new Intent(intentAction);
Ivan Podogov1ab87252017-01-03 12:02:18 +0000999 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001000 intent.setFlags(
1001 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001002 try {
1003 mContext.startActivity(intent);
1004 } catch (ActivityNotFoundException e) {
1005 // Shouldn't happen
1006 Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
1007 return false;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001008 }
Ivan Podogov1ab87252017-01-03 12:02:18 +00001009 return true;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001010 } catch (PackageManager.NameNotFoundException e) {
1011 throw new RemoteException(e.getMessage());
1012 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001013 }
1014
baishengf62d8692018-01-25 18:07:24 +08001015 /**
Jack Hea80cead2019-04-23 20:00:18 -07001016 * Check if AppOpsManager is available and the packageName belongs to uid
1017 *
1018 * A null package belongs to any uid
1019 */
1020 private void checkPackage(int uid, String packageName) {
1021 if (mAppOps == null) {
1022 Slog.w(TAG, "checkPackage(): called before system boot up, uid "
1023 + uid + ", packageName " + packageName);
1024 throw new IllegalStateException("System has not boot yet");
1025 }
1026 if (packageName == null) {
1027 Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
1028 return;
1029 }
1030 try {
1031 mAppOps.checkPackage(uid, packageName);
1032 } catch (SecurityException e) {
1033 Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
Jack Hea80cead2019-04-23 20:00:18 -07001034 throw new SecurityException(e.getMessage());
1035 }
1036 }
1037
1038 /**
baishengf62d8692018-01-25 18:07:24 +08001039 * Check if the caller must still pass permission check or if the caller is exempted
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001040 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
baishengf62d8692018-01-25 18:07:24 +08001041 *
1042 * Commands from some callers may be exempted from triggering the consent UI when
1043 * enabling bluetooth. This exemption is checked via the
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001044 * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
baishengf62d8692018-01-25 18:07:24 +08001045 * the consent UI where it may otherwise be required.
1046 *
1047 * @hide
1048 */
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001049 private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
baishengf62d8692018-01-25 18:07:24 +08001050 int result = mContext.checkCallingPermission(
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001051 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
baishengf62d8692018-01-25 18:07:24 +08001052 return result == PackageManager.PERMISSION_GRANTED;
1053 }
1054
fredc649fe492012-04-19 01:07:18 -07001055 public void unbindAndFinish() {
fredcf2458862012-04-16 15:18:27 -07001056 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001057 Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
1058 + " mUnbinding = " + mUnbinding);
fredcf2458862012-04-16 15:18:27 -07001059 }
1060
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001061 try {
1062 mBluetoothLock.writeLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001063 if (mUnbinding) {
1064 return;
1065 }
fredc0f420372012-04-12 00:02:00 -07001066 mUnbinding = true;
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001067 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
Pavlin Radoslavov74f60c02016-09-21 17:28:11 -07001068 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
Zhihai Xu40874a02012-10-08 17:57:03 -07001069 if (mBluetooth != null) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001070 //Unregister callback object
1071 try {
1072 mBluetooth.unregisterCallback(mBluetoothCallback);
1073 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001074 Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001075 }
Marie Janssen9db28eb2016-01-12 16:05:15 -08001076 mBluetoothBinder = null;
fredcd6883532012-04-25 17:46:13 -07001077 mBluetooth = null;
fredc0f420372012-04-12 00:02:00 -07001078 mContext.unbindService(mConnection);
fredcd6883532012-04-25 17:46:13 -07001079 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -07001080 mBinding = false;
fredcf2458862012-04-16 15:18:27 -07001081 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001082 mUnbinding = false;
fredc0f420372012-04-12 00:02:00 -07001083 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001084 mBluetoothGatt = null;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001085 } finally {
1086 mBluetoothLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -07001087 }
1088 }
1089
Matthew Xieddf7e472013-03-01 18:41:02 -08001090 public IBluetoothGatt getBluetoothGatt() {
1091 // sync protection
1092 return mBluetoothGatt;
1093 }
1094
Benjamin Franze8b98922014-11-12 15:57:54 +00001095 @Override
1096 public boolean bindBluetoothProfileService(int bluetoothProfile,
1097 IBluetoothProfileServiceConnection proxy) {
1098 if (!mEnable) {
1099 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001100 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
1101 + ", while Bluetooth was disabled");
Benjamin Franze8b98922014-11-12 15:57:54 +00001102 }
1103 return false;
1104 }
1105 synchronized (mProfileServices) {
1106 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
1107 if (psc == null) {
1108 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001109 Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
1110 + bluetoothProfile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001111 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001112
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001113 if (bluetoothProfile != BluetoothProfile.HEADSET) {
1114 return false;
1115 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001116
1117 Intent intent = new Intent(IBluetoothHeadset.class.getName());
Benjamin Franze8b98922014-11-12 15:57:54 +00001118 psc = new ProfileServiceConnections(intent);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001119 if (!psc.bindService()) {
1120 return false;
1121 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001122
Benjamin Franze8b98922014-11-12 15:57:54 +00001123 mProfileServices.put(new Integer(bluetoothProfile), psc);
Benjamin Franze8b98922014-11-12 15:57:54 +00001124 }
1125 }
1126
1127 // Introducing a delay to give the client app time to prepare
1128 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
1129 addProxyMsg.arg1 = bluetoothProfile;
1130 addProxyMsg.obj = proxy;
1131 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
1132 return true;
1133 }
1134
1135 @Override
1136 public void unbindBluetoothProfileService(int bluetoothProfile,
1137 IBluetoothProfileServiceConnection proxy) {
1138 synchronized (mProfileServices) {
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001139 Integer profile = new Integer(bluetoothProfile);
1140 ProfileServiceConnections psc = mProfileServices.get(profile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001141 if (psc == null) {
1142 return;
1143 }
1144 psc.removeProxy(proxy);
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001145 if (psc.isEmpty()) {
1146 // All prxoies are disconnected, unbind with the service.
1147 try {
1148 mContext.unbindService(psc);
1149 } catch (IllegalArgumentException e) {
1150 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
1151 }
1152 mProfileServices.remove(profile);
1153 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001154 }
1155 }
1156
1157 private void unbindAllBluetoothProfileServices() {
1158 synchronized (mProfileServices) {
1159 for (Integer i : mProfileServices.keySet()) {
1160 ProfileServiceConnections psc = mProfileServices.get(i);
Benjamin Franz5b614592014-12-09 18:58:45 +00001161 try {
1162 mContext.unbindService(psc);
1163 } catch (IllegalArgumentException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001164 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
Benjamin Franz5b614592014-12-09 18:58:45 +00001165 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001166 psc.removeAllProxies();
1167 }
1168 mProfileServices.clear();
1169 }
1170 }
1171
1172 /**
Miao Chou658bf2f2015-06-26 17:14:35 -07001173 * Send enable message and set adapter name and address. Called when the boot phase becomes
1174 * PHASE_SYSTEM_SERVICES_READY.
1175 */
1176 public void handleOnBootPhase() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001177 if (DBG) {
1178 Slog.d(TAG, "Bluetooth boot completed");
1179 }
Jack Hea80cead2019-04-23 20:00:18 -07001180 mAppOps = mContext.getSystemService(AppOpsManager.class);
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001181 UserManagerInternal userManagerInternal =
1182 LocalServices.getService(UserManagerInternal.class);
1183 userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001184 final boolean isBluetoothDisallowed = isBluetoothDisallowed();
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001185 if (isBluetoothDisallowed) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001186 return;
1187 }
Miao Chou658bf2f2015-06-26 17:14:35 -07001188 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001189 if (DBG) {
1190 Slog.d(TAG, "Auto-enabling Bluetooth.");
1191 }
Jack He8caab152018-03-02 13:08:36 -08001192 sendEnableMsg(mQuietEnableExternal,
1193 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
1194 mContext.getPackageName());
Ajay Panickerbf796d82016-03-11 13:47:20 -08001195 } else if (!isNameAndAddressSet()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001196 if (DBG) {
1197 Slog.d(TAG, "Getting adapter name and address");
1198 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001199 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1200 mHandler.sendMessage(getMsg);
Miao Chou658bf2f2015-06-26 17:14:35 -07001201 }
Miao Chou658bf2f2015-06-26 17:14:35 -07001202 }
1203
1204 /**
1205 * Called when switching to a different foreground user.
1206 */
1207 public void handleOnSwitchUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001208 if (DBG) {
1209 Slog.d(TAG, "User " + userHandle + " switched");
1210 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001211 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1212 }
1213
1214 /**
1215 * Called when user is unlocked.
1216 */
1217 public void handleOnUnlockUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001218 if (DBG) {
1219 Slog.d(TAG, "User " + userHandle + " unlocked");
1220 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001221 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
Miao Chou658bf2f2015-06-26 17:14:35 -07001222 }
1223
1224 /**
Benjamin Franze8b98922014-11-12 15:57:54 +00001225 * This class manages the clients connected to a given ProfileService
1226 * and maintains the connection with that service.
1227 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001228 private final class ProfileServiceConnections
1229 implements ServiceConnection, IBinder.DeathRecipient {
Benjamin Franze8b98922014-11-12 15:57:54 +00001230 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001231 new RemoteCallbackList<IBluetoothProfileServiceConnection>();
Benjamin Franze8b98922014-11-12 15:57:54 +00001232 IBinder mService;
1233 ComponentName mClassName;
1234 Intent mIntent;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001235 boolean mInvokingProxyCallbacks = false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001236
1237 ProfileServiceConnections(Intent intent) {
1238 mService = null;
1239 mClassName = null;
1240 mIntent = intent;
1241 }
1242
Benjamin Franz5b614592014-12-09 18:58:45 +00001243 private boolean bindService() {
jonerlin37fc85d2018-08-09 16:39:43 +08001244 int state = BluetoothAdapter.STATE_OFF;
1245 try {
1246 mBluetoothLock.readLock().lock();
1247 if (mBluetooth != null) {
1248 state = mBluetooth.getState();
1249 }
1250 } catch (RemoteException e) {
1251 Slog.e(TAG, "Unable to call getState", e);
1252 return false;
1253 } finally {
1254 mBluetoothLock.readLock().unlock();
1255 }
1256
1257 if (!mEnable || state != BluetoothAdapter.STATE_ON) {
1258 if (DBG) {
1259 Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
1260 }
1261 return false;
1262 }
1263
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001264 if (mIntent != null && mService == null && doBind(mIntent, this, 0,
1265 UserHandle.CURRENT_OR_SELF)) {
Benjamin Franze8b98922014-11-12 15:57:54 +00001266 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1267 msg.obj = this;
1268 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
Benjamin Franz5b614592014-12-09 18:58:45 +00001269 return true;
Benjamin Franze8b98922014-11-12 15:57:54 +00001270 }
Jeff Sharkey67609c72016-03-05 14:29:13 -07001271 Slog.w(TAG, "Unable to bind with intent: " + mIntent);
Benjamin Franz5b614592014-12-09 18:58:45 +00001272 return false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001273 }
1274
1275 private void addProxy(IBluetoothProfileServiceConnection proxy) {
1276 mProxies.register(proxy);
1277 if (mService != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001278 try {
Benjamin Franze8b98922014-11-12 15:57:54 +00001279 proxy.onServiceConnected(mClassName, mService);
1280 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001281 Slog.e(TAG, "Unable to connect to proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001282 }
1283 } else {
1284 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1285 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1286 msg.obj = this;
1287 mHandler.sendMessage(msg);
1288 }
1289 }
1290 }
1291
1292 private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1293 if (proxy != null) {
1294 if (mProxies.unregister(proxy)) {
1295 try {
1296 proxy.onServiceDisconnected(mClassName);
1297 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001298 Slog.e(TAG, "Unable to disconnect proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001299 }
1300 }
1301 } else {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001302 Slog.w(TAG, "Trying to remove a null proxy");
Benjamin Franze8b98922014-11-12 15:57:54 +00001303 }
1304 }
1305
1306 private void removeAllProxies() {
1307 onServiceDisconnected(mClassName);
1308 mProxies.kill();
1309 }
1310
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001311 private boolean isEmpty() {
1312 return mProxies.getRegisteredCallbackCount() == 0;
1313 }
1314
Benjamin Franze8b98922014-11-12 15:57:54 +00001315 @Override
1316 public void onServiceConnected(ComponentName className, IBinder service) {
1317 // remove timeout message
1318 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1319 mService = service;
1320 mClassName = className;
1321 try {
1322 mService.linkToDeath(this, 0);
1323 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001324 Slog.e(TAG, "Unable to linkToDeath", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001325 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001326
1327 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001328 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001329 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001330 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001331 mInvokingProxyCallbacks = true;
1332
1333 final int n = mProxies.beginBroadcast();
1334 try {
1335 for (int i = 0; i < n; i++) {
1336 try {
1337 mProxies.getBroadcastItem(i).onServiceConnected(className, service);
1338 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001339 Slog.e(TAG, "Unable to connect to proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001340 }
1341 }
1342 } finally {
1343 mProxies.finishBroadcast();
1344 mInvokingProxyCallbacks = false;
1345 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001346 }
1347
1348 @Override
1349 public void onServiceDisconnected(ComponentName className) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001350 if (mService == null) {
1351 return;
1352 }
Chienyuan177156b2018-12-18 10:40:25 +08001353 try {
1354 mService.unlinkToDeath(this, 0);
1355 } catch (NoSuchElementException e) {
1356 Log.e(TAG, "error unlinking to death", e);
1357 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001358 mService = null;
1359 mClassName = null;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001360
1361 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001362 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001363 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001364 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001365 mInvokingProxyCallbacks = true;
1366
1367 final int n = mProxies.beginBroadcast();
1368 try {
1369 for (int i = 0; i < n; i++) {
1370 try {
1371 mProxies.getBroadcastItem(i).onServiceDisconnected(className);
1372 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001373 Slog.e(TAG, "Unable to disconnect from proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001374 }
1375 }
1376 } finally {
1377 mProxies.finishBroadcast();
1378 mInvokingProxyCallbacks = false;
1379 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001380 }
1381
1382 @Override
1383 public void binderDied() {
1384 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001385 Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
Benjamin Franze8b98922014-11-12 15:57:54 +00001386 }
1387 onServiceDisconnected(mClassName);
1388 // Trigger rebind
1389 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1390 msg.obj = this;
1391 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1392 }
1393 }
1394
fredcbf072a72012-05-09 16:52:50 -07001395 private void sendBluetoothStateCallback(boolean isUp) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001396 try {
1397 int n = mStateChangeCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001398 if (DBG) {
1399 Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
1400 + " receivers.");
1401 }
1402 for (int i = 0; i < n; i++) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001403 try {
1404 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
1405 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001406 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001407 }
fredcbf072a72012-05-09 16:52:50 -07001408 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001409 } finally {
1410 mStateChangeCallbacks.finishBroadcast();
fredcbf072a72012-05-09 16:52:50 -07001411 }
fredcbf072a72012-05-09 16:52:50 -07001412 }
1413
1414 /**
Zhihai Xu40874a02012-10-08 17:57:03 -07001415 * Inform BluetoothAdapter instances that Adapter service is up
1416 */
1417 private void sendBluetoothServiceUpCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001418 try {
1419 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001420 Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1421 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001422 try {
1423 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001424 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001425 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
Zhihai Xu40874a02012-10-08 17:57:03 -07001426 }
1427 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001428 } finally {
1429 mCallbacks.finishBroadcast();
Zhihai Xu40874a02012-10-08 17:57:03 -07001430 }
1431 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001432
Zhihai Xu40874a02012-10-08 17:57:03 -07001433 /**
fredcbf072a72012-05-09 16:52:50 -07001434 * Inform BluetoothAdapter instances that Adapter service is down
1435 */
1436 private void sendBluetoothServiceDownCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001437 try {
1438 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001439 Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1440 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001441 try {
1442 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001443 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001444 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
fredcd6883532012-04-25 17:46:13 -07001445 }
1446 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001447 } finally {
1448 mCallbacks.finishBroadcast();
fredcd6883532012-04-25 17:46:13 -07001449 }
1450 }
Svet Ganov408abf72015-05-12 19:13:36 -07001451
fredc0f420372012-04-12 00:02:00 -07001452 public String getAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001453 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001454
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001455 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1456 Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001457 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001458 }
1459
Svet Ganov408abf72015-05-12 19:13:36 -07001460 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1461 != PackageManager.PERMISSION_GRANTED) {
1462 return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1463 }
1464
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001465 try {
1466 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001467 if (mBluetooth != null) {
1468 return mBluetooth.getAddress();
1469 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001470 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001471 Slog.e(TAG,
1472 "getAddress(): Unable to retrieve address remotely. Returning cached address",
1473 e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001474 } finally {
1475 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001476 }
Ajay Panickerbf796d82016-03-11 13:47:20 -08001477
Matthew Xiecdce0b92012-07-12 19:06:15 -07001478 // mAddress is accessed from outside.
1479 // It is alright without a lock. Here, bluetooth is off, no other thread is
1480 // changing mAddress
fredc0f420372012-04-12 00:02:00 -07001481 return mAddress;
1482 }
fredc649fe492012-04-19 01:07:18 -07001483
fredc0f420372012-04-12 00:02:00 -07001484 public String getName() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001485 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001486
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001487 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1488 Slog.w(TAG, "getName(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001489 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001490 }
1491
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001492 try {
1493 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001494 if (mBluetooth != null) {
1495 return mBluetooth.getName();
1496 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001497 } catch (RemoteException e) {
1498 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1499 } finally {
1500 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001501 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001502
Matthew Xiecdce0b92012-07-12 19:06:15 -07001503 // mName is accessed from outside.
1504 // It alright without a lock. Here, bluetooth is off, no other thread is
1505 // changing mName
fredc0f420372012-04-12 00:02:00 -07001506 return mName;
1507 }
1508
fredc0f420372012-04-12 00:02:00 -07001509 private class BluetoothServiceConnection implements ServiceConnection {
Marie Janssencb21ad72016-12-13 10:51:02 -08001510 public void onServiceConnected(ComponentName componentName, IBinder service) {
1511 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001512 if (DBG) {
1513 Slog.d(TAG, "BluetoothServiceConnection: " + name);
1514 }
fredc0f420372012-04-12 00:02:00 -07001515 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001516 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001517 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001518 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001519 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1520 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001521 Slog.e(TAG, "Unknown service connected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001522 return;
1523 }
fredc0f420372012-04-12 00:02:00 -07001524 msg.obj = service;
1525 mHandler.sendMessage(msg);
1526 }
1527
Marie Janssencb21ad72016-12-13 10:51:02 -08001528 public void onServiceDisconnected(ComponentName componentName) {
1529 // Called if we unexpectedly disconnect.
1530 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001531 if (DBG) {
1532 Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
1533 }
fredc0f420372012-04-12 00:02:00 -07001534 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001535 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001536 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001537 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001538 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1539 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001540 Slog.e(TAG, "Unknown service disconnected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001541 return;
1542 }
fredc0f420372012-04-12 00:02:00 -07001543 mHandler.sendMessage(msg);
1544 }
1545 }
1546
1547 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1548
Zhihai Xu40874a02012-10-08 17:57:03 -07001549 private class BluetoothHandler extends Handler {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001550 boolean mGetNameAddressOnly = false;
1551
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001552 BluetoothHandler(Looper looper) {
Zhihai Xu40874a02012-10-08 17:57:03 -07001553 super(looper);
1554 }
1555
fredc0f420372012-04-12 00:02:00 -07001556 @Override
1557 public void handleMessage(Message msg) {
fredc0f420372012-04-12 00:02:00 -07001558 switch (msg.what) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001559 case MESSAGE_GET_NAME_AND_ADDRESS:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001560 if (DBG) {
1561 Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1562 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001563 try {
1564 mBluetoothLock.writeLock().lock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001565 if ((mBluetooth == null) && (!mBinding)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001566 if (DBG) {
1567 Slog.d(TAG, "Binding to service to get name and address");
1568 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001569 mGetNameAddressOnly = true;
1570 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1571 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
1572 Intent i = new Intent(IBluetooth.class.getName());
1573 if (!doBind(i, mConnection,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001574 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1575 UserHandle.CURRENT)) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001576 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1577 } else {
1578 mBinding = true;
1579 }
1580 } else if (mBluetooth != null) {
1581 try {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001582 storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress());
Ajay Panicker4bb48302016-03-31 14:14:27 -07001583 } catch (RemoteException re) {
1584 Slog.e(TAG, "Unable to grab names", re);
1585 }
1586 if (mGetNameAddressOnly && !mEnable) {
1587 unbindAndFinish();
1588 }
1589 mGetNameAddressOnly = false;
1590 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001591 } finally {
1592 mBluetoothLock.writeLock().unlock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001593 }
1594 break;
1595
Matthew Xiecdce0b92012-07-12 19:06:15 -07001596 case MESSAGE_ENABLE:
fredcf2458862012-04-16 15:18:27 -07001597 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001598 Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
fredc649fe492012-04-19 01:07:18 -07001599 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001600 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1601 mEnable = true;
Calvin Ona0b91d72016-06-15 17:58:23 -07001602
1603 // Use service interface to get the exact state
1604 try {
1605 mBluetoothLock.readLock().lock();
1606 if (mBluetooth != null) {
1607 int state = mBluetooth.getState();
1608 if (state == BluetoothAdapter.STATE_BLE_ON) {
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001609 Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
Calvin Ona0b91d72016-06-15 17:58:23 -07001610 mBluetooth.onLeServiceUp();
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001611 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Calvin Ona0b91d72016-06-15 17:58:23 -07001612 break;
1613 }
1614 }
1615 } catch (RemoteException e) {
1616 Slog.e(TAG, "", e);
1617 } finally {
1618 mBluetoothLock.readLock().unlock();
1619 }
1620
1621 mQuietEnable = (msg.arg1 == 1);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001622 if (mBluetooth == null) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001623 handleEnable(mQuietEnable);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001624 } else {
1625 //
1626 // We need to wait until transitioned to STATE_OFF and
1627 // the previous Bluetooth process has exited. The
1628 // waiting period has three components:
1629 // (a) Wait until the local state is STATE_OFF. This
1630 // is accomplished by "waitForOnOff(false, true)".
1631 // (b) Wait until the STATE_OFF state is updated to
1632 // all components.
1633 // (c) Wait until the Bluetooth process exits, and
1634 // ActivityManager detects it.
1635 // The waiting for (b) and (c) is accomplished by
1636 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
1637 // message. On slower devices, that delay needs to be
1638 // on the order of (2 * SERVICE_RESTART_TIME_MS).
1639 //
1640 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001641 Message restartMsg =
1642 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1643 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001644 }
fredc649fe492012-04-19 01:07:18 -07001645 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001646
fredc0f420372012-04-12 00:02:00 -07001647 case MESSAGE_DISABLE:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001648 if (DBG) {
1649 Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
1650 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001651 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1652 if (mEnable && mBluetooth != null) {
1653 waitForOnOff(true, false);
1654 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001655 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001656 waitForOnOff(false, false);
1657 } else {
1658 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001659 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001660 }
fredc0f420372012-04-12 00:02:00 -07001661 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001662
Stanley Tng873b5702017-05-01 21:27:31 -07001663 case MESSAGE_RESTORE_USER_SETTING:
Jack He8caab152018-03-02 13:08:36 -08001664 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1665 if (DBG) {
1666 Slog.d(TAG, "Restore Bluetooth state to disabled");
Stanley Tng873b5702017-05-01 21:27:31 -07001667 }
Jack He8caab152018-03-02 13:08:36 -08001668 persistBluetoothSetting(BLUETOOTH_OFF);
1669 mEnableExternal = false;
1670 sendDisableMsg(
1671 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1672 mContext.getPackageName());
1673 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1674 if (DBG) {
1675 Slog.d(TAG, "Restore Bluetooth state to enabled");
1676 }
1677 mQuietEnableExternal = false;
1678 mEnableExternal = true;
1679 // waive WRITE_SECURE_SETTINGS permission check
1680 sendEnableMsg(false,
1681 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1682 mContext.getPackageName());
Stanley Tng873b5702017-05-01 21:27:31 -07001683 }
1684 break;
1685
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001686 case MESSAGE_REGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001687 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001688 mCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001689 break;
Marie Janssencb21ad72016-12-13 10:51:02 -08001690 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001691 case MESSAGE_UNREGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001692 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001693 mCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001694 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001695 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001696 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
1697 IBluetoothStateChangeCallback callback =
1698 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001699 mStateChangeCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001700 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001701 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001702 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
1703 IBluetoothStateChangeCallback callback =
1704 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001705 mStateChangeCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001706 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001707 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001708 case MESSAGE_ADD_PROXY_DELAYED: {
Jack He8caab152018-03-02 13:08:36 -08001709 ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
Benjamin Franze8b98922014-11-12 15:57:54 +00001710 if (psc == null) {
1711 break;
1712 }
1713 IBluetoothProfileServiceConnection proxy =
1714 (IBluetoothProfileServiceConnection) msg.obj;
1715 psc.addProxy(proxy);
1716 break;
1717 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001718 case MESSAGE_BIND_PROFILE_SERVICE: {
Benjamin Franze8b98922014-11-12 15:57:54 +00001719 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1720 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1721 if (psc == null) {
1722 break;
1723 }
1724 psc.bindService();
1725 break;
1726 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001727 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
1728 if (DBG) {
1729 Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
1730 }
fredc0f420372012-04-12 00:02:00 -07001731
1732 IBinder service = (IBinder) msg.obj;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001733 try {
1734 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001735 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001736 mBluetoothGatt =
1737 IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
Myles Watson304ebf22018-05-11 08:47:24 -07001738 continueFromBleOnState();
Matthew Xieddf7e472013-03-01 18:41:02 -08001739 break;
1740 } // else must be SERVICE_IBLUETOOTH
1741
1742 //Remove timeout
Zhihai Xuaf5971e2013-06-10 20:28:31 -07001743 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Matthew Xieddf7e472013-03-01 18:41:02 -08001744
fredc0f420372012-04-12 00:02:00 -07001745 mBinding = false;
Marie Janssen9db28eb2016-01-12 16:05:15 -08001746 mBluetoothBinder = service;
Jeff Sharkey0a17db12016-11-04 11:23:46 -06001747 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
fredc0f420372012-04-12 00:02:00 -07001748
Ajay Panicker4bb48302016-03-31 14:14:27 -07001749 if (!isNameAndAddressSet()) {
1750 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1751 mHandler.sendMessage(getMsg);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001752 if (mGetNameAddressOnly) {
1753 return;
1754 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001755 }
1756
Matthew Xiecdce0b92012-07-12 19:06:15 -07001757 //Register callback object
fredcbf072a72012-05-09 16:52:50 -07001758 try {
Matthew Xiecdce0b92012-07-12 19:06:15 -07001759 mBluetooth.registerCallback(mBluetoothCallback);
1760 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001761 Slog.e(TAG, "Unable to register BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001762 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001763 //Inform BluetoothAdapter instances that service is up
Zhihai Xu40874a02012-10-08 17:57:03 -07001764 sendBluetoothServiceUpCallback();
1765
Matthew Xiecdce0b92012-07-12 19:06:15 -07001766 //Do enable request
1767 try {
Jack Hea6e031c2017-12-08 12:21:37 -08001768 if (!mQuietEnable) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001769 if (!mBluetooth.enable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001770 Slog.e(TAG, "IBluetooth.enable() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001771 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001772 } else {
1773 if (!mBluetooth.enableNoAutoConnect()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001774 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001775 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001776 }
1777 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001778 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07001779 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001780 } finally {
1781 mBluetoothLock.writeLock().unlock();
Freda8c6df02012-07-11 10:25:23 -07001782 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001783
1784 if (!mEnable) {
1785 waitForOnOff(true, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001786 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001787 waitForOnOff(false, false);
1788 }
fredc649fe492012-04-19 01:07:18 -07001789 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001790 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001791 case MESSAGE_BLUETOOTH_STATE_CHANGE: {
fredcbf072a72012-05-09 16:52:50 -07001792 int prevState = msg.arg1;
1793 int newState = msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08001794 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001795 Slog.d(TAG,
1796 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
1797 prevState) + " > " + BluetoothAdapter.nameForState(
1798 newState));
Marie Janssencb21ad72016-12-13 10:51:02 -08001799 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001800 mState = newState;
1801 bluetoothStateChangeHandler(prevState, newState);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001802 // handle error state transition case from TURNING_ON to OFF
1803 // unbind and rebind bluetooth service and enable bluetooth
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001804 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
1805 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001806 recoverBluetoothServiceFromError(false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001807 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001808 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
1809 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001810 recoverBluetoothServiceFromError(true);
Nitin Arorad055adb2015-03-02 15:03:51 -08001811 }
Calvin Ona0b91d72016-06-15 17:58:23 -07001812 // If we tried to enable BT while BT was in the process of shutting down,
1813 // wait for the BT process to fully tear down and then force a restart
1814 // here. This is a bit of a hack (b/29363429).
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001815 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
1816 == BluetoothAdapter.STATE_OFF)) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001817 if (mEnable) {
1818 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1819 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001820 Message restartMsg =
1821 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Calvin Ona0b91d72016-06-15 17:58:23 -07001822 mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
1823 }
1824 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001825 if (newState == BluetoothAdapter.STATE_ON
1826 || newState == BluetoothAdapter.STATE_BLE_ON) {
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001827 // bluetooth is working, reset the counter
1828 if (mErrorRecoveryRetryCounter != 0) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001829 Slog.w(TAG, "bluetooth is recovered from error");
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001830 mErrorRecoveryRetryCounter = 0;
1831 }
1832 }
fredc649fe492012-04-19 01:07:18 -07001833 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001834 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001835 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
Marie Janssencb21ad72016-12-13 10:51:02 -08001836 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001837 try {
1838 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001839 if (msg.arg1 == SERVICE_IBLUETOOTH) {
1840 // if service is unbinded already, do nothing and return
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001841 if (mBluetooth == null) {
1842 break;
1843 }
Matthew Xieddf7e472013-03-01 18:41:02 -08001844 mBluetooth = null;
1845 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1846 mBluetoothGatt = null;
1847 break;
1848 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001849 Slog.e(TAG, "Unknown argument for service disconnect!");
Matthew Xieddf7e472013-03-01 18:41:02 -08001850 break;
1851 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001852 } finally {
1853 mBluetoothLock.writeLock().unlock();
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301854 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001855
Marie Janssene54b4222017-03-16 18:10:59 -07001856 // log the unexpected crash
1857 addCrashLog();
Jack He8caab152018-03-02 13:08:36 -08001858 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
1859 mContext.getPackageName(), false);
Zhihai Xu40874a02012-10-08 17:57:03 -07001860 if (mEnable) {
1861 mEnable = false;
1862 // Send a Bluetooth Restart message
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001863 Message restartMsg =
1864 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1865 mHandler.sendMessageDelayed(restartMsg, SERVICE_RESTART_TIME_MS);
Zhihai Xu40874a02012-10-08 17:57:03 -07001866 }
1867
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001868 sendBluetoothServiceDownCallback();
Zhihai Xu40874a02012-10-08 17:57:03 -07001869
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001870 // Send BT state broadcast to update
1871 // the BT icon correctly
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001872 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
1873 == BluetoothAdapter.STATE_ON)) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001874 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001875 BluetoothAdapter.STATE_TURNING_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001876 mState = BluetoothAdapter.STATE_TURNING_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07001877 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001878 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1879 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001880 BluetoothAdapter.STATE_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001881 }
1882
1883 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1884 mState = BluetoothAdapter.STATE_OFF;
fredc649fe492012-04-19 01:07:18 -07001885 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001886 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001887 case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
Marie Janssencb21ad72016-12-13 10:51:02 -08001888 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE");
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301889 /* Enable without persisting the setting as
1890 it doesnt change when IBluetooth
1891 service restarts */
Zhihai Xu40874a02012-10-08 17:57:03 -07001892 mEnable = true;
Jack He8caab152018-03-02 13:08:36 -08001893 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
1894 mContext.getPackageName(), true);
Zhihai Xu401202b2012-12-03 11:36:21 -08001895 handleEnable(mQuietEnable);
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301896 break;
1897 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001898 case MESSAGE_TIMEOUT_BIND: {
1899 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1900 mBluetoothLock.writeLock().lock();
1901 mBinding = false;
1902 mBluetoothLock.writeLock().unlock();
1903 break;
1904 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001905 case MESSAGE_TIMEOUT_UNBIND: {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001906 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001907 mBluetoothLock.writeLock().lock();
1908 mUnbinding = false;
1909 mBluetoothLock.writeLock().unlock();
fredc649fe492012-04-19 01:07:18 -07001910 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001911 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001912
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001913 case MESSAGE_USER_SWITCHED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001914 if (DBG) {
1915 Slog.d(TAG, "MESSAGE_USER_SWITCHED");
1916 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001917 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001918
Zhihai Xu40874a02012-10-08 17:57:03 -07001919 /* disable and enable BT when detect a user switch */
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07001920 if (mBluetooth != null && isEnabled()) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001921 try {
1922 mBluetoothLock.readLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001923 if (mBluetooth != null) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001924 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xu40874a02012-10-08 17:57:03 -07001925 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001926 } catch (RemoteException re) {
1927 Slog.e(TAG, "Unable to unregister", re);
1928 } finally {
1929 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001930 }
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001931
1932 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1933 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
1934 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
1935 mState = BluetoothAdapter.STATE_OFF;
1936 }
1937 if (mState == BluetoothAdapter.STATE_OFF) {
1938 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
1939 mState = BluetoothAdapter.STATE_TURNING_ON;
1940 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001941
1942 waitForOnOff(true, false);
1943
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001944 if (mState == BluetoothAdapter.STATE_TURNING_ON) {
1945 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
1946 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001947
Benjamin Franze8b98922014-11-12 15:57:54 +00001948 unbindAllBluetoothProfileServices();
Zhihai Xu40874a02012-10-08 17:57:03 -07001949 // disable
Jack He8caab152018-03-02 13:08:36 -08001950 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
1951 mContext.getPackageName(), false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001952 handleDisable();
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001953 // Pbap service need receive STATE_TURNING_OFF intent to close
1954 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001955 BluetoothAdapter.STATE_TURNING_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001956
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001957 boolean didDisableTimeout = !waitForOnOff(false, true);
Zhihai Xu40874a02012-10-08 17:57:03 -07001958
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001959 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001960 BluetoothAdapter.STATE_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001961 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001962
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07001963 try {
1964 mBluetoothLock.writeLock().lock();
1965 if (mBluetooth != null) {
1966 mBluetooth = null;
1967 // Unbind
1968 mContext.unbindService(mConnection);
1969 }
1970 mBluetoothGatt = null;
1971 } finally {
1972 mBluetoothLock.writeLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001973 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001974
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001975 //
1976 // If disabling Bluetooth times out, wait for an
1977 // additional amount of time to ensure the process is
1978 // shut down completely before attempting to restart.
1979 //
1980 if (didDisableTimeout) {
1981 SystemClock.sleep(3000);
1982 } else {
1983 SystemClock.sleep(100);
1984 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001985
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001986 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1987 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07001988 // enable
Jack He8caab152018-03-02 13:08:36 -08001989 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
1990 mContext.getPackageName(), true);
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07001991 // mEnable flag could have been reset on disableBLE. Reenable it.
1992 mEnable = true;
Zhihai Xu401202b2012-12-03 11:36:21 -08001993 handleEnable(mQuietEnable);
John Spurlock8a985d22014-02-25 09:40:05 -05001994 } else if (mBinding || mBluetooth != null) {
Zhihai Xu40874a02012-10-08 17:57:03 -07001995 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
1996 userMsg.arg2 = 1 + msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08001997 // if user is switched when service is binding retry after a delay
Zhihai Xu40874a02012-10-08 17:57:03 -07001998 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
1999 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002000 Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
Zhihai Xu40874a02012-10-08 17:57:03 -07002001 }
John Spurlock8a985d22014-02-25 09:40:05 -05002002 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002003 break;
2004 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002005 case MESSAGE_USER_UNLOCKED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002006 if (DBG) {
2007 Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
2008 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002009 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
2010
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002011 if (mEnable && !mBinding && (mBluetooth == null)) {
2012 // We should be connected, but we gave up for some
2013 // reason; maybe the Bluetooth service wasn't encryption
2014 // aware, so try binding again.
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002015 if (DBG) {
2016 Slog.d(TAG, "Enabled but not bound; retrying after unlock");
2017 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002018 handleEnable(mQuietEnable);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002019 }
2020 }
fredc0f420372012-04-12 00:02:00 -07002021 }
2022 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002023 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002024
Zhihai Xu401202b2012-12-03 11:36:21 -08002025 private void handleEnable(boolean quietMode) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002026 mQuietEnable = quietMode;
2027
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002028 try {
2029 mBluetoothLock.writeLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002030 if ((mBluetooth == null) && (!mBinding)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002031 //Start bind timeout and bind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002032 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
2033 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002034 Intent i = new Intent(IBluetooth.class.getName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002035 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
Dianne Hackbornce09f5a2014-10-10 15:03:13 -07002036 UserHandle.CURRENT)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002037 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Zhihai Xu40874a02012-10-08 17:57:03 -07002038 } else {
2039 mBinding = true;
Matthew Xiecdce0b92012-07-12 19:06:15 -07002040 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002041 } else if (mBluetooth != null) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002042 //Enable bluetooth
2043 try {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002044 if (!mQuietEnable) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002045 if (!mBluetooth.enable()) {
2046 Slog.e(TAG, "IBluetooth.enable() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002047 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002048 } else {
2049 if (!mBluetooth.enableNoAutoConnect()) {
2050 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002051 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002052 }
2053 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002054 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002055 }
2056 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002057 } finally {
2058 mBluetoothLock.writeLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002059 }
2060 }
2061
Dianne Hackborn221ea892013-08-04 16:50:16 -07002062 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
2063 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
2064 intent.setComponent(comp);
2065 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07002066 Slog.e(TAG, "Fail to bind to: " + intent);
Dianne Hackborn221ea892013-08-04 16:50:16 -07002067 return false;
2068 }
2069 return true;
2070 }
2071
Zhihai Xu401202b2012-12-03 11:36:21 -08002072 private void handleDisable() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002073 try {
2074 mBluetoothLock.readLock().lock();
Andre Eisenbach305fdab2015-11-11 21:43:26 -08002075 if (mBluetooth != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002076 if (DBG) {
2077 Slog.d(TAG, "Sending off request.");
2078 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002079 if (!mBluetooth.disable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002080 Slog.e(TAG, "IBluetooth.disable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002081 }
2082 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002083 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002084 Slog.e(TAG, "Unable to call disable()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002085 } finally {
2086 mBluetoothLock.readLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002087 }
2088 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002089
2090 private boolean checkIfCallerIsForegroundUser() {
2091 int foregroundUser;
2092 int callingUser = UserHandle.getCallingUserId();
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002093 int callingUid = Binder.getCallingUid();
Zhihai Xu40874a02012-10-08 17:57:03 -07002094 long callingIdentity = Binder.clearCallingIdentity();
Benjamin Franze8b98922014-11-12 15:57:54 +00002095 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2096 UserInfo ui = um.getProfileParent(callingUser);
2097 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002098 int callingAppId = UserHandle.getAppId(callingUid);
Zhihai Xu40874a02012-10-08 17:57:03 -07002099 boolean valid = false;
2100 try {
2101 foregroundUser = ActivityManager.getCurrentUser();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002102 valid = (callingUser == foregroundUser) || parentUser == foregroundUser
2103 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid;
Marie Janssencb21ad72016-12-13 10:51:02 -08002104 if (DBG && !valid) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002105 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
2106 + callingUser + " parentUser=" + parentUser + " foregroundUser="
2107 + foregroundUser);
Zhihai Xu40874a02012-10-08 17:57:03 -07002108 }
2109 } finally {
2110 Binder.restoreCallingIdentity(callingIdentity);
2111 }
2112 return valid;
2113 }
2114
Nitin Arorad055adb2015-03-02 15:03:51 -08002115 private void sendBleStateChanged(int prevState, int newState) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002116 if (DBG) {
2117 Slog.d(TAG,
2118 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
2119 + BluetoothAdapter.nameForState(newState));
2120 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002121 // Send broadcast message to everyone else
2122 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
2123 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2124 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2125 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2126 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
2127 }
2128
Zhihai Xu40874a02012-10-08 17:57:03 -07002129 private void bluetoothStateChangeHandler(int prevState, int newState) {
Nitin Arorad055adb2015-03-02 15:03:51 -08002130 boolean isStandardBroadcast = true;
Marie Janssencb21ad72016-12-13 10:51:02 -08002131 if (prevState == newState) { // No change. Nothing to do.
2132 return;
2133 }
2134 // Notify all proxy objects first of adapter state change
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002135 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002136 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002137 && newState == BluetoothAdapter.STATE_BLE_ON);
Zhihai Xu40874a02012-10-08 17:57:03 -07002138
Marie Janssencb21ad72016-12-13 10:51:02 -08002139 if (newState == BluetoothAdapter.STATE_OFF) {
2140 // If Bluetooth is off, send service down event to proxy objects, and unbind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002141 if (DBG) {
2142 Slog.d(TAG, "Bluetooth is complete send Service Down");
2143 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002144 sendBluetoothServiceDownCallback();
2145 unbindAndFinish();
Nitin Arorad055adb2015-03-02 15:03:51 -08002146 sendBleStateChanged(prevState, newState);
Marie Janssencb21ad72016-12-13 10:51:02 -08002147 // Don't broadcast as it has already been broadcast before
Nitin Arorad055adb2015-03-02 15:03:51 -08002148 isStandardBroadcast = false;
2149
Marie Janssencb21ad72016-12-13 10:51:02 -08002150 } else if (!intermediate_off) {
2151 // connect to GattService
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002152 if (DBG) {
2153 Slog.d(TAG, "Bluetooth is in LE only mode");
2154 }
Myles Watson304ebf22018-05-11 08:47:24 -07002155 if (mBluetoothGatt != null || !mContext.getPackageManager()
2156 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
2157 continueFromBleOnState();
Marie Janssencb21ad72016-12-13 10:51:02 -08002158 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002159 if (DBG) {
2160 Slog.d(TAG, "Binding Bluetooth GATT service");
2161 }
Myles Watson304ebf22018-05-11 08:47:24 -07002162 Intent i = new Intent(IBluetoothGatt.class.getName());
2163 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
2164 UserHandle.CURRENT);
Nitin Arorad055adb2015-03-02 15:03:51 -08002165 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002166 sendBleStateChanged(prevState, newState);
2167 //Don't broadcase this as std intent
2168 isStandardBroadcast = false;
2169
2170 } else if (intermediate_off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002171 if (DBG) {
2172 Slog.d(TAG, "Intermediate off, back to LE only mode");
2173 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002174 // For LE only mode, broadcast as is
2175 sendBleStateChanged(prevState, newState);
2176 sendBluetoothStateCallback(false); // BT is OFF for general users
2177 // Broadcast as STATE_OFF
2178 newState = BluetoothAdapter.STATE_OFF;
2179 sendBrEdrDownCallback();
Nitin Arorad055adb2015-03-02 15:03:51 -08002180 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002181 } else if (newState == BluetoothAdapter.STATE_ON) {
2182 boolean isUp = (newState == BluetoothAdapter.STATE_ON);
2183 sendBluetoothStateCallback(isUp);
2184 sendBleStateChanged(prevState, newState);
2185
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002186 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
2187 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002188 sendBleStateChanged(prevState, newState);
2189 isStandardBroadcast = false;
2190
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002191 } else if (newState == BluetoothAdapter.STATE_TURNING_ON
2192 || newState == BluetoothAdapter.STATE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002193 sendBleStateChanged(prevState, newState);
2194 }
2195
2196 if (isStandardBroadcast) {
2197 if (prevState == BluetoothAdapter.STATE_BLE_ON) {
2198 // Show prevState of BLE_ON as OFF to standard users
2199 prevState = BluetoothAdapter.STATE_OFF;
2200 }
2201 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
2202 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2203 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2204 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2205 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
Zhihai Xu40874a02012-10-08 17:57:03 -07002206 }
2207 }
2208
2209 /**
2210 * if on is true, wait for state become ON
2211 * if off is true, wait for state become OFF
2212 * if both on and off are false, wait for state not ON
2213 */
2214 private boolean waitForOnOff(boolean on, boolean off) {
2215 int i = 0;
2216 while (i < 10) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002217 try {
2218 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002219 if (mBluetooth == null) {
2220 break;
2221 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002222 if (on) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002223 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
2224 return true;
2225 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002226 } else if (off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002227 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) {
2228 return true;
2229 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002230 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002231 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) {
2232 return true;
2233 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002234 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002235 } catch (RemoteException e) {
2236 Slog.e(TAG, "getState()", e);
2237 break;
2238 } finally {
2239 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002240 }
2241 if (on || off) {
2242 SystemClock.sleep(300);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002243 } else {
Zhihai Xu40874a02012-10-08 17:57:03 -07002244 SystemClock.sleep(50);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002245 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002246 i++;
2247 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002248 Slog.e(TAG, "waitForOnOff time out");
Zhihai Xu40874a02012-10-08 17:57:03 -07002249 return false;
2250 }
Zhihai Xu681ae7f2012-11-12 15:14:18 -08002251
Jack He8caab152018-03-02 13:08:36 -08002252 private void sendDisableMsg(int reason, String packageName) {
Zhihai Xu401202b2012-12-03 11:36:21 -08002253 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
Jack He8caab152018-03-02 13:08:36 -08002254 addActiveLog(reason, packageName, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08002255 }
2256
Jack He8caab152018-03-02 13:08:36 -08002257 private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002258 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
Jack He8caab152018-03-02 13:08:36 -08002259 addActiveLog(reason, packageName, true);
Marie Janssen12a35012017-06-26 07:21:03 -07002260 mLastEnabledTime = SystemClock.elapsedRealtime();
Marie Janssen59804562016-12-28 14:13:21 -08002261 }
2262
Jack He8caab152018-03-02 13:08:36 -08002263 private void addActiveLog(int reason, String packageName, boolean enable) {
Marie Janssen59804562016-12-28 14:13:21 -08002264 synchronized (mActiveLogs) {
Marie Janssene54b4222017-03-16 18:10:59 -07002265 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
Marie Janssen59804562016-12-28 14:13:21 -08002266 mActiveLogs.remove();
2267 }
Jack He8caab152018-03-02 13:08:36 -08002268 mActiveLogs.add(
2269 new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
Marie Janssen59804562016-12-28 14:13:21 -08002270 }
Tej Singhd8e7cc62018-03-22 18:30:31 +00002271
2272 int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
2273 StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2274 StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
2275 Binder.getCallingUid(), null, state, reason, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08002276 }
2277
Marie Janssene54b4222017-03-16 18:10:59 -07002278 private void addCrashLog() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002279 synchronized (mCrashTimestamps) {
2280 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
2281 mCrashTimestamps.removeFirst();
2282 }
2283 mCrashTimestamps.add(System.currentTimeMillis());
2284 mCrashes++;
2285 }
Marie Janssene54b4222017-03-16 18:10:59 -07002286 }
2287
Marie Janssen2977c3e2016-11-09 12:01:24 -08002288 private void recoverBluetoothServiceFromError(boolean clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002289 Slog.e(TAG, "recoverBluetoothServiceFromError");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002290 try {
2291 mBluetoothLock.readLock().lock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002292 if (mBluetooth != null) {
2293 //Unregister callback object
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002294 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002295 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002296 } catch (RemoteException re) {
2297 Slog.e(TAG, "Unable to unregister", re);
2298 } finally {
2299 mBluetoothLock.readLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002300 }
2301
2302 SystemClock.sleep(500);
2303
2304 // disable
Jack He8caab152018-03-02 13:08:36 -08002305 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
2306 mContext.getPackageName(), false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002307 handleDisable();
2308
2309 waitForOnOff(false, true);
2310
2311 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002312
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002313 try {
2314 mBluetoothLock.writeLock().lock();
2315 if (mBluetooth != null) {
2316 mBluetooth = null;
2317 // Unbind
2318 mContext.unbindService(mConnection);
2319 }
2320 mBluetoothGatt = null;
2321 } finally {
2322 mBluetoothLock.writeLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002323 }
2324
2325 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2326 mState = BluetoothAdapter.STATE_OFF;
2327
Marie Janssen2977c3e2016-11-09 12:01:24 -08002328 if (clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002329 clearBleApps();
Marie Janssen2977c3e2016-11-09 12:01:24 -08002330 }
2331
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002332 mEnable = false;
2333
2334 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) {
2335 // Send a Bluetooth Restart message to reenable bluetooth
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002336 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002337 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
2338 } else {
2339 // todo: notify user to power down and power up phone to make bluetooth work.
2340 }
2341 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002342
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01002343 private boolean isBluetoothDisallowed() {
2344 long callingIdentity = Binder.clearCallingIdentity();
2345 try {
2346 return mContext.getSystemService(UserManager.class)
2347 .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2348 } finally {
2349 Binder.restoreCallingIdentity(callingIdentity);
2350 }
2351 }
2352
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002353 /**
2354 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002355 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2356 * state if Bluetooth is not disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002357 *
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002358 * @param userId user to disable bluetooth sharing for.
2359 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002360 */
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002361 private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002362 final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2363 "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002364 final int newState =
2365 bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2366 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002367 try {
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002368 final IPackageManager imp = AppGlobals.getPackageManager();
Myles Watson6291fae2017-06-29 03:12:02 -07002369 imp.setComponentEnabledSetting(oppLauncherComponent, newState,
2370 PackageManager.DONT_KILL_APP, userId);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002371 } catch (Exception e) {
2372 // The component was not found, do nothing.
2373 }
2374 }
2375
Mike Lockwood726d4de2014-10-28 14:06:28 -07002376 @Override
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002377 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002378 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
2379 return;
2380 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002381 String errorMsg = null;
Marie Janssen59804562016-12-28 14:13:21 -08002382
2383 boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
2384
2385 if (!protoOut) {
2386 writer.println("Bluetooth Status");
2387 writer.println(" enabled: " + isEnabled());
2388 writer.println(" state: " + BluetoothAdapter.nameForState(mState));
2389 writer.println(" address: " + mAddress);
2390 writer.println(" name: " + mName);
2391 if (mEnable) {
Marie Janssen12a35012017-06-26 07:21:03 -07002392 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002393 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
2394 (int) (onDuration / (1000 * 60 * 60)),
2395 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
2396 (int) (onDuration % 1000));
Andre Eisenbache66e1682017-04-10 13:49:13 -07002397 writer.println(" time since enabled: " + onDurationString);
Marie Janssen59804562016-12-28 14:13:21 -08002398 }
2399
Marie Janssena95924d2017-01-18 09:37:52 -08002400 if (mActiveLogs.size() == 0) {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002401 writer.println("\nBluetooth never enabled!");
Marie Janssena95924d2017-01-18 09:37:52 -08002402 } else {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002403 writer.println("\nEnable log:");
Marie Janssena95924d2017-01-18 09:37:52 -08002404 for (ActiveLog log : mActiveLogs) {
2405 writer.println(" " + log);
2406 }
Marie Janssen59804562016-12-28 14:13:21 -08002407 }
2408
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002409 writer.println(
2410 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2411 if (mCrashes == CRASH_LOG_MAX_SIZE) {
2412 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2413 }
Marie Janssene54b4222017-03-16 18:10:59 -07002414 for (Long time : mCrashTimestamps) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002415 writer.println(" " + timeToLog(time));
Marie Janssene54b4222017-03-16 18:10:59 -07002416 }
2417
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002418 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
2419 + "registered");
Marie Janssen59804562016-12-28 14:13:21 -08002420 for (ClientDeathRecipient app : mBleApps.values()) {
Marie Janssena95924d2017-01-18 09:37:52 -08002421 writer.println(" " + app.getPackageName());
Marie Janssen59804562016-12-28 14:13:21 -08002422 }
2423
Marie Janssena95924d2017-01-18 09:37:52 -08002424 writer.println("");
Marie Janssen59804562016-12-28 14:13:21 -08002425 writer.flush();
Marie Janssenf5ec5382017-01-03 11:37:38 -08002426 if (args.length == 0) {
Marie Janssena95924d2017-01-18 09:37:52 -08002427 // Add arg to produce output
2428 args = new String[1];
2429 args[0] = "--print";
Marie Janssenf5ec5382017-01-03 11:37:38 -08002430 }
Marie Janssen59804562016-12-28 14:13:21 -08002431 }
2432
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002433 if (mBluetoothBinder == null) {
2434 errorMsg = "Bluetooth Service not connected";
2435 } else {
2436 try {
2437 mBluetoothBinder.dump(fd, args);
2438 } catch (RemoteException re) {
Marie Janssen59804562016-12-28 14:13:21 -08002439 errorMsg = "RemoteException while dumping Bluetooth Service";
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002440 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002441 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002442 if (errorMsg != null) {
2443 // Silently return if we are extracting metrics in Protobuf format
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002444 if (protoOut) {
2445 return;
2446 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002447 writer.println(errorMsg);
2448 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002449 }
Jack He8caab152018-03-02 13:08:36 -08002450
2451 private static String getEnableDisableReasonString(int reason) {
2452 switch (reason) {
2453 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
2454 return "APPLICATION_REQUEST";
2455 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
2456 return "AIRPLANE_MODE";
2457 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
2458 return "DISALLOWED";
2459 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
2460 return "RESTARTED";
2461 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
2462 return "START_ERROR";
2463 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
2464 return "SYSTEM_BOOT";
2465 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
2466 return "CRASH";
2467 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
2468 return "USER_SWITCH";
2469 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
2470 return "RESTORE_USER_SETTING";
2471 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
2472 default: return "UNKNOWN[" + reason + "]";
2473 }
2474 }
fredc0f420372012-04-12 00:02:00 -07002475}