blob: 470300e6485c3d1a0ed4ee155da75c618f6ff4bd [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
Winson Chungf2b41772019-11-06 15:00:48 -080019import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
20import static android.os.UserHandle.USER_SYSTEM;
21
Svet Ganov408abf72015-05-12 19:13:36 -070022import android.Manifest;
Zhihai Xu40874a02012-10-08 17:57:03 -070023import android.app.ActivityManager;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010024import android.app.AppGlobals;
Jack Hea80cead2019-04-23 20:00:18 -070025import android.app.AppOpsManager;
fredc0f420372012-04-12 00:02:00 -070026import android.bluetooth.BluetoothAdapter;
Benjamin Franze8b98922014-11-12 15:57:54 +000027import android.bluetooth.BluetoothProfile;
Jack He8caab152018-03-02 13:08:36 -080028import android.bluetooth.BluetoothProtoEnums;
fredc0f420372012-04-12 00:02:00 -070029import android.bluetooth.IBluetooth;
fredcbf072a72012-05-09 16:52:50 -070030import android.bluetooth.IBluetoothCallback;
Wei Wange4a744b2015-06-11 17:50:29 -070031import android.bluetooth.IBluetoothGatt;
Benjamin Franze8b98922014-11-12 15:57:54 +000032import android.bluetooth.IBluetoothHeadset;
fredc0f420372012-04-12 00:02:00 -070033import android.bluetooth.IBluetoothManager;
34import android.bluetooth.IBluetoothManagerCallback;
Benjamin Franze8b98922014-11-12 15:57:54 +000035import android.bluetooth.IBluetoothProfileServiceConnection;
fredc0f420372012-04-12 00:02:00 -070036import android.bluetooth.IBluetoothStateChangeCallback;
Svet Ganov77df6f32016-08-17 11:46:34 -070037import android.content.ActivityNotFoundException;
fredc0f420372012-04-12 00:02:00 -070038import android.content.BroadcastReceiver;
39import android.content.ComponentName;
40import android.content.ContentResolver;
41import android.content.Context;
42import android.content.Intent;
43import android.content.IntentFilter;
44import android.content.ServiceConnection;
Svetoslav Ganovac69be52016-06-29 17:31:44 -070045import android.content.pm.ApplicationInfo;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010046import android.content.pm.IPackageManager;
Matthew Xie32ab77b2013-05-08 19:26:57 -070047import android.content.pm.PackageManager;
Winson Chungf2b41772019-11-06 15:00:48 -080048import android.content.pm.PackageManagerInternal;
Benjamin Franze8b98922014-11-12 15:57:54 +000049import android.content.pm.UserInfo;
Wei Wange4a744b2015-06-11 17:50:29 -070050import android.database.ContentObserver;
Zhihai Xu40874a02012-10-08 17:57:03 -070051import android.os.Binder;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010052import android.os.Bundle;
fredc0f420372012-04-12 00:02:00 -070053import android.os.Handler;
fredc0f420372012-04-12 00:02:00 -070054import android.os.IBinder;
Zhihai Xu40874a02012-10-08 17:57:03 -070055import android.os.Looper;
fredc0f420372012-04-12 00:02:00 -070056import android.os.Message;
Zhihai Xu40874a02012-10-08 17:57:03 -070057import android.os.Process;
fredcd6883532012-04-25 17:46:13 -070058import android.os.RemoteCallbackList;
fredc0f420372012-04-12 00:02:00 -070059import android.os.RemoteException;
Zhihai Xu40874a02012-10-08 17:57:03 -070060import android.os.SystemClock;
Stanley Tngfe8c8332018-06-19 08:48:10 -070061import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070062import android.os.UserHandle;
Benjamin Franze8b98922014-11-12 15:57:54 +000063import android.os.UserManager;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010064import android.os.UserManagerInternal;
65import android.os.UserManagerInternal.UserRestrictionsListener;
fredc0f420372012-04-12 00:02:00 -070066import android.provider.Settings;
Wei Wang67d84162015-04-26 17:04:29 -070067import android.provider.Settings.SettingNotFoundException;
Stanley Tngfe8c8332018-06-19 08:48:10 -070068import android.text.TextUtils;
69import android.util.FeatureFlagUtils;
70import android.util.Log;
Jeff Sharkey67609c72016-03-05 14:29:13 -070071import android.util.Slog;
Tej Singhd8e7cc62018-03-22 18:30:31 +000072import android.util.StatsLog;
Mike Lockwood726d4de2014-10-28 14:06:28 -070073
Arthur Hsuf3f95a92018-01-11 16:46:22 -080074import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060075import com.android.internal.util.DumpUtils;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010076import com.android.server.pm.UserRestrictionsUtils;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +010077
Mike Lockwood726d4de2014-10-28 14:06:28 -070078import java.io.FileDescriptor;
79import java.io.PrintWriter;
Benjamin Franze8b98922014-11-12 15:57:54 +000080import java.util.HashMap;
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +010081import java.util.ArrayList;
Marie Janssen59804562016-12-28 14:13:21 -080082import java.util.LinkedList;
Myles Watsonb5cd11a2017-11-27 16:42:11 -080083import java.util.Locale;
Benjamin Franze8b98922014-11-12 15:57:54 +000084import java.util.Map;
Chienyuan177156b2018-12-18 10:40:25 +080085import java.util.NoSuchElementException;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010086import java.util.concurrent.ConcurrentHashMap;
87import java.util.concurrent.locks.ReentrantReadWriteLock;
Miao Chou658bf2f2015-06-26 17:14:35 -070088
Marie Janssen59804562016-12-28 14:13:21 -080089
fredc0f420372012-04-12 00:02:00 -070090class BluetoothManagerService extends IBluetoothManager.Stub {
91 private static final String TAG = "BluetoothManagerService";
Pavlin Radoslavov41401112016-06-27 15:25:18 -070092 private static final boolean DBG = true;
fredc0f420372012-04-12 00:02:00 -070093
fredc0f420372012-04-12 00:02:00 -070094 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
95 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
Marie Janssene54b4222017-03-16 18:10:59 -070096
Myles Watsonb5cd11a2017-11-27 16:42:11 -080097 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
98 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
99 private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name";
Marie Janssene54b4222017-03-16 18:10:59 -0700100
101 private static final int ACTIVE_LOG_MAX_SIZE = 20;
102 private static final int CRASH_LOG_MAX_SIZE = 100;
Marie Janssene54b4222017-03-16 18:10:59 -0700103
fredc0f420372012-04-12 00:02:00 -0700104 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530105 //Maximum msec to wait for service restart
Ugo Yu1ff6fd32019-11-20 17:59:11 +0800106 private static final int SERVICE_RESTART_TIME_MS = 400;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800107 //Maximum msec to wait for restart due to error
108 private static final int ERROR_RESTART_TIME_MS = 3000;
Zhihai Xu40874a02012-10-08 17:57:03 -0700109 //Maximum msec to delay MESSAGE_USER_SWITCHED
110 private static final int USER_SWITCHED_TIME_MS = 200;
Benjamin Franze8b98922014-11-12 15:57:54 +0000111 // Delay for the addProxy function in msec
112 private static final int ADD_PROXY_DELAY_MS = 100;
fredc0f420372012-04-12 00:02:00 -0700113
114 private static final int MESSAGE_ENABLE = 1;
115 private static final int MESSAGE_DISABLE = 2;
fredc649fe492012-04-19 01:07:18 -0700116 private static final int MESSAGE_REGISTER_ADAPTER = 20;
117 private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
118 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
119 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
120 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
121 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530122 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700123 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
124 private static final int MESSAGE_TIMEOUT_BIND = 100;
125 private static final int MESSAGE_TIMEOUT_UNBIND = 101;
Ajay Panicker4bb48302016-03-31 14:14:27 -0700126 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
Zhihai Xu40874a02012-10-08 17:57:03 -0700127 private static final int MESSAGE_USER_SWITCHED = 300;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700128 private static final int MESSAGE_USER_UNLOCKED = 301;
Benjamin Franze8b98922014-11-12 15:57:54 +0000129 private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
130 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
Stanley Tng873b5702017-05-01 21:27:31 -0700131 private static final int MESSAGE_RESTORE_USER_SETTING = 500;
132
133 private static final int RESTORE_SETTING_TO_ON = 1;
134 private static final int RESTORE_SETTING_TO_OFF = 0;
Marie Janssencb21ad72016-12-13 10:51:02 -0800135
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700136 private static final int MAX_ERROR_RESTART_RETRIES = 6;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800137
Zhihai Xu401202b2012-12-03 11:36:21 -0800138 // Bluetooth persisted setting is off
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800139 private static final int BLUETOOTH_OFF = 0;
Zhihai Xu401202b2012-12-03 11:36:21 -0800140 // Bluetooth persisted setting is on
141 // and Airplane mode won't affect Bluetooth state at start up
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800142 private static final int BLUETOOTH_ON_BLUETOOTH = 1;
Zhihai Xu401202b2012-12-03 11:36:21 -0800143 // Bluetooth persisted setting is on
144 // but Airplane mode will affect Bluetooth state at start up
145 // and Airplane mode will have higher priority.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800146 private static final int BLUETOOTH_ON_AIRPLANE = 2;
fredc0f420372012-04-12 00:02:00 -0700147
Matthew Xieddf7e472013-03-01 18:41:02 -0800148 private static final int SERVICE_IBLUETOOTH = 1;
149 private static final int SERVICE_IBLUETOOTHGATT = 2;
150
fredc0f420372012-04-12 00:02:00 -0700151 private final Context mContext;
Matthew Xiecdce0b92012-07-12 19:06:15 -0700152
153 // Locks are not provided for mName and mAddress.
154 // They are accessed in handler or broadcast receiver, same thread context.
fredc0f420372012-04-12 00:02:00 -0700155 private String mAddress;
156 private String mName;
Matthew Xie6fde3092012-07-11 17:10:07 -0700157 private final ContentResolver mContentResolver;
158 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
159 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800160 private IBinder mBluetoothBinder;
fredc649fe492012-04-19 01:07:18 -0700161 private IBluetooth mBluetooth;
Matthew Xieddf7e472013-03-01 18:41:02 -0800162 private IBluetoothGatt mBluetoothGatt;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800163 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
fredc649fe492012-04-19 01:07:18 -0700164 private boolean mBinding;
165 private boolean mUnbinding;
Marie Janssen59804562016-12-28 14:13:21 -0800166
Zhihai Xu401202b2012-12-03 11:36:21 -0800167 // used inside handler thread
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700168 private boolean mQuietEnable = false;
Marie Janssen59804562016-12-28 14:13:21 -0800169 private boolean mEnable;
170
Jack He8caab152018-03-02 13:08:36 -0800171 private static CharSequence timeToLog(long timestamp) {
Marie Janssene54b4222017-03-16 18:10:59 -0700172 return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
173 }
174
Marie Janssen59804562016-12-28 14:13:21 -0800175 /**
176 * Used for tracking apps that enabled / disabled Bluetooth.
177 */
178 private class ActiveLog {
Jack He8caab152018-03-02 13:08:36 -0800179 private int mReason;
Marie Janssen59804562016-12-28 14:13:21 -0800180 private String mPackageName;
181 private boolean mEnable;
182 private long mTimestamp;
183
Jack He8caab152018-03-02 13:08:36 -0800184 ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
185 mReason = reason;
Marie Janssen59804562016-12-28 14:13:21 -0800186 mPackageName = packageName;
187 mEnable = enable;
188 mTimestamp = timestamp;
189 }
190
Marie Janssen59804562016-12-28 14:13:21 -0800191 public String toString() {
Jack He8caab152018-03-02 13:08:36 -0800192 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
193 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
Marie Janssen59804562016-12-28 14:13:21 -0800194 }
195
196 }
197
Jack He8caab152018-03-02 13:08:36 -0800198 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
199 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
Marie Janssene54b4222017-03-16 18:10:59 -0700200 private int mCrashes;
Marie Janssen12a35012017-06-26 07:21:03 -0700201 private long mLastEnabledTime;
Marie Janssen59804562016-12-28 14:13:21 -0800202
203 // configuration from external IBinder call which is used to
Zhihai Xu401202b2012-12-03 11:36:21 -0800204 // synchronize with broadcast receiver.
205 private boolean mQuietEnableExternal;
Zhihai Xu401202b2012-12-03 11:36:21 -0800206 private boolean mEnableExternal;
Marie Janssen59804562016-12-28 14:13:21 -0800207
208 // Map of apps registered to keep BLE scanning on.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800209 private Map<IBinder, ClientDeathRecipient> mBleApps =
210 new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
Marie Janssen59804562016-12-28 14:13:21 -0800211
Zhihai Xu40874a02012-10-08 17:57:03 -0700212 private int mState;
Zhihai Xu40874a02012-10-08 17:57:03 -0700213 private final BluetoothHandler mHandler;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800214 private int mErrorRecoveryRetryCounter;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200215 private final int mSystemUiUid;
fredc0f420372012-04-12 00:02:00 -0700216
Stanley Tng61dbd812019-01-13 16:04:31 -0800217 private boolean mIsHearingAidProfileSupported;
218
Jack Hea80cead2019-04-23 20:00:18 -0700219 private AppOpsManager mAppOps;
220
Benjamin Franze8b98922014-11-12 15:57:54 +0000221 // Save a ProfileServiceConnections object for each of the bound
222 // bluetooth profile services
Jack He8caab152018-03-02 13:08:36 -0800223 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
Benjamin Franze8b98922014-11-12 15:57:54 +0000224
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700225 private final boolean mWirelessConsentRequired;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700226
Marie Janssen59804562016-12-28 14:13:21 -0800227 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
fredcbf072a72012-05-09 16:52:50 -0700228 @Override
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800229 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
230 Message msg =
231 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
fredcbf072a72012-05-09 16:52:50 -0700232 mHandler.sendMessage(msg);
233 }
234 };
235
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100236 private final UserRestrictionsListener mUserRestrictionsListener =
237 new UserRestrictionsListener() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800238 @Override
239 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
240 Bundle prevRestrictions) {
Myles Watson6291fae2017-06-29 03:12:02 -0700241
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800242 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
243 UserManager.DISALLOW_BLUETOOTH_SHARING)) {
244 updateOppLauncherComponentState(userId,
245 newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
246 }
Pavel Grafov4f4f6f82017-03-28 13:44:04 +0100247
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800248 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
Winson Chungf2b41772019-11-06 15:00:48 -0800249 if (userId == USER_SYSTEM
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800250 && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
251 newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
Winson Chungf2b41772019-11-06 15:00:48 -0800252 if (userId == USER_SYSTEM && newRestrictions.getBoolean(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800253 UserManager.DISALLOW_BLUETOOTH)) {
254 updateOppLauncherComponentState(userId, true); // Sharing disallowed
Jack He8caab152018-03-02 13:08:36 -0800255 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
256 mContext.getPackageName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800257 } else {
258 updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
259 UserManager.DISALLOW_BLUETOOTH_SHARING));
260 }
261 }
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100262 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800263 };
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100264
Ajay Panicker467bc042017-02-22 12:23:15 -0800265 private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
266 @Override
267 public void onChange(boolean unused) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800268 synchronized (this) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800269 if (isBluetoothPersistedStateOn()) {
270 if (isAirplaneModeOn()) {
271 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
272 } else {
273 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
274 }
275 }
276
277 int st = BluetoothAdapter.STATE_OFF;
278 try {
279 mBluetoothLock.readLock().lock();
280 if (mBluetooth != null) {
281 st = mBluetooth.getState();
282 }
283 } catch (RemoteException e) {
284 Slog.e(TAG, "Unable to call getState", e);
285 return;
286 } finally {
287 mBluetoothLock.readLock().unlock();
288 }
289
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800290 Slog.d(TAG,
291 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState(
Rene Mayrhofer7d6c8e52018-11-28 11:32:40 -0800292 st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
Ajay Panicker467bc042017-02-22 12:23:15 -0800293
294 if (isAirplaneModeOn()) {
295 // Clear registered LE apps to force shut-off
296 clearBleApps();
297
298 // If state is BLE_ON make sure we trigger disableBLE
299 if (st == BluetoothAdapter.STATE_BLE_ON) {
300 try {
301 mBluetoothLock.readLock().lock();
302 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700303 addActiveLog(
304 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
305 mContext.getPackageName(), false);
Ajay Panicker467bc042017-02-22 12:23:15 -0800306 mBluetooth.onBrEdrDown();
307 mEnable = false;
308 mEnableExternal = false;
309 }
310 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800311 Slog.e(TAG, "Unable to call onBrEdrDown", e);
Ajay Panicker467bc042017-02-22 12:23:15 -0800312 } finally {
313 mBluetoothLock.readLock().unlock();
314 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800315 } else if (st == BluetoothAdapter.STATE_ON) {
Jack He8caab152018-03-02 13:08:36 -0800316 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
317 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800318 }
319 } else if (mEnableExternal) {
Jack He8caab152018-03-02 13:08:36 -0800320 sendEnableMsg(mQuietEnableExternal,
321 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
322 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800323 }
324 }
325 }
326 };
327
fredcbf072a72012-05-09 16:52:50 -0700328 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
fredc0f420372012-04-12 00:02:00 -0700329 @Override
330 public void onReceive(Context context, Intent intent) {
331 String action = intent.getAction();
fredcbf072a72012-05-09 16:52:50 -0700332 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
fredc0f420372012-04-12 00:02:00 -0700333 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800334 if (DBG) {
335 Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
336 }
fredc0f420372012-04-12 00:02:00 -0700337 if (newName != null) {
338 storeNameAndAddress(newName, null);
339 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700340 } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
341 String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
342 if (newAddress != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800343 if (DBG) {
344 Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
345 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700346 storeNameAndAddress(null, newAddress);
347 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800348 if (DBG) {
349 Slog.e(TAG, "No Bluetooth Adapter address parameter found");
350 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700351 }
Stanley Tng873b5702017-05-01 21:27:31 -0700352 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
353 final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
354 if (Settings.Global.BLUETOOTH_ON.equals(name)) {
355 // The Bluetooth On state may be changed during system restore.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800356 final String prevValue =
357 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
358 final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
Stanley Tng873b5702017-05-01 21:27:31 -0700359
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800360 if (DBG) {
361 Slog.d(TAG,
362 "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue
363 + ", newValue=" + newValue);
364 }
Stanley Tng873b5702017-05-01 21:27:31 -0700365
366 if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
367 Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800368 newValue.equals("0") ? RESTORE_SETTING_TO_OFF
369 : RESTORE_SETTING_TO_ON, 0);
Stanley Tng873b5702017-05-01 21:27:31 -0700370 mHandler.sendMessage(msg);
371 }
372 }
fredc0f420372012-04-12 00:02:00 -0700373 }
374 }
375 };
376
377 BluetoothManagerService(Context context) {
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700378 mHandler = new BluetoothHandler(IoThread.get().getLooper());
Zhihai Xu40874a02012-10-08 17:57:03 -0700379
fredc0f420372012-04-12 00:02:00 -0700380 mContext = context;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700381
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700382 mWirelessConsentRequired = context.getResources()
383 .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700384
Marie Janssene54b4222017-03-16 18:10:59 -0700385 mCrashes = 0;
fredc0f420372012-04-12 00:02:00 -0700386 mBluetooth = null;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800387 mBluetoothBinder = null;
Nitin Arorad055adb2015-03-02 15:03:51 -0800388 mBluetoothGatt = null;
fredc0f420372012-04-12 00:02:00 -0700389 mBinding = false;
390 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -0700391 mEnable = false;
392 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800393 mQuietEnableExternal = false;
394 mEnableExternal = false;
fredc0f420372012-04-12 00:02:00 -0700395 mAddress = null;
396 mName = null;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800397 mErrorRecoveryRetryCounter = 0;
fredc0f420372012-04-12 00:02:00 -0700398 mContentResolver = context.getContentResolver();
Wei Wange4a744b2015-06-11 17:50:29 -0700399 // Observe BLE scan only mode settings change.
400 registerForBleScanModeChange();
fredcd6883532012-04-25 17:46:13 -0700401 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
402 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
Stanley Tng873b5702017-05-01 21:27:31 -0700403
Stanley Tng61dbd812019-01-13 16:04:31 -0800404 mIsHearingAidProfileSupported = context.getResources()
405 .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);
406
Stanley Tngfe8c8332018-06-19 08:48:10 -0700407 // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
Stanley Tngfe8c8332018-06-19 08:48:10 -0700408 String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
409 if (!TextUtils.isEmpty(value)) {
Stanley Tng61dbd812019-01-13 16:04:31 -0800410 boolean isHearingAidEnabled = Boolean.parseBoolean(value);
Stanley Tngfe8c8332018-06-19 08:48:10 -0700411 Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
412 FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
Stanley Tng61dbd812019-01-13 16:04:31 -0800413 if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
414 // Overwrite to enable support by FeatureFlag
415 mIsHearingAidProfileSupported = true;
416 }
Stanley Tngfe8c8332018-06-19 08:48:10 -0700417 }
418
Stanley Tng873b5702017-05-01 21:27:31 -0700419 IntentFilter filter = new IntentFilter();
420 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
421 filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
422 filter.addAction(Intent.ACTION_SETTING_RESTORED);
Dianne Hackbornd83a0962014-05-02 16:28:33 -0700423 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Matthew Xie6fde3092012-07-11 17:10:07 -0700424 mContext.registerReceiver(mReceiver, filter);
Stanley Tng873b5702017-05-01 21:27:31 -0700425
fredc0f420372012-04-12 00:02:00 -0700426 loadStoredNameAndAddress();
Zhihai Xu401202b2012-12-03 11:36:21 -0800427 if (isBluetoothPersistedStateOn()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800428 if (DBG) {
429 Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
430 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800431 mEnableExternal = true;
fredc0f420372012-04-12 00:02:00 -0700432 }
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200433
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800434 String airplaneModeRadios =
435 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
436 if (airplaneModeRadios == null || airplaneModeRadios.contains(
437 Settings.Global.RADIO_BLUETOOTH)) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800438 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800439 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
440 mAirplaneModeObserver);
Ajay Panicker467bc042017-02-22 12:23:15 -0800441 }
442
Marie Janssen59804562016-12-28 14:13:21 -0800443 int systemUiUid = -1;
Winson Chungf2b41772019-11-06 15:00:48 -0800444 // Check if device is configured with no home screen, which implies no SystemUI.
445 boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
446 if (!noHome) {
447 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
448 systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
449 MATCH_SYSTEM_ONLY, USER_SYSTEM);
450 }
451 if (systemUiUid >= 0) {
Arthur Hsuf3f95a92018-01-11 16:46:22 -0800452 Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
Winson Chungf2b41772019-11-06 15:00:48 -0800453 } else {
Joe LaPennaacddf2b2015-09-04 12:52:42 -0700454 // Some platforms, such as wearables do not have a system ui.
Winson Chungf2b41772019-11-06 15:00:48 -0800455 Slog.w(TAG, "Unable to resolve SystemUI's UID.");
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200456 }
Marie Janssen59804562016-12-28 14:13:21 -0800457 mSystemUiUid = systemUiUid;
fredc0f420372012-04-12 00:02:00 -0700458 }
459
fredc649fe492012-04-19 01:07:18 -0700460 /**
461 * Returns true if airplane mode is currently on
462 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800463 private boolean isAirplaneModeOn() {
Christopher Tatec09cdce2012-09-10 16:50:14 -0700464 return Settings.Global.getInt(mContext.getContentResolver(),
465 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
fredc649fe492012-04-19 01:07:18 -0700466 }
467
Arthur Hsu2433baf2018-01-11 11:05:11 -0800468 private boolean supportBluetoothPersistedState() {
469 return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
470 }
471
fredc649fe492012-04-19 01:07:18 -0700472 /**
473 * Returns true if the Bluetooth saved state is "on"
474 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800475 private boolean isBluetoothPersistedStateOn() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800476 if (!supportBluetoothPersistedState()) {
477 return false;
478 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800479 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
480 if (DBG) {
481 Slog.d(TAG, "Bluetooth persisted state: " + state);
482 }
Marie Janssen9fa24912016-10-18 10:04:24 -0700483 return state != BLUETOOTH_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800484 }
485
486 /**
487 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
488 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800489 private boolean isBluetoothPersistedStateOnBluetooth() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800490 if (!supportBluetoothPersistedState()) {
491 return false;
492 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800493 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
494 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
fredc649fe492012-04-19 01:07:18 -0700495 }
496
497 /**
498 * Save the Bluetooth on/off state
fredc649fe492012-04-19 01:07:18 -0700499 */
Zhihai Xu401202b2012-12-03 11:36:21 -0800500 private void persistBluetoothSetting(int value) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800501 if (DBG) {
502 Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
503 }
Marie Janssenfa630682016-12-15 13:51:30 -0800504 // waive WRITE_SECURE_SETTINGS permission check
505 long callingIdentity = Binder.clearCallingIdentity();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800506 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value);
Marie Janssenfa630682016-12-15 13:51:30 -0800507 Binder.restoreCallingIdentity(callingIdentity);
fredc649fe492012-04-19 01:07:18 -0700508 }
509
510 /**
511 * Returns true if the Bluetooth Adapter's name and address is
512 * locally cached
513 * @return
514 */
fredc0f420372012-04-12 00:02:00 -0700515 private boolean isNameAndAddressSet() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800516 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
fredc0f420372012-04-12 00:02:00 -0700517 }
518
fredc649fe492012-04-19 01:07:18 -0700519 /**
520 * Retrieve the Bluetooth Adapter's name and address and save it in
521 * in the local cache
522 */
fredc0f420372012-04-12 00:02:00 -0700523 private void loadStoredNameAndAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800524 if (DBG) {
525 Slog.d(TAG, "Loading stored name and address");
526 }
527 if (mContext.getResources()
528 .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
529 && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0)
530 == 0) {
Zhihai Xud31c3222012-10-31 16:08:57 -0700531 // if the valid flag is not set, don't load the address and name
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800532 if (DBG) {
533 Slog.d(TAG, "invalid bluetooth name and address stored");
534 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700535 return;
536 }
fredc0f420372012-04-12 00:02:00 -0700537 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
538 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800539 if (DBG) {
540 Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
541 }
fredc0f420372012-04-12 00:02:00 -0700542 }
543
fredc649fe492012-04-19 01:07:18 -0700544 /**
545 * Save the Bluetooth name and address in the persistent store.
546 * Only non-null values will be saved.
547 * @param name
548 * @param address
549 */
fredc0f420372012-04-12 00:02:00 -0700550 private void storeNameAndAddress(String name, String address) {
551 if (name != null) {
552 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
fredc0f420372012-04-12 00:02:00 -0700553 mName = name;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800554 if (DBG) {
555 Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver,
556 SECURE_SETTINGS_BLUETOOTH_NAME));
557 }
fredc0f420372012-04-12 00:02:00 -0700558 }
559
560 if (address != null) {
561 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800562 mAddress = address;
563 if (DBG) {
564 Slog.d(TAG,
565 "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver,
566 SECURE_SETTINGS_BLUETOOTH_ADDRESS));
567 }
fredc0f420372012-04-12 00:02:00 -0700568 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700569
570 if ((name != null) && (address != null)) {
571 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
572 }
fredc0f420372012-04-12 00:02:00 -0700573 }
574
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800575 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700576 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700577 Slog.w(TAG, "Callback is null in registerAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700578 return null;
579 }
fredc0f420372012-04-12 00:02:00 -0700580 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
581 msg.obj = callback;
582 mHandler.sendMessage(msg);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700583
584 return mBluetooth;
fredc0f420372012-04-12 00:02:00 -0700585 }
586
587 public void unregisterAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700588 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700589 Slog.w(TAG, "Callback is null in unregisterAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700590 return;
591 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800592 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
fredc0f420372012-04-12 00:02:00 -0700593 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
594 msg.obj = callback;
595 mHandler.sendMessage(msg);
596 }
597
598 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800599 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800600 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800601 Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
602 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800603 }
fredc0f420372012-04-12 00:02:00 -0700604 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
605 msg.obj = callback;
606 mHandler.sendMessage(msg);
607 }
608
609 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800610 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800611 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800612 Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
613 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800614 }
fredc0f420372012-04-12 00:02:00 -0700615 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
616 msg.obj = callback;
617 mHandler.sendMessage(msg);
618 }
619
620 public boolean isEnabled() {
Zach Johnson76236d72019-11-26 21:30:07 -0800621 return getState() == BluetoothAdapter.STATE_ON;
fredc0f420372012-04-12 00:02:00 -0700622 }
623
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700624 public int getState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800625 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
Marie Janssencb21ad72016-12-13 10:51:02 -0800626 Slog.w(TAG, "getState(): report OFF for non-active and non system user");
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700627 return BluetoothAdapter.STATE_OFF;
628 }
629
630 try {
631 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800632 if (mBluetooth != null) {
633 return mBluetooth.getState();
634 }
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700635 } catch (RemoteException e) {
636 Slog.e(TAG, "getState()", e);
637 } finally {
638 mBluetoothLock.readLock().unlock();
639 }
640 return BluetoothAdapter.STATE_OFF;
641 }
642
Nitin Arorad055adb2015-03-02 15:03:51 -0800643 class ClientDeathRecipient implements IBinder.DeathRecipient {
Marie Janssen59804562016-12-28 14:13:21 -0800644 private String mPackageName;
645
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800646 ClientDeathRecipient(String packageName) {
Marie Janssen59804562016-12-28 14:13:21 -0800647 mPackageName = packageName;
648 }
649
Nitin Arorad055adb2015-03-02 15:03:51 -0800650 public void binderDied() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800651 if (DBG) {
652 Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
Marie Janssen2977c3e2016-11-09 12:01:24 -0800653 }
Stanley Tng2c5fd282018-03-19 13:06:45 -0700654
655 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
656 IBinder token = entry.getKey();
657 ClientDeathRecipient deathRec = entry.getValue();
658 if (deathRec.equals(this)) {
Stanley Tng600109c2018-03-20 16:54:27 -0700659 updateBleAppCount(token, false, mPackageName);
Stanley Tng2c5fd282018-03-19 13:06:45 -0700660 break;
661 }
662 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800663 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800664
Marie Janssen59804562016-12-28 14:13:21 -0800665 public String getPackageName() {
666 return mPackageName;
667 }
668 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800669
Wei Wang67d84162015-04-26 17:04:29 -0700670 @Override
671 public boolean isBleScanAlwaysAvailable() {
Marie Janssena80d7452016-10-25 10:47:51 -0700672 if (isAirplaneModeOn() && !mEnable) {
673 return false;
674 }
Wei Wang67d84162015-04-26 17:04:29 -0700675 try {
Jack He8caab152018-03-02 13:08:36 -0800676 return Settings.Global.getInt(mContentResolver,
677 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
Wei Wang67d84162015-04-26 17:04:29 -0700678 } catch (SettingNotFoundException e) {
679 }
680 return false;
681 }
682
Stanley Tng61dbd812019-01-13 16:04:31 -0800683 @Override
684 public boolean isHearingAidProfileSupported() {
685 return mIsHearingAidProfileSupported;
686 }
687
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +0100688 @Override
689 /** @hide */
690 public java.util.List<String> getSystemConfigEnabledProfilesForPackage(String packageName) {
691 if (Binder.getCallingUid() != Process.BLUETOOTH_UID) {
692 Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth");
693 return null;
694 }
695
696 SystemConfig systemConfig = SystemConfig.getInstance();
697 if (systemConfig == null) {
698 return null;
699 }
700
701 android.util.ArrayMap<String, Boolean> componentEnabledStates =
702 systemConfig.getComponentsEnabledStates(packageName);
703 if (componentEnabledStates == null) {
704 return null;
705 }
706
707 ArrayList enabledProfiles = new ArrayList<String>();
708 for (Map.Entry<String, Boolean> entry : componentEnabledStates.entrySet()) {
709 if (entry.getValue()) {
710 enabledProfiles.add(entry.getKey());
711 }
712 }
713
714 return enabledProfiles;
715 }
716
Wei Wange4a744b2015-06-11 17:50:29 -0700717 // Monitor change of BLE scan only mode settings.
718 private void registerForBleScanModeChange() {
719 ContentObserver contentObserver = new ContentObserver(null) {
720 @Override
721 public void onChange(boolean selfChange) {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800722 if (isBleScanAlwaysAvailable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800723 // Nothing to do
724 return;
Marie Janssen2977c3e2016-11-09 12:01:24 -0800725 }
726 // BLE scan is not available.
727 disableBleScanMode();
728 clearBleApps();
729 try {
730 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800731 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700732 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
733 mContext.getPackageName(), false);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800734 mBluetooth.onBrEdrDown();
735 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800736 } catch (RemoteException e) {
737 Slog.e(TAG, "error when disabling bluetooth", e);
738 } finally {
739 mBluetoothLock.readLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700740 }
741 }
742 };
743
744 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800745 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
746 contentObserver);
Wei Wange4a744b2015-06-11 17:50:29 -0700747 }
748
749 // Disable ble scan only mode.
750 private void disableBleScanMode() {
751 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700752 mBluetoothLock.writeLock().lock();
Wei Wange4a744b2015-06-11 17:50:29 -0700753 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800754 if (DBG) {
755 Slog.d(TAG, "Reseting the mEnable flag for clean disable");
756 }
Wei Wange4a744b2015-06-11 17:50:29 -0700757 mEnable = false;
758 }
759 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700760 Slog.e(TAG, "getState()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700761 } finally {
762 mBluetoothLock.writeLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700763 }
764 }
765
Marie Janssen59804562016-12-28 14:13:21 -0800766 public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
Jack Hea80cead2019-04-23 20:00:18 -0700767 // Check if packageName belongs to callingUid
768 final int callingUid = Binder.getCallingUid();
769 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
770 if (!isCallerSystem) {
771 checkPackage(callingUid, packageName);
772 }
Marie Janssen59804562016-12-28 14:13:21 -0800773 ClientDeathRecipient r = mBleApps.get(token);
774 if (r == null && enable) {
775 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
776 try {
777 token.linkToDeath(deathRec, 0);
778 } catch (RemoteException ex) {
779 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
Nitin Arorad055adb2015-03-02 15:03:51 -0800780 }
Marie Janssen59804562016-12-28 14:13:21 -0800781 mBleApps.put(token, deathRec);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800782 if (DBG) {
783 Slog.d(TAG, "Registered for death of " + packageName);
784 }
Marie Janssen59804562016-12-28 14:13:21 -0800785 } else if (!enable && r != null) {
786 // Unregister death recipient as the app goes away.
787 token.unlinkToDeath(r, 0);
788 mBleApps.remove(token);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800789 if (DBG) {
790 Slog.d(TAG, "Unregistered for death of " + packageName);
791 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800792 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800793 int appCount = mBleApps.size();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800794 if (DBG) {
795 Slog.d(TAG, appCount + " registered Ble Apps");
796 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800797 if (appCount == 0 && mEnable) {
Wei Wange4a744b2015-06-11 17:50:29 -0700798 disableBleScanMode();
Nitin Arorad055adb2015-03-02 15:03:51 -0800799 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800800 if (appCount == 0 && !mEnableExternal) {
801 sendBrEdrDownCallback();
802 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800803 return appCount;
Nitin Arorad055adb2015-03-02 15:03:51 -0800804 }
805
Wei Wange4a744b2015-06-11 17:50:29 -0700806 // Clear all apps using BLE scan only mode.
807 private void clearBleApps() {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800808 mBleApps.clear();
Wei Wange4a744b2015-06-11 17:50:29 -0700809 }
810
Marie Janssen59804562016-12-28 14:13:21 -0800811 /** @hide */
Nitin Arorad055adb2015-03-02 15:03:51 -0800812 public boolean isBleAppPresent() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800813 if (DBG) {
814 Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
815 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800816 return mBleApps.size() > 0;
Nitin Arorad055adb2015-03-02 15:03:51 -0800817 }
818
819 /**
Myles Watson304ebf22018-05-11 08:47:24 -0700820 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
Nitin Arorad055adb2015-03-02 15:03:51 -0800821 */
Myles Watson304ebf22018-05-11 08:47:24 -0700822 private void continueFromBleOnState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800823 if (DBG) {
Myles Watson304ebf22018-05-11 08:47:24 -0700824 Slog.d(TAG, "continueFromBleOnState()");
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800825 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700826 try {
827 mBluetoothLock.readLock().lock();
Marie Janssenfa630682016-12-15 13:51:30 -0800828 if (mBluetooth == null) {
Myles Watson304ebf22018-05-11 08:47:24 -0700829 Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
Marie Janssenfa630682016-12-15 13:51:30 -0800830 return;
831 }
832 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
833 // This triggers transition to STATE_ON
Nitin Arorad055adb2015-03-02 15:03:51 -0800834 mBluetooth.onLeServiceUp();
Nitin Arorad055adb2015-03-02 15:03:51 -0800835 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Nitin Arorad055adb2015-03-02 15:03:51 -0800836 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700837 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800838 Slog.e(TAG, "Unable to call onServiceUp", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700839 } finally {
840 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800841 }
842 }
843
844 /**
845 * Inform BluetoothAdapter instances that BREDR part is down
846 * and turn off all service and stack if no LE app needs it
847 */
848 private void sendBrEdrDownCallback() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800849 if (DBG) {
850 Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
851 }
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700852
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700853 if (mBluetooth == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700854 Slog.w(TAG, "Bluetooth handle is null");
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700855 return;
856 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800857
Martin Brabhamc2b06222017-02-27 16:55:07 -0800858 if (isBleAppPresent()) {
859 // Need to stay at BLE ON. Disconnect all Gatt connections
860 try {
861 mBluetoothGatt.unregAll();
862 } catch (RemoteException e) {
863 Slog.e(TAG, "Unable to disconnect all apps.", e);
864 }
865 } else {
Nitin Arorad055adb2015-03-02 15:03:51 -0800866 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700867 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800868 if (mBluetooth != null) {
869 mBluetooth.onBrEdrDown();
870 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700871 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700872 Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700873 } finally {
874 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800875 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800876 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800877
Nitin Arorad055adb2015-03-02 15:03:51 -0800878 }
879
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800880 public boolean enableNoAutoConnect(String packageName) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100881 if (isBluetoothDisallowed()) {
882 if (DBG) {
883 Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
884 }
885 return false;
886 }
887
Jack Hea80cead2019-04-23 20:00:18 -0700888 // Check if packageName belongs to callingUid
889 final int callingUid = Binder.getCallingUid();
890 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
891 if (!isCallerSystem) {
892 checkPackage(callingUid, packageName);
893 }
894
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700895 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800896 "Need BLUETOOTH ADMIN permission");
Zhihai Xu40874a02012-10-08 17:57:03 -0700897
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700898 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800899 Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = "
900 + mBinding);
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700901 }
Jack Hea80cead2019-04-23 20:00:18 -0700902 int callingAppId = UserHandle.getAppId(callingUid);
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800903
904 if (callingAppId != Process.NFC_UID) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700905 throw new SecurityException("no permission to enable Bluetooth quietly");
906 }
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800907
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800908 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800909 mQuietEnableExternal = true;
910 mEnableExternal = true;
Jack He8caab152018-03-02 13:08:36 -0800911 sendEnableMsg(true,
912 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800913 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700914 return true;
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700915 }
Ajay Panicker4bb48302016-03-31 14:14:27 -0700916
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700917 public boolean enable(String packageName) throws RemoteException {
918 final int callingUid = Binder.getCallingUid();
919 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
920
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100921 if (isBluetoothDisallowed()) {
922 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800923 Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100924 }
925 return false;
926 }
927
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700928 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700929 // Check if packageName belongs to callingUid
930 checkPackage(callingUid, packageName);
931
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700932 if (!checkIfCallerIsForegroundUser()) {
933 Slog.w(TAG, "enable(): not allowed for non-active and non system user");
934 return false;
935 }
936
937 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
938 "Need BLUETOOTH ADMIN permission");
939
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700940 if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800941 callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700942 return false;
943 }
fredcf2458862012-04-16 15:18:27 -0700944 }
945
Zhihai Xu401202b2012-12-03 11:36:21 -0800946 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800947 Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
948 + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
Sanket Agarwal090bf552016-04-21 14:10:55 -0700949 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800950
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800951 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800952 mQuietEnableExternal = false;
953 mEnableExternal = true;
954 // waive WRITE_SECURE_SETTINGS permission check
Jack He8caab152018-03-02 13:08:36 -0800955 sendEnableMsg(false,
956 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800957 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800958 if (DBG) {
959 Slog.d(TAG, "enable returning");
960 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800961 return true;
fredc0f420372012-04-12 00:02:00 -0700962 }
963
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700964 public boolean disable(String packageName, boolean persist) throws RemoteException {
965 final int callingUid = Binder.getCallingUid();
966 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
Zhihai Xu40874a02012-10-08 17:57:03 -0700967
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700968 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700969 // Check if packageName belongs to callingUid
970 checkPackage(callingUid, packageName);
971
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700972 if (!checkIfCallerIsForegroundUser()) {
973 Slog.w(TAG, "disable(): not allowed for non-active and non system user");
974 return false;
975 }
976
977 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
978 "Need BLUETOOTH ADMIN permission");
979
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700980 if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800981 callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700982 return false;
983 }
Zhihai Xu40874a02012-10-08 17:57:03 -0700984 }
985
fredcf2458862012-04-16 15:18:27 -0700986 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800987 Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
Matthew Xiecdce0b92012-07-12 19:06:15 -0700988 }
fredcf2458862012-04-16 15:18:27 -0700989
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800990 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800991 if (persist) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800992 persistBluetoothSetting(BLUETOOTH_OFF);
Zhihai Xu401202b2012-12-03 11:36:21 -0800993 }
994 mEnableExternal = false;
Jack He8caab152018-03-02 13:08:36 -0800995 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
996 packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800997 }
fredc0f420372012-04-12 00:02:00 -0700998 return true;
999 }
1000
baishengf62d8692018-01-25 18:07:24 +08001001 private boolean startConsentUiIfNeeded(String packageName,
1002 int callingUid, String intentAction) throws RemoteException {
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001003 if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
baishengf62d8692018-01-25 18:07:24 +08001004 return false;
1005 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001006 try {
1007 // Validate the package only if we are going to use it
1008 ApplicationInfo applicationInfo = mContext.getPackageManager()
1009 .getApplicationInfoAsUser(packageName,
1010 PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
1011 UserHandle.getUserId(callingUid));
1012 if (applicationInfo.uid != callingUid) {
baishengf62d8692018-01-25 18:07:24 +08001013 throw new SecurityException("Package " + packageName
1014 + " not in uid " + callingUid);
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001015 }
1016
Ivan Podogovd2d32b12016-12-05 16:46:52 +00001017 Intent intent = new Intent(intentAction);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001018 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001019 intent.setFlags(
1020 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001021 try {
1022 mContext.startActivity(intent);
1023 } catch (ActivityNotFoundException e) {
1024 // Shouldn't happen
1025 Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
1026 return false;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001027 }
Ivan Podogov1ab87252017-01-03 12:02:18 +00001028 return true;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001029 } catch (PackageManager.NameNotFoundException e) {
1030 throw new RemoteException(e.getMessage());
1031 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001032 }
1033
baishengf62d8692018-01-25 18:07:24 +08001034 /**
Jack Hea80cead2019-04-23 20:00:18 -07001035 * Check if AppOpsManager is available and the packageName belongs to uid
1036 *
1037 * A null package belongs to any uid
1038 */
1039 private void checkPackage(int uid, String packageName) {
1040 if (mAppOps == null) {
1041 Slog.w(TAG, "checkPackage(): called before system boot up, uid "
1042 + uid + ", packageName " + packageName);
1043 throw new IllegalStateException("System has not boot yet");
1044 }
1045 if (packageName == null) {
1046 Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
1047 return;
1048 }
1049 try {
1050 mAppOps.checkPackage(uid, packageName);
1051 } catch (SecurityException e) {
1052 Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
Jack Hea80cead2019-04-23 20:00:18 -07001053 throw new SecurityException(e.getMessage());
1054 }
1055 }
1056
1057 /**
baishengf62d8692018-01-25 18:07:24 +08001058 * Check if the caller must still pass permission check or if the caller is exempted
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001059 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
baishengf62d8692018-01-25 18:07:24 +08001060 *
1061 * Commands from some callers may be exempted from triggering the consent UI when
1062 * enabling bluetooth. This exemption is checked via the
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001063 * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
baishengf62d8692018-01-25 18:07:24 +08001064 * the consent UI where it may otherwise be required.
1065 *
1066 * @hide
1067 */
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001068 private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
baishengf62d8692018-01-25 18:07:24 +08001069 int result = mContext.checkCallingPermission(
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001070 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
baishengf62d8692018-01-25 18:07:24 +08001071 return result == PackageManager.PERMISSION_GRANTED;
1072 }
1073
fredc649fe492012-04-19 01:07:18 -07001074 public void unbindAndFinish() {
fredcf2458862012-04-16 15:18:27 -07001075 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001076 Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
1077 + " mUnbinding = " + mUnbinding);
fredcf2458862012-04-16 15:18:27 -07001078 }
1079
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001080 try {
1081 mBluetoothLock.writeLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001082 if (mUnbinding) {
1083 return;
1084 }
fredc0f420372012-04-12 00:02:00 -07001085 mUnbinding = true;
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001086 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
Pavlin Radoslavov74f60c02016-09-21 17:28:11 -07001087 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
Zhihai Xu40874a02012-10-08 17:57:03 -07001088 if (mBluetooth != null) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001089 //Unregister callback object
1090 try {
1091 mBluetooth.unregisterCallback(mBluetoothCallback);
1092 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001093 Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001094 }
Marie Janssen9db28eb2016-01-12 16:05:15 -08001095 mBluetoothBinder = null;
fredcd6883532012-04-25 17:46:13 -07001096 mBluetooth = null;
fredc0f420372012-04-12 00:02:00 -07001097 mContext.unbindService(mConnection);
fredcd6883532012-04-25 17:46:13 -07001098 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -07001099 mBinding = false;
fredcf2458862012-04-16 15:18:27 -07001100 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001101 mUnbinding = false;
fredc0f420372012-04-12 00:02:00 -07001102 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001103 mBluetoothGatt = null;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001104 } finally {
1105 mBluetoothLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -07001106 }
1107 }
1108
Matthew Xieddf7e472013-03-01 18:41:02 -08001109 public IBluetoothGatt getBluetoothGatt() {
1110 // sync protection
1111 return mBluetoothGatt;
1112 }
1113
Benjamin Franze8b98922014-11-12 15:57:54 +00001114 @Override
1115 public boolean bindBluetoothProfileService(int bluetoothProfile,
1116 IBluetoothProfileServiceConnection proxy) {
1117 if (!mEnable) {
1118 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001119 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
1120 + ", while Bluetooth was disabled");
Benjamin Franze8b98922014-11-12 15:57:54 +00001121 }
1122 return false;
1123 }
1124 synchronized (mProfileServices) {
1125 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
1126 if (psc == null) {
1127 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001128 Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
1129 + bluetoothProfile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001130 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001131
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001132 if (bluetoothProfile != BluetoothProfile.HEADSET) {
1133 return false;
1134 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001135
1136 Intent intent = new Intent(IBluetoothHeadset.class.getName());
Benjamin Franze8b98922014-11-12 15:57:54 +00001137 psc = new ProfileServiceConnections(intent);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001138 if (!psc.bindService()) {
1139 return false;
1140 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001141
Benjamin Franze8b98922014-11-12 15:57:54 +00001142 mProfileServices.put(new Integer(bluetoothProfile), psc);
Benjamin Franze8b98922014-11-12 15:57:54 +00001143 }
1144 }
1145
1146 // Introducing a delay to give the client app time to prepare
1147 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
1148 addProxyMsg.arg1 = bluetoothProfile;
1149 addProxyMsg.obj = proxy;
1150 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
1151 return true;
1152 }
1153
1154 @Override
1155 public void unbindBluetoothProfileService(int bluetoothProfile,
1156 IBluetoothProfileServiceConnection proxy) {
1157 synchronized (mProfileServices) {
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001158 Integer profile = new Integer(bluetoothProfile);
1159 ProfileServiceConnections psc = mProfileServices.get(profile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001160 if (psc == null) {
1161 return;
1162 }
1163 psc.removeProxy(proxy);
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001164 if (psc.isEmpty()) {
1165 // All prxoies are disconnected, unbind with the service.
1166 try {
1167 mContext.unbindService(psc);
1168 } catch (IllegalArgumentException e) {
1169 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
1170 }
1171 mProfileServices.remove(profile);
1172 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001173 }
1174 }
1175
1176 private void unbindAllBluetoothProfileServices() {
1177 synchronized (mProfileServices) {
1178 for (Integer i : mProfileServices.keySet()) {
1179 ProfileServiceConnections psc = mProfileServices.get(i);
Benjamin Franz5b614592014-12-09 18:58:45 +00001180 try {
1181 mContext.unbindService(psc);
1182 } catch (IllegalArgumentException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001183 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
Benjamin Franz5b614592014-12-09 18:58:45 +00001184 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001185 psc.removeAllProxies();
1186 }
1187 mProfileServices.clear();
1188 }
1189 }
1190
1191 /**
Miao Chou658bf2f2015-06-26 17:14:35 -07001192 * Send enable message and set adapter name and address. Called when the boot phase becomes
1193 * PHASE_SYSTEM_SERVICES_READY.
1194 */
1195 public void handleOnBootPhase() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001196 if (DBG) {
1197 Slog.d(TAG, "Bluetooth boot completed");
1198 }
Jack Hea80cead2019-04-23 20:00:18 -07001199 mAppOps = mContext.getSystemService(AppOpsManager.class);
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001200 UserManagerInternal userManagerInternal =
1201 LocalServices.getService(UserManagerInternal.class);
1202 userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001203 final boolean isBluetoothDisallowed = isBluetoothDisallowed();
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001204 if (isBluetoothDisallowed) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001205 return;
1206 }
Zongheng Wang79e0bf62019-07-08 15:22:04 -07001207 final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
1208 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001209 if (DBG) {
1210 Slog.d(TAG, "Auto-enabling Bluetooth.");
1211 }
Jack He8caab152018-03-02 13:08:36 -08001212 sendEnableMsg(mQuietEnableExternal,
1213 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
1214 mContext.getPackageName());
Ajay Panickerbf796d82016-03-11 13:47:20 -08001215 } else if (!isNameAndAddressSet()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001216 if (DBG) {
1217 Slog.d(TAG, "Getting adapter name and address");
1218 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001219 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1220 mHandler.sendMessage(getMsg);
Miao Chou658bf2f2015-06-26 17:14:35 -07001221 }
Miao Chou658bf2f2015-06-26 17:14:35 -07001222 }
1223
1224 /**
1225 * Called when switching to a different foreground user.
1226 */
1227 public void handleOnSwitchUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001228 if (DBG) {
1229 Slog.d(TAG, "User " + userHandle + " switched");
1230 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001231 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1232 }
1233
1234 /**
1235 * Called when user is unlocked.
1236 */
1237 public void handleOnUnlockUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001238 if (DBG) {
1239 Slog.d(TAG, "User " + userHandle + " unlocked");
1240 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001241 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
Miao Chou658bf2f2015-06-26 17:14:35 -07001242 }
1243
1244 /**
Benjamin Franze8b98922014-11-12 15:57:54 +00001245 * This class manages the clients connected to a given ProfileService
1246 * and maintains the connection with that service.
1247 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001248 private final class ProfileServiceConnections
1249 implements ServiceConnection, IBinder.DeathRecipient {
Benjamin Franze8b98922014-11-12 15:57:54 +00001250 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001251 new RemoteCallbackList<IBluetoothProfileServiceConnection>();
Benjamin Franze8b98922014-11-12 15:57:54 +00001252 IBinder mService;
1253 ComponentName mClassName;
1254 Intent mIntent;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001255 boolean mInvokingProxyCallbacks = false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001256
1257 ProfileServiceConnections(Intent intent) {
1258 mService = null;
1259 mClassName = null;
1260 mIntent = intent;
1261 }
1262
Benjamin Franz5b614592014-12-09 18:58:45 +00001263 private boolean bindService() {
jonerlin37fc85d2018-08-09 16:39:43 +08001264 int state = BluetoothAdapter.STATE_OFF;
1265 try {
1266 mBluetoothLock.readLock().lock();
1267 if (mBluetooth != null) {
1268 state = mBluetooth.getState();
1269 }
1270 } catch (RemoteException e) {
1271 Slog.e(TAG, "Unable to call getState", e);
1272 return false;
1273 } finally {
1274 mBluetoothLock.readLock().unlock();
1275 }
1276
1277 if (!mEnable || state != BluetoothAdapter.STATE_ON) {
1278 if (DBG) {
1279 Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
1280 }
1281 return false;
1282 }
1283
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001284 if (mIntent != null && mService == null && doBind(mIntent, this, 0,
1285 UserHandle.CURRENT_OR_SELF)) {
Benjamin Franze8b98922014-11-12 15:57:54 +00001286 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1287 msg.obj = this;
1288 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
Benjamin Franz5b614592014-12-09 18:58:45 +00001289 return true;
Benjamin Franze8b98922014-11-12 15:57:54 +00001290 }
Jeff Sharkey67609c72016-03-05 14:29:13 -07001291 Slog.w(TAG, "Unable to bind with intent: " + mIntent);
Benjamin Franz5b614592014-12-09 18:58:45 +00001292 return false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001293 }
1294
1295 private void addProxy(IBluetoothProfileServiceConnection proxy) {
1296 mProxies.register(proxy);
1297 if (mService != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001298 try {
Benjamin Franze8b98922014-11-12 15:57:54 +00001299 proxy.onServiceConnected(mClassName, mService);
1300 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001301 Slog.e(TAG, "Unable to connect to proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001302 }
1303 } else {
1304 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1305 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1306 msg.obj = this;
1307 mHandler.sendMessage(msg);
1308 }
1309 }
1310 }
1311
1312 private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1313 if (proxy != null) {
1314 if (mProxies.unregister(proxy)) {
1315 try {
1316 proxy.onServiceDisconnected(mClassName);
1317 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001318 Slog.e(TAG, "Unable to disconnect proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001319 }
1320 }
1321 } else {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001322 Slog.w(TAG, "Trying to remove a null proxy");
Benjamin Franze8b98922014-11-12 15:57:54 +00001323 }
1324 }
1325
1326 private void removeAllProxies() {
1327 onServiceDisconnected(mClassName);
1328 mProxies.kill();
1329 }
1330
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001331 private boolean isEmpty() {
1332 return mProxies.getRegisteredCallbackCount() == 0;
1333 }
1334
Benjamin Franze8b98922014-11-12 15:57:54 +00001335 @Override
1336 public void onServiceConnected(ComponentName className, IBinder service) {
1337 // remove timeout message
1338 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1339 mService = service;
1340 mClassName = className;
1341 try {
1342 mService.linkToDeath(this, 0);
1343 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001344 Slog.e(TAG, "Unable to linkToDeath", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001345 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001346
1347 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001348 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001349 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001350 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001351 mInvokingProxyCallbacks = true;
1352
1353 final int n = mProxies.beginBroadcast();
1354 try {
1355 for (int i = 0; i < n; i++) {
1356 try {
1357 mProxies.getBroadcastItem(i).onServiceConnected(className, service);
1358 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001359 Slog.e(TAG, "Unable to connect to proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001360 }
1361 }
1362 } finally {
1363 mProxies.finishBroadcast();
1364 mInvokingProxyCallbacks = false;
1365 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001366 }
1367
1368 @Override
1369 public void onServiceDisconnected(ComponentName className) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001370 if (mService == null) {
1371 return;
1372 }
Chienyuan177156b2018-12-18 10:40:25 +08001373 try {
1374 mService.unlinkToDeath(this, 0);
1375 } catch (NoSuchElementException e) {
1376 Log.e(TAG, "error unlinking to death", e);
1377 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001378 mService = null;
1379 mClassName = null;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001380
1381 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001382 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001383 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001384 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001385 mInvokingProxyCallbacks = true;
1386
1387 final int n = mProxies.beginBroadcast();
1388 try {
1389 for (int i = 0; i < n; i++) {
1390 try {
1391 mProxies.getBroadcastItem(i).onServiceDisconnected(className);
1392 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001393 Slog.e(TAG, "Unable to disconnect from proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001394 }
1395 }
1396 } finally {
1397 mProxies.finishBroadcast();
1398 mInvokingProxyCallbacks = false;
1399 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001400 }
1401
1402 @Override
1403 public void binderDied() {
1404 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001405 Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
Benjamin Franze8b98922014-11-12 15:57:54 +00001406 }
1407 onServiceDisconnected(mClassName);
1408 // Trigger rebind
1409 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1410 msg.obj = this;
1411 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1412 }
1413 }
1414
fredcbf072a72012-05-09 16:52:50 -07001415 private void sendBluetoothStateCallback(boolean isUp) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001416 try {
1417 int n = mStateChangeCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001418 if (DBG) {
1419 Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
1420 + " receivers.");
1421 }
1422 for (int i = 0; i < n; i++) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001423 try {
1424 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
1425 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001426 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001427 }
fredcbf072a72012-05-09 16:52:50 -07001428 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001429 } finally {
1430 mStateChangeCallbacks.finishBroadcast();
fredcbf072a72012-05-09 16:52:50 -07001431 }
fredcbf072a72012-05-09 16:52:50 -07001432 }
1433
1434 /**
Zhihai Xu40874a02012-10-08 17:57:03 -07001435 * Inform BluetoothAdapter instances that Adapter service is up
1436 */
1437 private void sendBluetoothServiceUpCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001438 try {
1439 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001440 Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1441 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001442 try {
1443 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001444 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001445 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
Zhihai Xu40874a02012-10-08 17:57:03 -07001446 }
1447 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001448 } finally {
1449 mCallbacks.finishBroadcast();
Zhihai Xu40874a02012-10-08 17:57:03 -07001450 }
1451 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001452
Zhihai Xu40874a02012-10-08 17:57:03 -07001453 /**
fredcbf072a72012-05-09 16:52:50 -07001454 * Inform BluetoothAdapter instances that Adapter service is down
1455 */
1456 private void sendBluetoothServiceDownCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001457 try {
1458 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001459 Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1460 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001461 try {
1462 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001463 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001464 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
fredcd6883532012-04-25 17:46:13 -07001465 }
1466 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001467 } finally {
1468 mCallbacks.finishBroadcast();
fredcd6883532012-04-25 17:46:13 -07001469 }
1470 }
Svet Ganov408abf72015-05-12 19:13:36 -07001471
fredc0f420372012-04-12 00:02:00 -07001472 public String getAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001473 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001474
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001475 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1476 Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001477 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001478 }
1479
Svet Ganov408abf72015-05-12 19:13:36 -07001480 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1481 != PackageManager.PERMISSION_GRANTED) {
1482 return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1483 }
1484
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001485 try {
1486 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001487 if (mBluetooth != null) {
1488 return mBluetooth.getAddress();
1489 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001490 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001491 Slog.e(TAG,
1492 "getAddress(): Unable to retrieve address remotely. Returning cached address",
1493 e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001494 } finally {
1495 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001496 }
Ajay Panickerbf796d82016-03-11 13:47:20 -08001497
Matthew Xiecdce0b92012-07-12 19:06:15 -07001498 // mAddress is accessed from outside.
1499 // It is alright without a lock. Here, bluetooth is off, no other thread is
1500 // changing mAddress
fredc0f420372012-04-12 00:02:00 -07001501 return mAddress;
1502 }
fredc649fe492012-04-19 01:07:18 -07001503
fredc0f420372012-04-12 00:02:00 -07001504 public String getName() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001505 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001506
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001507 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1508 Slog.w(TAG, "getName(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001509 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001510 }
1511
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001512 try {
1513 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001514 if (mBluetooth != null) {
1515 return mBluetooth.getName();
1516 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001517 } catch (RemoteException e) {
1518 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1519 } finally {
1520 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001521 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001522
Matthew Xiecdce0b92012-07-12 19:06:15 -07001523 // mName is accessed from outside.
1524 // It alright without a lock. Here, bluetooth is off, no other thread is
1525 // changing mName
fredc0f420372012-04-12 00:02:00 -07001526 return mName;
1527 }
1528
fredc0f420372012-04-12 00:02:00 -07001529 private class BluetoothServiceConnection implements ServiceConnection {
Marie Janssencb21ad72016-12-13 10:51:02 -08001530 public void onServiceConnected(ComponentName componentName, IBinder service) {
1531 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001532 if (DBG) {
1533 Slog.d(TAG, "BluetoothServiceConnection: " + name);
1534 }
fredc0f420372012-04-12 00:02:00 -07001535 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001536 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001537 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001538 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001539 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1540 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001541 Slog.e(TAG, "Unknown service connected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001542 return;
1543 }
fredc0f420372012-04-12 00:02:00 -07001544 msg.obj = service;
1545 mHandler.sendMessage(msg);
1546 }
1547
Marie Janssencb21ad72016-12-13 10:51:02 -08001548 public void onServiceDisconnected(ComponentName componentName) {
1549 // Called if we unexpectedly disconnect.
1550 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001551 if (DBG) {
1552 Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
1553 }
fredc0f420372012-04-12 00:02:00 -07001554 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001555 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001556 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001557 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001558 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1559 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001560 Slog.e(TAG, "Unknown service disconnected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001561 return;
1562 }
fredc0f420372012-04-12 00:02:00 -07001563 mHandler.sendMessage(msg);
1564 }
1565 }
1566
1567 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1568
Zhihai Xu40874a02012-10-08 17:57:03 -07001569 private class BluetoothHandler extends Handler {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001570 boolean mGetNameAddressOnly = false;
1571
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001572 BluetoothHandler(Looper looper) {
Zhihai Xu40874a02012-10-08 17:57:03 -07001573 super(looper);
1574 }
1575
fredc0f420372012-04-12 00:02:00 -07001576 @Override
1577 public void handleMessage(Message msg) {
fredc0f420372012-04-12 00:02:00 -07001578 switch (msg.what) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001579 case MESSAGE_GET_NAME_AND_ADDRESS:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001580 if (DBG) {
1581 Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1582 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001583 try {
1584 mBluetoothLock.writeLock().lock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001585 if ((mBluetooth == null) && (!mBinding)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001586 if (DBG) {
1587 Slog.d(TAG, "Binding to service to get name and address");
1588 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001589 mGetNameAddressOnly = true;
1590 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1591 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
1592 Intent i = new Intent(IBluetooth.class.getName());
1593 if (!doBind(i, mConnection,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001594 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1595 UserHandle.CURRENT)) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001596 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1597 } else {
1598 mBinding = true;
1599 }
1600 } else if (mBluetooth != null) {
1601 try {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001602 storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress());
Ajay Panicker4bb48302016-03-31 14:14:27 -07001603 } catch (RemoteException re) {
1604 Slog.e(TAG, "Unable to grab names", re);
1605 }
1606 if (mGetNameAddressOnly && !mEnable) {
1607 unbindAndFinish();
1608 }
1609 mGetNameAddressOnly = false;
1610 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001611 } finally {
1612 mBluetoothLock.writeLock().unlock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001613 }
1614 break;
1615
Matthew Xiecdce0b92012-07-12 19:06:15 -07001616 case MESSAGE_ENABLE:
fredcf2458862012-04-16 15:18:27 -07001617 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001618 Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
fredc649fe492012-04-19 01:07:18 -07001619 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001620 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1621 mEnable = true;
Calvin Ona0b91d72016-06-15 17:58:23 -07001622
1623 // Use service interface to get the exact state
1624 try {
1625 mBluetoothLock.readLock().lock();
1626 if (mBluetooth != null) {
1627 int state = mBluetooth.getState();
1628 if (state == BluetoothAdapter.STATE_BLE_ON) {
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001629 Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
Calvin Ona0b91d72016-06-15 17:58:23 -07001630 mBluetooth.onLeServiceUp();
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001631 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Calvin Ona0b91d72016-06-15 17:58:23 -07001632 break;
1633 }
1634 }
1635 } catch (RemoteException e) {
1636 Slog.e(TAG, "", e);
1637 } finally {
1638 mBluetoothLock.readLock().unlock();
1639 }
1640
1641 mQuietEnable = (msg.arg1 == 1);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001642 if (mBluetooth == null) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001643 handleEnable(mQuietEnable);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001644 } else {
1645 //
1646 // We need to wait until transitioned to STATE_OFF and
1647 // the previous Bluetooth process has exited. The
1648 // waiting period has three components:
1649 // (a) Wait until the local state is STATE_OFF. This
1650 // is accomplished by "waitForOnOff(false, true)".
1651 // (b) Wait until the STATE_OFF state is updated to
1652 // all components.
1653 // (c) Wait until the Bluetooth process exits, and
1654 // ActivityManager detects it.
1655 // The waiting for (b) and (c) is accomplished by
1656 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001657 // message. The delay time is backed off if Bluetooth
1658 // continuously failed to turn on itself.
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001659 //
1660 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001661 Message restartMsg =
1662 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001663 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001664 }
fredc649fe492012-04-19 01:07:18 -07001665 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001666
fredc0f420372012-04-12 00:02:00 -07001667 case MESSAGE_DISABLE:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001668 if (DBG) {
1669 Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
1670 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001671 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1672 if (mEnable && mBluetooth != null) {
1673 waitForOnOff(true, false);
1674 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001675 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001676 waitForOnOff(false, false);
1677 } else {
1678 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001679 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001680 }
fredc0f420372012-04-12 00:02:00 -07001681 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001682
Stanley Tng873b5702017-05-01 21:27:31 -07001683 case MESSAGE_RESTORE_USER_SETTING:
Jack He8caab152018-03-02 13:08:36 -08001684 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1685 if (DBG) {
1686 Slog.d(TAG, "Restore Bluetooth state to disabled");
Stanley Tng873b5702017-05-01 21:27:31 -07001687 }
Jack He8caab152018-03-02 13:08:36 -08001688 persistBluetoothSetting(BLUETOOTH_OFF);
1689 mEnableExternal = false;
1690 sendDisableMsg(
1691 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1692 mContext.getPackageName());
1693 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1694 if (DBG) {
1695 Slog.d(TAG, "Restore Bluetooth state to enabled");
1696 }
1697 mQuietEnableExternal = false;
1698 mEnableExternal = true;
1699 // waive WRITE_SECURE_SETTINGS permission check
1700 sendEnableMsg(false,
1701 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1702 mContext.getPackageName());
Stanley Tng873b5702017-05-01 21:27:31 -07001703 }
1704 break;
1705
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001706 case MESSAGE_REGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001707 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001708 mCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001709 break;
Marie Janssencb21ad72016-12-13 10:51:02 -08001710 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001711 case MESSAGE_UNREGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001712 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001713 mCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001714 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001715 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001716 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
1717 IBluetoothStateChangeCallback callback =
1718 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001719 mStateChangeCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001720 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001721 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001722 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
1723 IBluetoothStateChangeCallback callback =
1724 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001725 mStateChangeCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001726 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001727 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001728 case MESSAGE_ADD_PROXY_DELAYED: {
Jack He8caab152018-03-02 13:08:36 -08001729 ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
Benjamin Franze8b98922014-11-12 15:57:54 +00001730 if (psc == null) {
1731 break;
1732 }
1733 IBluetoothProfileServiceConnection proxy =
1734 (IBluetoothProfileServiceConnection) msg.obj;
1735 psc.addProxy(proxy);
1736 break;
1737 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001738 case MESSAGE_BIND_PROFILE_SERVICE: {
Benjamin Franze8b98922014-11-12 15:57:54 +00001739 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1740 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1741 if (psc == null) {
1742 break;
1743 }
1744 psc.bindService();
1745 break;
1746 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001747 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
1748 if (DBG) {
1749 Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
1750 }
fredc0f420372012-04-12 00:02:00 -07001751
1752 IBinder service = (IBinder) msg.obj;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001753 try {
1754 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001755 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001756 mBluetoothGatt =
1757 IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
Myles Watson304ebf22018-05-11 08:47:24 -07001758 continueFromBleOnState();
Matthew Xieddf7e472013-03-01 18:41:02 -08001759 break;
1760 } // else must be SERVICE_IBLUETOOTH
1761
1762 //Remove timeout
Zhihai Xuaf5971e2013-06-10 20:28:31 -07001763 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Matthew Xieddf7e472013-03-01 18:41:02 -08001764
fredc0f420372012-04-12 00:02:00 -07001765 mBinding = false;
Marie Janssen9db28eb2016-01-12 16:05:15 -08001766 mBluetoothBinder = service;
Jeff Sharkey0a17db12016-11-04 11:23:46 -06001767 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
fredc0f420372012-04-12 00:02:00 -07001768
Ajay Panicker4bb48302016-03-31 14:14:27 -07001769 if (!isNameAndAddressSet()) {
1770 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1771 mHandler.sendMessage(getMsg);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001772 if (mGetNameAddressOnly) {
1773 return;
1774 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001775 }
1776
Matthew Xiecdce0b92012-07-12 19:06:15 -07001777 //Register callback object
fredcbf072a72012-05-09 16:52:50 -07001778 try {
Matthew Xiecdce0b92012-07-12 19:06:15 -07001779 mBluetooth.registerCallback(mBluetoothCallback);
1780 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001781 Slog.e(TAG, "Unable to register BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001782 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001783 //Inform BluetoothAdapter instances that service is up
Zhihai Xu40874a02012-10-08 17:57:03 -07001784 sendBluetoothServiceUpCallback();
1785
Matthew Xiecdce0b92012-07-12 19:06:15 -07001786 //Do enable request
1787 try {
Zach Johnson1c86ed12019-11-26 21:46:08 -08001788 if (!mBluetooth.enable(mQuietEnable)) {
1789 Slog.e(TAG, "IBluetooth.enable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07001790 }
1791 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001792 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07001793 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001794 } finally {
1795 mBluetoothLock.writeLock().unlock();
Freda8c6df02012-07-11 10:25:23 -07001796 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001797
1798 if (!mEnable) {
1799 waitForOnOff(true, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001800 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001801 waitForOnOff(false, false);
1802 }
fredc649fe492012-04-19 01:07:18 -07001803 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001804 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001805 case MESSAGE_BLUETOOTH_STATE_CHANGE: {
fredcbf072a72012-05-09 16:52:50 -07001806 int prevState = msg.arg1;
1807 int newState = msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08001808 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001809 Slog.d(TAG,
1810 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
1811 prevState) + " > " + BluetoothAdapter.nameForState(
1812 newState));
Marie Janssencb21ad72016-12-13 10:51:02 -08001813 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001814 mState = newState;
1815 bluetoothStateChangeHandler(prevState, newState);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001816 // handle error state transition case from TURNING_ON to OFF
1817 // unbind and rebind bluetooth service and enable bluetooth
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001818 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
1819 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001820 recoverBluetoothServiceFromError(false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001821 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001822 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
1823 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001824 recoverBluetoothServiceFromError(true);
Nitin Arorad055adb2015-03-02 15:03:51 -08001825 }
Calvin Ona0b91d72016-06-15 17:58:23 -07001826 // If we tried to enable BT while BT was in the process of shutting down,
1827 // wait for the BT process to fully tear down and then force a restart
1828 // here. This is a bit of a hack (b/29363429).
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001829 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
1830 == BluetoothAdapter.STATE_OFF)) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001831 if (mEnable) {
1832 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1833 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001834 Message restartMsg =
1835 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001836 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Calvin Ona0b91d72016-06-15 17:58:23 -07001837 }
1838 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001839 if (newState == BluetoothAdapter.STATE_ON
1840 || newState == BluetoothAdapter.STATE_BLE_ON) {
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001841 // bluetooth is working, reset the counter
1842 if (mErrorRecoveryRetryCounter != 0) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001843 Slog.w(TAG, "bluetooth is recovered from error");
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001844 mErrorRecoveryRetryCounter = 0;
1845 }
1846 }
fredc649fe492012-04-19 01:07:18 -07001847 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001848 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001849 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
Marie Janssencb21ad72016-12-13 10:51:02 -08001850 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001851 try {
1852 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001853 if (msg.arg1 == SERVICE_IBLUETOOTH) {
1854 // if service is unbinded already, do nothing and return
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001855 if (mBluetooth == null) {
1856 break;
1857 }
Matthew Xieddf7e472013-03-01 18:41:02 -08001858 mBluetooth = null;
1859 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1860 mBluetoothGatt = null;
1861 break;
1862 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001863 Slog.e(TAG, "Unknown argument for service disconnect!");
Matthew Xieddf7e472013-03-01 18:41:02 -08001864 break;
1865 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001866 } finally {
1867 mBluetoothLock.writeLock().unlock();
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301868 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001869
Marie Janssene54b4222017-03-16 18:10:59 -07001870 // log the unexpected crash
1871 addCrashLog();
Jack He8caab152018-03-02 13:08:36 -08001872 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
1873 mContext.getPackageName(), false);
Zhihai Xu40874a02012-10-08 17:57:03 -07001874 if (mEnable) {
1875 mEnable = false;
1876 // Send a Bluetooth Restart message
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001877 Message restartMsg =
1878 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001879 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Zhihai Xu40874a02012-10-08 17:57:03 -07001880 }
1881
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001882 sendBluetoothServiceDownCallback();
Zhihai Xu40874a02012-10-08 17:57:03 -07001883
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001884 // Send BT state broadcast to update
1885 // the BT icon correctly
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001886 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
1887 == BluetoothAdapter.STATE_ON)) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001888 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001889 BluetoothAdapter.STATE_TURNING_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001890 mState = BluetoothAdapter.STATE_TURNING_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07001891 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001892 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1893 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001894 BluetoothAdapter.STATE_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001895 }
1896
1897 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1898 mState = BluetoothAdapter.STATE_OFF;
fredc649fe492012-04-19 01:07:18 -07001899 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001900 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001901 case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001902 mErrorRecoveryRetryCounter++;
1903 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
1904 + mErrorRecoveryRetryCounter);
1905 if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
1906 /* Enable without persisting the setting as
1907 it doesnt change when IBluetooth
1908 service restarts */
1909 mEnable = true;
1910 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
1911 mContext.getPackageName(), true);
1912 handleEnable(mQuietEnable);
1913 } else {
1914 Slog.e(TAG, "Reach maximum retry to restart Bluetooth!");
1915 }
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301916 break;
1917 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001918 case MESSAGE_TIMEOUT_BIND: {
1919 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1920 mBluetoothLock.writeLock().lock();
1921 mBinding = false;
1922 mBluetoothLock.writeLock().unlock();
1923 break;
1924 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001925 case MESSAGE_TIMEOUT_UNBIND: {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001926 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001927 mBluetoothLock.writeLock().lock();
1928 mUnbinding = false;
1929 mBluetoothLock.writeLock().unlock();
fredc649fe492012-04-19 01:07:18 -07001930 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001931 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001932
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001933 case MESSAGE_USER_SWITCHED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001934 if (DBG) {
1935 Slog.d(TAG, "MESSAGE_USER_SWITCHED");
1936 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001937 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001938
Zhihai Xu40874a02012-10-08 17:57:03 -07001939 /* disable and enable BT when detect a user switch */
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07001940 if (mBluetooth != null && isEnabled()) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001941 try {
1942 mBluetoothLock.readLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001943 if (mBluetooth != null) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001944 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xu40874a02012-10-08 17:57:03 -07001945 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001946 } catch (RemoteException re) {
1947 Slog.e(TAG, "Unable to unregister", re);
1948 } finally {
1949 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001950 }
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001951
1952 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1953 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
1954 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
1955 mState = BluetoothAdapter.STATE_OFF;
1956 }
1957 if (mState == BluetoothAdapter.STATE_OFF) {
1958 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
1959 mState = BluetoothAdapter.STATE_TURNING_ON;
1960 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001961
1962 waitForOnOff(true, false);
1963
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001964 if (mState == BluetoothAdapter.STATE_TURNING_ON) {
1965 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
1966 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001967
Benjamin Franze8b98922014-11-12 15:57:54 +00001968 unbindAllBluetoothProfileServices();
Zhihai Xu40874a02012-10-08 17:57:03 -07001969 // disable
Jack He8caab152018-03-02 13:08:36 -08001970 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
1971 mContext.getPackageName(), false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001972 handleDisable();
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001973 // Pbap service need receive STATE_TURNING_OFF intent to close
1974 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001975 BluetoothAdapter.STATE_TURNING_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001976
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001977 boolean didDisableTimeout = !waitForOnOff(false, true);
Zhihai Xu40874a02012-10-08 17:57:03 -07001978
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001979 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001980 BluetoothAdapter.STATE_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001981 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001982
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07001983 try {
1984 mBluetoothLock.writeLock().lock();
1985 if (mBluetooth != null) {
1986 mBluetooth = null;
1987 // Unbind
1988 mContext.unbindService(mConnection);
1989 }
1990 mBluetoothGatt = null;
1991 } finally {
1992 mBluetoothLock.writeLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001993 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001994
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001995 //
1996 // If disabling Bluetooth times out, wait for an
1997 // additional amount of time to ensure the process is
1998 // shut down completely before attempting to restart.
1999 //
2000 if (didDisableTimeout) {
2001 SystemClock.sleep(3000);
2002 } else {
2003 SystemClock.sleep(100);
2004 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002005
Zhihai Xu4e22ad32012-11-13 15:11:26 -08002006 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2007 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07002008 // enable
Jack He8caab152018-03-02 13:08:36 -08002009 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
2010 mContext.getPackageName(), true);
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07002011 // mEnable flag could have been reset on disableBLE. Reenable it.
2012 mEnable = true;
Zhihai Xu401202b2012-12-03 11:36:21 -08002013 handleEnable(mQuietEnable);
John Spurlock8a985d22014-02-25 09:40:05 -05002014 } else if (mBinding || mBluetooth != null) {
Zhihai Xu40874a02012-10-08 17:57:03 -07002015 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
2016 userMsg.arg2 = 1 + msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08002017 // if user is switched when service is binding retry after a delay
Zhihai Xu40874a02012-10-08 17:57:03 -07002018 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
2019 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002020 Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
Zhihai Xu40874a02012-10-08 17:57:03 -07002021 }
John Spurlock8a985d22014-02-25 09:40:05 -05002022 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002023 break;
2024 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002025 case MESSAGE_USER_UNLOCKED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002026 if (DBG) {
2027 Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
2028 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002029 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
2030
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002031 if (mEnable && !mBinding && (mBluetooth == null)) {
2032 // We should be connected, but we gave up for some
2033 // reason; maybe the Bluetooth service wasn't encryption
2034 // aware, so try binding again.
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002035 if (DBG) {
2036 Slog.d(TAG, "Enabled but not bound; retrying after unlock");
2037 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002038 handleEnable(mQuietEnable);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002039 }
2040 }
fredc0f420372012-04-12 00:02:00 -07002041 }
2042 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002043 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002044
Zhihai Xu401202b2012-12-03 11:36:21 -08002045 private void handleEnable(boolean quietMode) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002046 mQuietEnable = quietMode;
2047
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002048 try {
2049 mBluetoothLock.writeLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002050 if ((mBluetooth == null) && (!mBinding)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002051 //Start bind timeout and bind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002052 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
2053 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002054 Intent i = new Intent(IBluetooth.class.getName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002055 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
Dianne Hackbornce09f5a2014-10-10 15:03:13 -07002056 UserHandle.CURRENT)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002057 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Zhihai Xu40874a02012-10-08 17:57:03 -07002058 } else {
2059 mBinding = true;
Matthew Xiecdce0b92012-07-12 19:06:15 -07002060 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002061 } else if (mBluetooth != null) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002062 //Enable bluetooth
2063 try {
Zach Johnson1c86ed12019-11-26 21:46:08 -08002064 if (!mBluetooth.enable(mQuietEnable)) {
2065 Slog.e(TAG, "IBluetooth.enable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002066 }
2067 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002068 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002069 }
2070 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002071 } finally {
2072 mBluetoothLock.writeLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002073 }
2074 }
2075
Dianne Hackborn221ea892013-08-04 16:50:16 -07002076 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
2077 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
2078 intent.setComponent(comp);
2079 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07002080 Slog.e(TAG, "Fail to bind to: " + intent);
Dianne Hackborn221ea892013-08-04 16:50:16 -07002081 return false;
2082 }
2083 return true;
2084 }
2085
Zhihai Xu401202b2012-12-03 11:36:21 -08002086 private void handleDisable() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002087 try {
2088 mBluetoothLock.readLock().lock();
Andre Eisenbach305fdab2015-11-11 21:43:26 -08002089 if (mBluetooth != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002090 if (DBG) {
2091 Slog.d(TAG, "Sending off request.");
2092 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002093 if (!mBluetooth.disable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002094 Slog.e(TAG, "IBluetooth.disable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002095 }
2096 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002097 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002098 Slog.e(TAG, "Unable to call disable()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002099 } finally {
2100 mBluetoothLock.readLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002101 }
2102 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002103
2104 private boolean checkIfCallerIsForegroundUser() {
2105 int foregroundUser;
2106 int callingUser = UserHandle.getCallingUserId();
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002107 int callingUid = Binder.getCallingUid();
Zhihai Xu40874a02012-10-08 17:57:03 -07002108 long callingIdentity = Binder.clearCallingIdentity();
Benjamin Franze8b98922014-11-12 15:57:54 +00002109 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2110 UserInfo ui = um.getProfileParent(callingUser);
2111 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002112 int callingAppId = UserHandle.getAppId(callingUid);
Zhihai Xu40874a02012-10-08 17:57:03 -07002113 boolean valid = false;
2114 try {
2115 foregroundUser = ActivityManager.getCurrentUser();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002116 valid = (callingUser == foregroundUser) || parentUser == foregroundUser
2117 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid;
Marie Janssencb21ad72016-12-13 10:51:02 -08002118 if (DBG && !valid) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002119 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
2120 + callingUser + " parentUser=" + parentUser + " foregroundUser="
2121 + foregroundUser);
Zhihai Xu40874a02012-10-08 17:57:03 -07002122 }
2123 } finally {
2124 Binder.restoreCallingIdentity(callingIdentity);
2125 }
2126 return valid;
2127 }
2128
Nitin Arorad055adb2015-03-02 15:03:51 -08002129 private void sendBleStateChanged(int prevState, int newState) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002130 if (DBG) {
2131 Slog.d(TAG,
2132 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
2133 + BluetoothAdapter.nameForState(newState));
2134 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002135 // Send broadcast message to everyone else
2136 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
2137 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2138 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2139 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2140 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
2141 }
2142
Zhihai Xu40874a02012-10-08 17:57:03 -07002143 private void bluetoothStateChangeHandler(int prevState, int newState) {
Nitin Arorad055adb2015-03-02 15:03:51 -08002144 boolean isStandardBroadcast = true;
Marie Janssencb21ad72016-12-13 10:51:02 -08002145 if (prevState == newState) { // No change. Nothing to do.
2146 return;
2147 }
2148 // Notify all proxy objects first of adapter state change
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002149 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002150 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002151 && newState == BluetoothAdapter.STATE_BLE_ON);
Zhihai Xu40874a02012-10-08 17:57:03 -07002152
Marie Janssencb21ad72016-12-13 10:51:02 -08002153 if (newState == BluetoothAdapter.STATE_OFF) {
2154 // If Bluetooth is off, send service down event to proxy objects, and unbind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002155 if (DBG) {
2156 Slog.d(TAG, "Bluetooth is complete send Service Down");
2157 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002158 sendBluetoothServiceDownCallback();
2159 unbindAndFinish();
Nitin Arorad055adb2015-03-02 15:03:51 -08002160 sendBleStateChanged(prevState, newState);
Marie Janssencb21ad72016-12-13 10:51:02 -08002161 // Don't broadcast as it has already been broadcast before
Nitin Arorad055adb2015-03-02 15:03:51 -08002162 isStandardBroadcast = false;
2163
Marie Janssencb21ad72016-12-13 10:51:02 -08002164 } else if (!intermediate_off) {
2165 // connect to GattService
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002166 if (DBG) {
2167 Slog.d(TAG, "Bluetooth is in LE only mode");
2168 }
Myles Watson304ebf22018-05-11 08:47:24 -07002169 if (mBluetoothGatt != null || !mContext.getPackageManager()
2170 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
2171 continueFromBleOnState();
Marie Janssencb21ad72016-12-13 10:51:02 -08002172 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002173 if (DBG) {
2174 Slog.d(TAG, "Binding Bluetooth GATT service");
2175 }
Myles Watson304ebf22018-05-11 08:47:24 -07002176 Intent i = new Intent(IBluetoothGatt.class.getName());
2177 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
2178 UserHandle.CURRENT);
Nitin Arorad055adb2015-03-02 15:03:51 -08002179 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002180 sendBleStateChanged(prevState, newState);
2181 //Don't broadcase this as std intent
2182 isStandardBroadcast = false;
2183
2184 } else if (intermediate_off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002185 if (DBG) {
2186 Slog.d(TAG, "Intermediate off, back to LE only mode");
2187 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002188 // For LE only mode, broadcast as is
2189 sendBleStateChanged(prevState, newState);
2190 sendBluetoothStateCallback(false); // BT is OFF for general users
2191 // Broadcast as STATE_OFF
2192 newState = BluetoothAdapter.STATE_OFF;
2193 sendBrEdrDownCallback();
Nitin Arorad055adb2015-03-02 15:03:51 -08002194 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002195 } else if (newState == BluetoothAdapter.STATE_ON) {
2196 boolean isUp = (newState == BluetoothAdapter.STATE_ON);
2197 sendBluetoothStateCallback(isUp);
2198 sendBleStateChanged(prevState, newState);
2199
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002200 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
2201 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002202 sendBleStateChanged(prevState, newState);
2203 isStandardBroadcast = false;
2204
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002205 } else if (newState == BluetoothAdapter.STATE_TURNING_ON
2206 || newState == BluetoothAdapter.STATE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002207 sendBleStateChanged(prevState, newState);
2208 }
2209
2210 if (isStandardBroadcast) {
2211 if (prevState == BluetoothAdapter.STATE_BLE_ON) {
2212 // Show prevState of BLE_ON as OFF to standard users
2213 prevState = BluetoothAdapter.STATE_OFF;
2214 }
2215 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
2216 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2217 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2218 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2219 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
Zhihai Xu40874a02012-10-08 17:57:03 -07002220 }
2221 }
2222
2223 /**
2224 * if on is true, wait for state become ON
2225 * if off is true, wait for state become OFF
2226 * if both on and off are false, wait for state not ON
2227 */
2228 private boolean waitForOnOff(boolean on, boolean off) {
2229 int i = 0;
2230 while (i < 10) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002231 try {
2232 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002233 if (mBluetooth == null) {
2234 break;
2235 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002236 if (on) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002237 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
2238 return true;
2239 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002240 } else if (off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002241 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) {
2242 return true;
2243 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002244 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002245 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) {
2246 return true;
2247 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002248 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002249 } catch (RemoteException e) {
2250 Slog.e(TAG, "getState()", e);
2251 break;
2252 } finally {
2253 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002254 }
2255 if (on || off) {
2256 SystemClock.sleep(300);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002257 } else {
Zhihai Xu40874a02012-10-08 17:57:03 -07002258 SystemClock.sleep(50);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002259 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002260 i++;
2261 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002262 Slog.e(TAG, "waitForOnOff time out");
Zhihai Xu40874a02012-10-08 17:57:03 -07002263 return false;
2264 }
Zhihai Xu681ae7f2012-11-12 15:14:18 -08002265
Jack He8caab152018-03-02 13:08:36 -08002266 private void sendDisableMsg(int reason, String packageName) {
Zhihai Xu401202b2012-12-03 11:36:21 -08002267 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
Jack He8caab152018-03-02 13:08:36 -08002268 addActiveLog(reason, packageName, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08002269 }
2270
Jack He8caab152018-03-02 13:08:36 -08002271 private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002272 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
Jack He8caab152018-03-02 13:08:36 -08002273 addActiveLog(reason, packageName, true);
Marie Janssen12a35012017-06-26 07:21:03 -07002274 mLastEnabledTime = SystemClock.elapsedRealtime();
Marie Janssen59804562016-12-28 14:13:21 -08002275 }
2276
Jack He8caab152018-03-02 13:08:36 -08002277 private void addActiveLog(int reason, String packageName, boolean enable) {
Marie Janssen59804562016-12-28 14:13:21 -08002278 synchronized (mActiveLogs) {
Marie Janssene54b4222017-03-16 18:10:59 -07002279 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
Marie Janssen59804562016-12-28 14:13:21 -08002280 mActiveLogs.remove();
2281 }
Jack He8caab152018-03-02 13:08:36 -08002282 mActiveLogs.add(
2283 new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
Marie Janssen59804562016-12-28 14:13:21 -08002284 }
Tej Singhd8e7cc62018-03-22 18:30:31 +00002285
2286 int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
2287 StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2288 StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
2289 Binder.getCallingUid(), null, state, reason, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08002290 }
2291
Marie Janssene54b4222017-03-16 18:10:59 -07002292 private void addCrashLog() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002293 synchronized (mCrashTimestamps) {
2294 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
2295 mCrashTimestamps.removeFirst();
2296 }
2297 mCrashTimestamps.add(System.currentTimeMillis());
2298 mCrashes++;
2299 }
Marie Janssene54b4222017-03-16 18:10:59 -07002300 }
2301
Marie Janssen2977c3e2016-11-09 12:01:24 -08002302 private void recoverBluetoothServiceFromError(boolean clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002303 Slog.e(TAG, "recoverBluetoothServiceFromError");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002304 try {
2305 mBluetoothLock.readLock().lock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002306 if (mBluetooth != null) {
2307 //Unregister callback object
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002308 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002309 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002310 } catch (RemoteException re) {
2311 Slog.e(TAG, "Unable to unregister", re);
2312 } finally {
2313 mBluetoothLock.readLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002314 }
2315
2316 SystemClock.sleep(500);
2317
2318 // disable
Jack He8caab152018-03-02 13:08:36 -08002319 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
2320 mContext.getPackageName(), false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002321 handleDisable();
2322
2323 waitForOnOff(false, true);
2324
2325 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002326
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002327 try {
2328 mBluetoothLock.writeLock().lock();
2329 if (mBluetooth != null) {
2330 mBluetooth = null;
2331 // Unbind
2332 mContext.unbindService(mConnection);
2333 }
2334 mBluetoothGatt = null;
2335 } finally {
2336 mBluetoothLock.writeLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002337 }
2338
2339 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2340 mState = BluetoothAdapter.STATE_OFF;
2341
Marie Janssen2977c3e2016-11-09 12:01:24 -08002342 if (clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002343 clearBleApps();
Marie Janssen2977c3e2016-11-09 12:01:24 -08002344 }
2345
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002346 mEnable = false;
2347
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002348 // Send a Bluetooth Restart message to reenable bluetooth
2349 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
2350 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002351 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002352
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01002353 private boolean isBluetoothDisallowed() {
2354 long callingIdentity = Binder.clearCallingIdentity();
2355 try {
2356 return mContext.getSystemService(UserManager.class)
2357 .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2358 } finally {
2359 Binder.restoreCallingIdentity(callingIdentity);
2360 }
2361 }
2362
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002363 /**
2364 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002365 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2366 * state if Bluetooth is not disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002367 *
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002368 * @param userId user to disable bluetooth sharing for.
2369 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002370 */
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002371 private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002372 final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2373 "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002374 final int newState =
2375 bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2376 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002377 try {
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002378 final IPackageManager imp = AppGlobals.getPackageManager();
Myles Watson6291fae2017-06-29 03:12:02 -07002379 imp.setComponentEnabledSetting(oppLauncherComponent, newState,
2380 PackageManager.DONT_KILL_APP, userId);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002381 } catch (Exception e) {
2382 // The component was not found, do nothing.
2383 }
2384 }
2385
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002386 private int getServiceRestartMs() {
2387 return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
2388 }
2389
Mike Lockwood726d4de2014-10-28 14:06:28 -07002390 @Override
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002391 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002392 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
2393 return;
2394 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002395 String errorMsg = null;
Marie Janssen59804562016-12-28 14:13:21 -08002396
2397 boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
2398
2399 if (!protoOut) {
2400 writer.println("Bluetooth Status");
2401 writer.println(" enabled: " + isEnabled());
2402 writer.println(" state: " + BluetoothAdapter.nameForState(mState));
2403 writer.println(" address: " + mAddress);
2404 writer.println(" name: " + mName);
2405 if (mEnable) {
Marie Janssen12a35012017-06-26 07:21:03 -07002406 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002407 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
2408 (int) (onDuration / (1000 * 60 * 60)),
2409 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
2410 (int) (onDuration % 1000));
Andre Eisenbache66e1682017-04-10 13:49:13 -07002411 writer.println(" time since enabled: " + onDurationString);
Marie Janssen59804562016-12-28 14:13:21 -08002412 }
2413
Marie Janssena95924d2017-01-18 09:37:52 -08002414 if (mActiveLogs.size() == 0) {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002415 writer.println("\nBluetooth never enabled!");
Marie Janssena95924d2017-01-18 09:37:52 -08002416 } else {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002417 writer.println("\nEnable log:");
Marie Janssena95924d2017-01-18 09:37:52 -08002418 for (ActiveLog log : mActiveLogs) {
2419 writer.println(" " + log);
2420 }
Marie Janssen59804562016-12-28 14:13:21 -08002421 }
2422
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002423 writer.println(
2424 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2425 if (mCrashes == CRASH_LOG_MAX_SIZE) {
2426 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2427 }
Marie Janssene54b4222017-03-16 18:10:59 -07002428 for (Long time : mCrashTimestamps) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002429 writer.println(" " + timeToLog(time));
Marie Janssene54b4222017-03-16 18:10:59 -07002430 }
2431
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002432 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
2433 + "registered");
Marie Janssen59804562016-12-28 14:13:21 -08002434 for (ClientDeathRecipient app : mBleApps.values()) {
Marie Janssena95924d2017-01-18 09:37:52 -08002435 writer.println(" " + app.getPackageName());
Marie Janssen59804562016-12-28 14:13:21 -08002436 }
2437
Marie Janssena95924d2017-01-18 09:37:52 -08002438 writer.println("");
Marie Janssen59804562016-12-28 14:13:21 -08002439 writer.flush();
Marie Janssenf5ec5382017-01-03 11:37:38 -08002440 if (args.length == 0) {
Marie Janssena95924d2017-01-18 09:37:52 -08002441 // Add arg to produce output
2442 args = new String[1];
2443 args[0] = "--print";
Marie Janssenf5ec5382017-01-03 11:37:38 -08002444 }
Marie Janssen59804562016-12-28 14:13:21 -08002445 }
2446
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002447 if (mBluetoothBinder == null) {
2448 errorMsg = "Bluetooth Service not connected";
2449 } else {
2450 try {
2451 mBluetoothBinder.dump(fd, args);
2452 } catch (RemoteException re) {
Marie Janssen59804562016-12-28 14:13:21 -08002453 errorMsg = "RemoteException while dumping Bluetooth Service";
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002454 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002455 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002456 if (errorMsg != null) {
2457 // Silently return if we are extracting metrics in Protobuf format
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002458 if (protoOut) {
2459 return;
2460 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002461 writer.println(errorMsg);
2462 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002463 }
Jack He8caab152018-03-02 13:08:36 -08002464
2465 private static String getEnableDisableReasonString(int reason) {
2466 switch (reason) {
2467 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
2468 return "APPLICATION_REQUEST";
2469 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
2470 return "AIRPLANE_MODE";
2471 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
2472 return "DISALLOWED";
2473 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
2474 return "RESTARTED";
2475 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
2476 return "START_ERROR";
2477 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
2478 return "SYSTEM_BOOT";
2479 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
2480 return "CRASH";
2481 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
2482 return "USER_SWITCH";
2483 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
2484 return "RESTORE_USER_SETTING";
2485 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
2486 default: return "UNKNOWN[" + reason + "]";
2487 }
2488 }
fredc0f420372012-04-12 00:02:00 -07002489}