blob: 311a494ee570f3df2f8448686f5a1ca40df361bb [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;
Mike Lockwood726d4de2014-10-28 14:06:28 -070072
Arthur Hsuf3f95a92018-01-11 16:46:22 -080073import com.android.internal.R;
Ugo Yufd8efab2019-10-16 20:27:23 +080074import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060075import com.android.internal.util.DumpUtils;
Muhammad Qureshie2b24322020-01-28 10:54:17 -080076import com.android.internal.util.FrameworkStatsLog;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010077import com.android.server.pm.UserRestrictionsUtils;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +010078
Mike Lockwood726d4de2014-10-28 14:06:28 -070079import java.io.FileDescriptor;
80import java.io.PrintWriter;
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +010081import java.util.ArrayList;
Muhammad Qureshie2b24322020-01-28 10:54:17 -080082import java.util.HashMap;
Marie Janssen59804562016-12-28 14:13:21 -080083import java.util.LinkedList;
Myles Watsonb5cd11a2017-11-27 16:42:11 -080084import java.util.Locale;
Benjamin Franze8b98922014-11-12 15:57:54 +000085import java.util.Map;
Chienyuan177156b2018-12-18 10:40:25 +080086import java.util.NoSuchElementException;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010087import java.util.concurrent.ConcurrentHashMap;
88import java.util.concurrent.locks.ReentrantReadWriteLock;
Miao Chou658bf2f2015-06-26 17:14:35 -070089
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.
Ugo Yufd8efab2019-10-16 20:27:23 +0800146 @VisibleForTesting
147 static final int BLUETOOTH_ON_AIRPLANE = 2;
fredc0f420372012-04-12 00:02:00 -0700148
Matthew Xieddf7e472013-03-01 18:41:02 -0800149 private static final int SERVICE_IBLUETOOTH = 1;
150 private static final int SERVICE_IBLUETOOTHGATT = 2;
151
fredc0f420372012-04-12 00:02:00 -0700152 private final Context mContext;
Matthew Xiecdce0b92012-07-12 19:06:15 -0700153
154 // Locks are not provided for mName and mAddress.
155 // They are accessed in handler or broadcast receiver, same thread context.
fredc0f420372012-04-12 00:02:00 -0700156 private String mAddress;
157 private String mName;
Matthew Xie6fde3092012-07-11 17:10:07 -0700158 private final ContentResolver mContentResolver;
159 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
160 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800161 private IBinder mBluetoothBinder;
fredc649fe492012-04-19 01:07:18 -0700162 private IBluetooth mBluetooth;
Matthew Xieddf7e472013-03-01 18:41:02 -0800163 private IBluetoothGatt mBluetoothGatt;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800164 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
fredc649fe492012-04-19 01:07:18 -0700165 private boolean mBinding;
166 private boolean mUnbinding;
Marie Janssen59804562016-12-28 14:13:21 -0800167
Ugo Yufd8efab2019-10-16 20:27:23 +0800168 private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
169
Zhihai Xu401202b2012-12-03 11:36:21 -0800170 // used inside handler thread
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700171 private boolean mQuietEnable = false;
Marie Janssen59804562016-12-28 14:13:21 -0800172 private boolean mEnable;
173
Jack He8caab152018-03-02 13:08:36 -0800174 private static CharSequence timeToLog(long timestamp) {
Marie Janssene54b4222017-03-16 18:10:59 -0700175 return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
176 }
177
Marie Janssen59804562016-12-28 14:13:21 -0800178 /**
179 * Used for tracking apps that enabled / disabled Bluetooth.
180 */
181 private class ActiveLog {
Jack He8caab152018-03-02 13:08:36 -0800182 private int mReason;
Marie Janssen59804562016-12-28 14:13:21 -0800183 private String mPackageName;
184 private boolean mEnable;
185 private long mTimestamp;
186
Jack He8caab152018-03-02 13:08:36 -0800187 ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
188 mReason = reason;
Marie Janssen59804562016-12-28 14:13:21 -0800189 mPackageName = packageName;
190 mEnable = enable;
191 mTimestamp = timestamp;
192 }
193
Marie Janssen59804562016-12-28 14:13:21 -0800194 public String toString() {
Jack He8caab152018-03-02 13:08:36 -0800195 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
196 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
Marie Janssen59804562016-12-28 14:13:21 -0800197 }
198
199 }
200
Jack He8caab152018-03-02 13:08:36 -0800201 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
202 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
Marie Janssene54b4222017-03-16 18:10:59 -0700203 private int mCrashes;
Marie Janssen12a35012017-06-26 07:21:03 -0700204 private long mLastEnabledTime;
Marie Janssen59804562016-12-28 14:13:21 -0800205
206 // configuration from external IBinder call which is used to
Zhihai Xu401202b2012-12-03 11:36:21 -0800207 // synchronize with broadcast receiver.
208 private boolean mQuietEnableExternal;
Zhihai Xu401202b2012-12-03 11:36:21 -0800209 private boolean mEnableExternal;
Marie Janssen59804562016-12-28 14:13:21 -0800210
211 // Map of apps registered to keep BLE scanning on.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800212 private Map<IBinder, ClientDeathRecipient> mBleApps =
213 new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
Marie Janssen59804562016-12-28 14:13:21 -0800214
Zhihai Xu40874a02012-10-08 17:57:03 -0700215 private int mState;
Zhihai Xu40874a02012-10-08 17:57:03 -0700216 private final BluetoothHandler mHandler;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800217 private int mErrorRecoveryRetryCounter;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200218 private final int mSystemUiUid;
fredc0f420372012-04-12 00:02:00 -0700219
Stanley Tng61dbd812019-01-13 16:04:31 -0800220 private boolean mIsHearingAidProfileSupported;
221
Jack Hea80cead2019-04-23 20:00:18 -0700222 private AppOpsManager mAppOps;
223
Benjamin Franze8b98922014-11-12 15:57:54 +0000224 // Save a ProfileServiceConnections object for each of the bound
225 // bluetooth profile services
Jack He8caab152018-03-02 13:08:36 -0800226 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
Benjamin Franze8b98922014-11-12 15:57:54 +0000227
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700228 private final boolean mWirelessConsentRequired;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700229
Marie Janssen59804562016-12-28 14:13:21 -0800230 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
fredcbf072a72012-05-09 16:52:50 -0700231 @Override
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800232 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
233 Message msg =
234 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
fredcbf072a72012-05-09 16:52:50 -0700235 mHandler.sendMessage(msg);
236 }
237 };
238
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100239 private final UserRestrictionsListener mUserRestrictionsListener =
240 new UserRestrictionsListener() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800241 @Override
242 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
243 Bundle prevRestrictions) {
Myles Watson6291fae2017-06-29 03:12:02 -0700244
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800245 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
246 UserManager.DISALLOW_BLUETOOTH_SHARING)) {
247 updateOppLauncherComponentState(userId,
248 newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
249 }
Pavel Grafov4f4f6f82017-03-28 13:44:04 +0100250
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800251 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
Winson Chungf2b41772019-11-06 15:00:48 -0800252 if (userId == USER_SYSTEM
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800253 && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
254 newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
Winson Chungf2b41772019-11-06 15:00:48 -0800255 if (userId == USER_SYSTEM && newRestrictions.getBoolean(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800256 UserManager.DISALLOW_BLUETOOTH)) {
257 updateOppLauncherComponentState(userId, true); // Sharing disallowed
Jack He8caab152018-03-02 13:08:36 -0800258 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
259 mContext.getPackageName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800260 } else {
261 updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
262 UserManager.DISALLOW_BLUETOOTH_SHARING));
263 }
264 }
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100265 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800266 };
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100267
Ugo Yufd8efab2019-10-16 20:27:23 +0800268 public void onAirplaneModeChanged() {
269 synchronized (this) {
270 if (isBluetoothPersistedStateOn()) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800271 if (isAirplaneModeOn()) {
Ugo Yufd8efab2019-10-16 20:27:23 +0800272 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
273 } else {
274 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Ajay Panicker467bc042017-02-22 12:23:15 -0800275 }
276 }
Ugo Yufd8efab2019-10-16 20:27:23 +0800277
278 int st = BluetoothAdapter.STATE_OFF;
279 try {
280 mBluetoothLock.readLock().lock();
281 if (mBluetooth != null) {
282 st = mBluetooth.getState();
283 }
284 } catch (RemoteException e) {
285 Slog.e(TAG, "Unable to call getState", e);
286 return;
287 } finally {
288 mBluetoothLock.readLock().unlock();
289 }
290
291 Slog.d(TAG,
292 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState(
293 st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
294
295 if (isAirplaneModeOn()) {
296 // Clear registered LE apps to force shut-off
297 clearBleApps();
298
299 // If state is BLE_ON make sure we trigger disableBLE
300 if (st == BluetoothAdapter.STATE_BLE_ON) {
301 try {
302 mBluetoothLock.readLock().lock();
303 if (mBluetooth != null) {
304 addActiveLog(
305 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
306 mContext.getPackageName(), false);
307 mBluetooth.onBrEdrDown();
308 mEnable = false;
309 mEnableExternal = false;
310 }
311 } catch (RemoteException e) {
312 Slog.e(TAG, "Unable to call onBrEdrDown", e);
313 } finally {
314 mBluetoothLock.readLock().unlock();
315 }
316 } else if (st == BluetoothAdapter.STATE_ON) {
317 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
318 mContext.getPackageName());
319 }
320 } else if (mEnableExternal) {
321 sendEnableMsg(mQuietEnableExternal,
322 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
323 mContext.getPackageName());
324 }
Ajay Panicker467bc042017-02-22 12:23:15 -0800325 }
Ugo Yufd8efab2019-10-16 20:27:23 +0800326 }
Ajay Panicker467bc042017-02-22 12:23:15 -0800327
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)) {
Ugo Yufd8efab2019-10-16 20:27:23 +0800438 mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
439 this, IoThread.get().getLooper(), context);
Ajay Panicker467bc042017-02-22 12:23:15 -0800440 }
441
Marie Janssen59804562016-12-28 14:13:21 -0800442 int systemUiUid = -1;
Winson Chungf2b41772019-11-06 15:00:48 -0800443 // Check if device is configured with no home screen, which implies no SystemUI.
444 boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
445 if (!noHome) {
446 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
447 systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
448 MATCH_SYSTEM_ONLY, USER_SYSTEM);
449 }
450 if (systemUiUid >= 0) {
Arthur Hsuf3f95a92018-01-11 16:46:22 -0800451 Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
Winson Chungf2b41772019-11-06 15:00:48 -0800452 } else {
Joe LaPennaacddf2b2015-09-04 12:52:42 -0700453 // Some platforms, such as wearables do not have a system ui.
Winson Chungf2b41772019-11-06 15:00:48 -0800454 Slog.w(TAG, "Unable to resolve SystemUI's UID.");
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200455 }
Marie Janssen59804562016-12-28 14:13:21 -0800456 mSystemUiUid = systemUiUid;
fredc0f420372012-04-12 00:02:00 -0700457 }
458
fredc649fe492012-04-19 01:07:18 -0700459 /**
460 * Returns true if airplane mode is currently on
461 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800462 private boolean isAirplaneModeOn() {
Christopher Tatec09cdce2012-09-10 16:50:14 -0700463 return Settings.Global.getInt(mContext.getContentResolver(),
464 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
fredc649fe492012-04-19 01:07:18 -0700465 }
466
Arthur Hsu2433baf2018-01-11 11:05:11 -0800467 private boolean supportBluetoothPersistedState() {
468 return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
469 }
470
fredc649fe492012-04-19 01:07:18 -0700471 /**
472 * Returns true if the Bluetooth saved state is "on"
473 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800474 private boolean isBluetoothPersistedStateOn() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800475 if (!supportBluetoothPersistedState()) {
476 return false;
477 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800478 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
479 if (DBG) {
480 Slog.d(TAG, "Bluetooth persisted state: " + state);
481 }
Marie Janssen9fa24912016-10-18 10:04:24 -0700482 return state != BLUETOOTH_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800483 }
484
Ugo Yufd8efab2019-10-16 20:27:23 +0800485 private boolean isBluetoothPersistedStateOnAirplane() {
486 if (!supportBluetoothPersistedState()) {
487 return false;
488 }
489 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
490 if (DBG) {
491 Slog.d(TAG, "Bluetooth persisted state: " + state);
492 }
493 return state == BLUETOOTH_ON_AIRPLANE;
494 }
495
Zhihai Xu401202b2012-12-03 11:36:21 -0800496 /**
497 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
498 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800499 private boolean isBluetoothPersistedStateOnBluetooth() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800500 if (!supportBluetoothPersistedState()) {
501 return false;
502 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800503 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
504 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
fredc649fe492012-04-19 01:07:18 -0700505 }
506
507 /**
508 * Save the Bluetooth on/off state
fredc649fe492012-04-19 01:07:18 -0700509 */
Zhihai Xu401202b2012-12-03 11:36:21 -0800510 private void persistBluetoothSetting(int value) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800511 if (DBG) {
512 Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
513 }
Marie Janssenfa630682016-12-15 13:51:30 -0800514 // waive WRITE_SECURE_SETTINGS permission check
515 long callingIdentity = Binder.clearCallingIdentity();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800516 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value);
Marie Janssenfa630682016-12-15 13:51:30 -0800517 Binder.restoreCallingIdentity(callingIdentity);
fredc649fe492012-04-19 01:07:18 -0700518 }
519
520 /**
521 * Returns true if the Bluetooth Adapter's name and address is
522 * locally cached
523 * @return
524 */
fredc0f420372012-04-12 00:02:00 -0700525 private boolean isNameAndAddressSet() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800526 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
fredc0f420372012-04-12 00:02:00 -0700527 }
528
fredc649fe492012-04-19 01:07:18 -0700529 /**
530 * Retrieve the Bluetooth Adapter's name and address and save it in
531 * in the local cache
532 */
fredc0f420372012-04-12 00:02:00 -0700533 private void loadStoredNameAndAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800534 if (DBG) {
535 Slog.d(TAG, "Loading stored name and address");
536 }
537 if (mContext.getResources()
538 .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
539 && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0)
540 == 0) {
Zhihai Xud31c3222012-10-31 16:08:57 -0700541 // if the valid flag is not set, don't load the address and name
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800542 if (DBG) {
543 Slog.d(TAG, "invalid bluetooth name and address stored");
544 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700545 return;
546 }
fredc0f420372012-04-12 00:02:00 -0700547 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
548 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800549 if (DBG) {
550 Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
551 }
fredc0f420372012-04-12 00:02:00 -0700552 }
553
fredc649fe492012-04-19 01:07:18 -0700554 /**
555 * Save the Bluetooth name and address in the persistent store.
556 * Only non-null values will be saved.
557 * @param name
558 * @param address
559 */
fredc0f420372012-04-12 00:02:00 -0700560 private void storeNameAndAddress(String name, String address) {
561 if (name != null) {
562 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
fredc0f420372012-04-12 00:02:00 -0700563 mName = name;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800564 if (DBG) {
565 Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver,
566 SECURE_SETTINGS_BLUETOOTH_NAME));
567 }
fredc0f420372012-04-12 00:02:00 -0700568 }
569
570 if (address != null) {
571 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800572 mAddress = address;
573 if (DBG) {
574 Slog.d(TAG,
575 "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver,
576 SECURE_SETTINGS_BLUETOOTH_ADDRESS));
577 }
fredc0f420372012-04-12 00:02:00 -0700578 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700579
580 if ((name != null) && (address != null)) {
581 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
582 }
fredc0f420372012-04-12 00:02:00 -0700583 }
584
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800585 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700586 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700587 Slog.w(TAG, "Callback is null in registerAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700588 return null;
589 }
fredc0f420372012-04-12 00:02:00 -0700590 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
591 msg.obj = callback;
592 mHandler.sendMessage(msg);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700593
594 return mBluetooth;
fredc0f420372012-04-12 00:02:00 -0700595 }
596
597 public void unregisterAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700598 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700599 Slog.w(TAG, "Callback is null in unregisterAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700600 return;
601 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800602 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
fredc0f420372012-04-12 00:02:00 -0700603 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
604 msg.obj = callback;
605 mHandler.sendMessage(msg);
606 }
607
608 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800609 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800610 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800611 Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
612 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800613 }
fredc0f420372012-04-12 00:02:00 -0700614 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
615 msg.obj = callback;
616 mHandler.sendMessage(msg);
617 }
618
619 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800620 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800621 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800622 Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
623 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800624 }
fredc0f420372012-04-12 00:02:00 -0700625 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
626 msg.obj = callback;
627 mHandler.sendMessage(msg);
628 }
629
630 public boolean isEnabled() {
Zach Johnson76236d72019-11-26 21:30:07 -0800631 return getState() == BluetoothAdapter.STATE_ON;
fredc0f420372012-04-12 00:02:00 -0700632 }
633
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700634 public int getState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800635 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
Marie Janssencb21ad72016-12-13 10:51:02 -0800636 Slog.w(TAG, "getState(): report OFF for non-active and non system user");
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700637 return BluetoothAdapter.STATE_OFF;
638 }
639
640 try {
641 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800642 if (mBluetooth != null) {
643 return mBluetooth.getState();
644 }
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700645 } catch (RemoteException e) {
646 Slog.e(TAG, "getState()", e);
647 } finally {
648 mBluetoothLock.readLock().unlock();
649 }
650 return BluetoothAdapter.STATE_OFF;
651 }
652
Nitin Arorad055adb2015-03-02 15:03:51 -0800653 class ClientDeathRecipient implements IBinder.DeathRecipient {
Marie Janssen59804562016-12-28 14:13:21 -0800654 private String mPackageName;
655
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800656 ClientDeathRecipient(String packageName) {
Marie Janssen59804562016-12-28 14:13:21 -0800657 mPackageName = packageName;
658 }
659
Nitin Arorad055adb2015-03-02 15:03:51 -0800660 public void binderDied() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800661 if (DBG) {
662 Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
Marie Janssen2977c3e2016-11-09 12:01:24 -0800663 }
Stanley Tng2c5fd282018-03-19 13:06:45 -0700664
665 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
666 IBinder token = entry.getKey();
667 ClientDeathRecipient deathRec = entry.getValue();
668 if (deathRec.equals(this)) {
Stanley Tng600109c2018-03-20 16:54:27 -0700669 updateBleAppCount(token, false, mPackageName);
Stanley Tng2c5fd282018-03-19 13:06:45 -0700670 break;
671 }
672 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800673 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800674
Marie Janssen59804562016-12-28 14:13:21 -0800675 public String getPackageName() {
676 return mPackageName;
677 }
678 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800679
Wei Wang67d84162015-04-26 17:04:29 -0700680 @Override
681 public boolean isBleScanAlwaysAvailable() {
Marie Janssena80d7452016-10-25 10:47:51 -0700682 if (isAirplaneModeOn() && !mEnable) {
683 return false;
684 }
Wei Wang67d84162015-04-26 17:04:29 -0700685 try {
Jack He8caab152018-03-02 13:08:36 -0800686 return Settings.Global.getInt(mContentResolver,
687 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
Wei Wang67d84162015-04-26 17:04:29 -0700688 } catch (SettingNotFoundException e) {
689 }
690 return false;
691 }
692
Stanley Tng61dbd812019-01-13 16:04:31 -0800693 @Override
694 public boolean isHearingAidProfileSupported() {
695 return mIsHearingAidProfileSupported;
696 }
697
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +0100698 @Override
699 /** @hide */
700 public java.util.List<String> getSystemConfigEnabledProfilesForPackage(String packageName) {
701 if (Binder.getCallingUid() != Process.BLUETOOTH_UID) {
702 Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth");
703 return null;
704 }
705
706 SystemConfig systemConfig = SystemConfig.getInstance();
707 if (systemConfig == null) {
708 return null;
709 }
710
711 android.util.ArrayMap<String, Boolean> componentEnabledStates =
712 systemConfig.getComponentsEnabledStates(packageName);
713 if (componentEnabledStates == null) {
714 return null;
715 }
716
717 ArrayList enabledProfiles = new ArrayList<String>();
718 for (Map.Entry<String, Boolean> entry : componentEnabledStates.entrySet()) {
719 if (entry.getValue()) {
720 enabledProfiles.add(entry.getKey());
721 }
722 }
723
724 return enabledProfiles;
725 }
726
Wei Wange4a744b2015-06-11 17:50:29 -0700727 // Monitor change of BLE scan only mode settings.
728 private void registerForBleScanModeChange() {
729 ContentObserver contentObserver = new ContentObserver(null) {
730 @Override
731 public void onChange(boolean selfChange) {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800732 if (isBleScanAlwaysAvailable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800733 // Nothing to do
734 return;
Marie Janssen2977c3e2016-11-09 12:01:24 -0800735 }
736 // BLE scan is not available.
737 disableBleScanMode();
738 clearBleApps();
739 try {
740 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800741 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700742 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
743 mContext.getPackageName(), false);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800744 mBluetooth.onBrEdrDown();
745 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800746 } catch (RemoteException e) {
747 Slog.e(TAG, "error when disabling bluetooth", e);
748 } finally {
749 mBluetoothLock.readLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700750 }
751 }
752 };
753
754 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800755 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
756 contentObserver);
Wei Wange4a744b2015-06-11 17:50:29 -0700757 }
758
759 // Disable ble scan only mode.
760 private void disableBleScanMode() {
761 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700762 mBluetoothLock.writeLock().lock();
Wei Wange4a744b2015-06-11 17:50:29 -0700763 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800764 if (DBG) {
765 Slog.d(TAG, "Reseting the mEnable flag for clean disable");
766 }
Wei Wange4a744b2015-06-11 17:50:29 -0700767 mEnable = false;
768 }
769 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700770 Slog.e(TAG, "getState()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700771 } finally {
772 mBluetoothLock.writeLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700773 }
774 }
775
Marie Janssen59804562016-12-28 14:13:21 -0800776 public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
Jack Hea80cead2019-04-23 20:00:18 -0700777 // Check if packageName belongs to callingUid
778 final int callingUid = Binder.getCallingUid();
779 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
780 if (!isCallerSystem) {
781 checkPackage(callingUid, packageName);
782 }
Marie Janssen59804562016-12-28 14:13:21 -0800783 ClientDeathRecipient r = mBleApps.get(token);
784 if (r == null && enable) {
785 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
786 try {
787 token.linkToDeath(deathRec, 0);
788 } catch (RemoteException ex) {
789 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
Nitin Arorad055adb2015-03-02 15:03:51 -0800790 }
Marie Janssen59804562016-12-28 14:13:21 -0800791 mBleApps.put(token, deathRec);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800792 if (DBG) {
793 Slog.d(TAG, "Registered for death of " + packageName);
794 }
Marie Janssen59804562016-12-28 14:13:21 -0800795 } else if (!enable && r != null) {
796 // Unregister death recipient as the app goes away.
797 token.unlinkToDeath(r, 0);
798 mBleApps.remove(token);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800799 if (DBG) {
800 Slog.d(TAG, "Unregistered for death of " + packageName);
801 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800802 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800803 int appCount = mBleApps.size();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800804 if (DBG) {
805 Slog.d(TAG, appCount + " registered Ble Apps");
806 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800807 if (appCount == 0 && mEnable) {
Wei Wange4a744b2015-06-11 17:50:29 -0700808 disableBleScanMode();
Nitin Arorad055adb2015-03-02 15:03:51 -0800809 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800810 if (appCount == 0 && !mEnableExternal) {
811 sendBrEdrDownCallback();
812 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800813 return appCount;
Nitin Arorad055adb2015-03-02 15:03:51 -0800814 }
815
Wei Wange4a744b2015-06-11 17:50:29 -0700816 // Clear all apps using BLE scan only mode.
817 private void clearBleApps() {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800818 mBleApps.clear();
Wei Wange4a744b2015-06-11 17:50:29 -0700819 }
820
Marie Janssen59804562016-12-28 14:13:21 -0800821 /** @hide */
Nitin Arorad055adb2015-03-02 15:03:51 -0800822 public boolean isBleAppPresent() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800823 if (DBG) {
824 Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
825 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800826 return mBleApps.size() > 0;
Nitin Arorad055adb2015-03-02 15:03:51 -0800827 }
828
829 /**
Myles Watson304ebf22018-05-11 08:47:24 -0700830 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
Nitin Arorad055adb2015-03-02 15:03:51 -0800831 */
Myles Watson304ebf22018-05-11 08:47:24 -0700832 private void continueFromBleOnState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800833 if (DBG) {
Myles Watson304ebf22018-05-11 08:47:24 -0700834 Slog.d(TAG, "continueFromBleOnState()");
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800835 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700836 try {
837 mBluetoothLock.readLock().lock();
Marie Janssenfa630682016-12-15 13:51:30 -0800838 if (mBluetooth == null) {
Myles Watson304ebf22018-05-11 08:47:24 -0700839 Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
Marie Janssenfa630682016-12-15 13:51:30 -0800840 return;
841 }
842 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
843 // This triggers transition to STATE_ON
Nitin Arorad055adb2015-03-02 15:03:51 -0800844 mBluetooth.onLeServiceUp();
Nitin Arorad055adb2015-03-02 15:03:51 -0800845 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Nitin Arorad055adb2015-03-02 15:03:51 -0800846 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700847 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800848 Slog.e(TAG, "Unable to call onServiceUp", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700849 } finally {
850 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800851 }
852 }
853
854 /**
855 * Inform BluetoothAdapter instances that BREDR part is down
856 * and turn off all service and stack if no LE app needs it
857 */
858 private void sendBrEdrDownCallback() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800859 if (DBG) {
860 Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
861 }
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700862
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700863 if (mBluetooth == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700864 Slog.w(TAG, "Bluetooth handle is null");
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700865 return;
866 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800867
Martin Brabhamc2b06222017-02-27 16:55:07 -0800868 if (isBleAppPresent()) {
869 // Need to stay at BLE ON. Disconnect all Gatt connections
870 try {
871 mBluetoothGatt.unregAll();
872 } catch (RemoteException e) {
873 Slog.e(TAG, "Unable to disconnect all apps.", e);
874 }
875 } else {
Nitin Arorad055adb2015-03-02 15:03:51 -0800876 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700877 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800878 if (mBluetooth != null) {
879 mBluetooth.onBrEdrDown();
880 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700881 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700882 Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700883 } finally {
884 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800885 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800886 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800887
Nitin Arorad055adb2015-03-02 15:03:51 -0800888 }
889
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800890 public boolean enableNoAutoConnect(String packageName) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100891 if (isBluetoothDisallowed()) {
892 if (DBG) {
893 Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
894 }
895 return false;
896 }
897
Jack Hea80cead2019-04-23 20:00:18 -0700898 // Check if packageName belongs to callingUid
899 final int callingUid = Binder.getCallingUid();
900 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
901 if (!isCallerSystem) {
902 checkPackage(callingUid, packageName);
903 }
904
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700905 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800906 "Need BLUETOOTH ADMIN permission");
Zhihai Xu40874a02012-10-08 17:57:03 -0700907
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700908 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800909 Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = "
910 + mBinding);
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700911 }
Jack Hea80cead2019-04-23 20:00:18 -0700912 int callingAppId = UserHandle.getAppId(callingUid);
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800913
914 if (callingAppId != Process.NFC_UID) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700915 throw new SecurityException("no permission to enable Bluetooth quietly");
916 }
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800917
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800918 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800919 mQuietEnableExternal = true;
920 mEnableExternal = true;
Jack He8caab152018-03-02 13:08:36 -0800921 sendEnableMsg(true,
922 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800923 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700924 return true;
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700925 }
Ajay Panicker4bb48302016-03-31 14:14:27 -0700926
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700927 public boolean enable(String packageName) throws RemoteException {
928 final int callingUid = Binder.getCallingUid();
929 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
930
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100931 if (isBluetoothDisallowed()) {
932 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800933 Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100934 }
935 return false;
936 }
937
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700938 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700939 // Check if packageName belongs to callingUid
940 checkPackage(callingUid, packageName);
941
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700942 if (!checkIfCallerIsForegroundUser()) {
943 Slog.w(TAG, "enable(): not allowed for non-active and non system user");
944 return false;
945 }
946
947 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
948 "Need BLUETOOTH ADMIN permission");
949
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700950 if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800951 callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700952 return false;
953 }
fredcf2458862012-04-16 15:18:27 -0700954 }
955
Zhihai Xu401202b2012-12-03 11:36:21 -0800956 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800957 Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
958 + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
Sanket Agarwal090bf552016-04-21 14:10:55 -0700959 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800960
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800961 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800962 mQuietEnableExternal = false;
963 mEnableExternal = true;
964 // waive WRITE_SECURE_SETTINGS permission check
Jack He8caab152018-03-02 13:08:36 -0800965 sendEnableMsg(false,
966 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800967 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800968 if (DBG) {
969 Slog.d(TAG, "enable returning");
970 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800971 return true;
fredc0f420372012-04-12 00:02:00 -0700972 }
973
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700974 public boolean disable(String packageName, boolean persist) throws RemoteException {
975 final int callingUid = Binder.getCallingUid();
976 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
Zhihai Xu40874a02012-10-08 17:57:03 -0700977
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700978 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700979 // Check if packageName belongs to callingUid
980 checkPackage(callingUid, packageName);
981
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700982 if (!checkIfCallerIsForegroundUser()) {
983 Slog.w(TAG, "disable(): not allowed for non-active and non system user");
984 return false;
985 }
986
987 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
988 "Need BLUETOOTH ADMIN permission");
989
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700990 if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800991 callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700992 return false;
993 }
Zhihai Xu40874a02012-10-08 17:57:03 -0700994 }
995
fredcf2458862012-04-16 15:18:27 -0700996 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800997 Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
Matthew Xiecdce0b92012-07-12 19:06:15 -0700998 }
fredcf2458862012-04-16 15:18:27 -0700999
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001000 synchronized (mReceiver) {
Ugo Yufd8efab2019-10-16 20:27:23 +08001001 if (!isBluetoothPersistedStateOnAirplane()) {
1002 if (persist) {
1003 persistBluetoothSetting(BLUETOOTH_OFF);
1004 }
1005 mEnableExternal = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001006 }
Jack He8caab152018-03-02 13:08:36 -08001007 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
1008 packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08001009 }
fredc0f420372012-04-12 00:02:00 -07001010 return true;
1011 }
1012
baishengf62d8692018-01-25 18:07:24 +08001013 private boolean startConsentUiIfNeeded(String packageName,
1014 int callingUid, String intentAction) throws RemoteException {
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001015 if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
baishengf62d8692018-01-25 18:07:24 +08001016 return false;
1017 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001018 try {
1019 // Validate the package only if we are going to use it
1020 ApplicationInfo applicationInfo = mContext.getPackageManager()
1021 .getApplicationInfoAsUser(packageName,
1022 PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
1023 UserHandle.getUserId(callingUid));
1024 if (applicationInfo.uid != callingUid) {
baishengf62d8692018-01-25 18:07:24 +08001025 throw new SecurityException("Package " + packageName
1026 + " not in uid " + callingUid);
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001027 }
1028
Ivan Podogovd2d32b12016-12-05 16:46:52 +00001029 Intent intent = new Intent(intentAction);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001030 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001031 intent.setFlags(
1032 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001033 try {
1034 mContext.startActivity(intent);
1035 } catch (ActivityNotFoundException e) {
1036 // Shouldn't happen
1037 Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
1038 return false;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001039 }
Ivan Podogov1ab87252017-01-03 12:02:18 +00001040 return true;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001041 } catch (PackageManager.NameNotFoundException e) {
1042 throw new RemoteException(e.getMessage());
1043 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001044 }
1045
baishengf62d8692018-01-25 18:07:24 +08001046 /**
Jack Hea80cead2019-04-23 20:00:18 -07001047 * Check if AppOpsManager is available and the packageName belongs to uid
1048 *
1049 * A null package belongs to any uid
1050 */
1051 private void checkPackage(int uid, String packageName) {
1052 if (mAppOps == null) {
1053 Slog.w(TAG, "checkPackage(): called before system boot up, uid "
1054 + uid + ", packageName " + packageName);
1055 throw new IllegalStateException("System has not boot yet");
1056 }
1057 if (packageName == null) {
1058 Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
1059 return;
1060 }
1061 try {
1062 mAppOps.checkPackage(uid, packageName);
1063 } catch (SecurityException e) {
1064 Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
Jack Hea80cead2019-04-23 20:00:18 -07001065 throw new SecurityException(e.getMessage());
1066 }
1067 }
1068
1069 /**
baishengf62d8692018-01-25 18:07:24 +08001070 * Check if the caller must still pass permission check or if the caller is exempted
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001071 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
baishengf62d8692018-01-25 18:07:24 +08001072 *
1073 * Commands from some callers may be exempted from triggering the consent UI when
1074 * enabling bluetooth. This exemption is checked via the
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001075 * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
baishengf62d8692018-01-25 18:07:24 +08001076 * the consent UI where it may otherwise be required.
1077 *
1078 * @hide
1079 */
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001080 private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
baishengf62d8692018-01-25 18:07:24 +08001081 int result = mContext.checkCallingPermission(
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001082 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
baishengf62d8692018-01-25 18:07:24 +08001083 return result == PackageManager.PERMISSION_GRANTED;
1084 }
1085
fredc649fe492012-04-19 01:07:18 -07001086 public void unbindAndFinish() {
fredcf2458862012-04-16 15:18:27 -07001087 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001088 Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
1089 + " mUnbinding = " + mUnbinding);
fredcf2458862012-04-16 15:18:27 -07001090 }
1091
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001092 try {
1093 mBluetoothLock.writeLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001094 if (mUnbinding) {
1095 return;
1096 }
fredc0f420372012-04-12 00:02:00 -07001097 mUnbinding = true;
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001098 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
Pavlin Radoslavov74f60c02016-09-21 17:28:11 -07001099 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
Zhihai Xu40874a02012-10-08 17:57:03 -07001100 if (mBluetooth != null) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001101 //Unregister callback object
1102 try {
1103 mBluetooth.unregisterCallback(mBluetoothCallback);
1104 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001105 Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001106 }
Marie Janssen9db28eb2016-01-12 16:05:15 -08001107 mBluetoothBinder = null;
fredcd6883532012-04-25 17:46:13 -07001108 mBluetooth = null;
fredc0f420372012-04-12 00:02:00 -07001109 mContext.unbindService(mConnection);
fredcd6883532012-04-25 17:46:13 -07001110 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -07001111 mBinding = false;
fredcf2458862012-04-16 15:18:27 -07001112 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001113 mUnbinding = false;
fredc0f420372012-04-12 00:02:00 -07001114 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001115 mBluetoothGatt = null;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001116 } finally {
1117 mBluetoothLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -07001118 }
1119 }
1120
Matthew Xieddf7e472013-03-01 18:41:02 -08001121 public IBluetoothGatt getBluetoothGatt() {
1122 // sync protection
1123 return mBluetoothGatt;
1124 }
1125
Benjamin Franze8b98922014-11-12 15:57:54 +00001126 @Override
1127 public boolean bindBluetoothProfileService(int bluetoothProfile,
1128 IBluetoothProfileServiceConnection proxy) {
1129 if (!mEnable) {
1130 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001131 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
1132 + ", while Bluetooth was disabled");
Benjamin Franze8b98922014-11-12 15:57:54 +00001133 }
1134 return false;
1135 }
1136 synchronized (mProfileServices) {
1137 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
1138 if (psc == null) {
1139 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001140 Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
1141 + bluetoothProfile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001142 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001143
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001144 if (bluetoothProfile != BluetoothProfile.HEADSET) {
1145 return false;
1146 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001147
1148 Intent intent = new Intent(IBluetoothHeadset.class.getName());
Benjamin Franze8b98922014-11-12 15:57:54 +00001149 psc = new ProfileServiceConnections(intent);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001150 if (!psc.bindService()) {
1151 return false;
1152 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001153
Benjamin Franze8b98922014-11-12 15:57:54 +00001154 mProfileServices.put(new Integer(bluetoothProfile), psc);
Benjamin Franze8b98922014-11-12 15:57:54 +00001155 }
1156 }
1157
1158 // Introducing a delay to give the client app time to prepare
1159 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
1160 addProxyMsg.arg1 = bluetoothProfile;
1161 addProxyMsg.obj = proxy;
1162 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
1163 return true;
1164 }
1165
1166 @Override
1167 public void unbindBluetoothProfileService(int bluetoothProfile,
1168 IBluetoothProfileServiceConnection proxy) {
1169 synchronized (mProfileServices) {
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001170 Integer profile = new Integer(bluetoothProfile);
1171 ProfileServiceConnections psc = mProfileServices.get(profile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001172 if (psc == null) {
1173 return;
1174 }
1175 psc.removeProxy(proxy);
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001176 if (psc.isEmpty()) {
1177 // All prxoies are disconnected, unbind with the service.
1178 try {
1179 mContext.unbindService(psc);
1180 } catch (IllegalArgumentException e) {
1181 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
1182 }
1183 mProfileServices.remove(profile);
1184 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001185 }
1186 }
1187
1188 private void unbindAllBluetoothProfileServices() {
1189 synchronized (mProfileServices) {
1190 for (Integer i : mProfileServices.keySet()) {
1191 ProfileServiceConnections psc = mProfileServices.get(i);
Benjamin Franz5b614592014-12-09 18:58:45 +00001192 try {
1193 mContext.unbindService(psc);
1194 } catch (IllegalArgumentException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001195 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
Benjamin Franz5b614592014-12-09 18:58:45 +00001196 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001197 psc.removeAllProxies();
1198 }
1199 mProfileServices.clear();
1200 }
1201 }
1202
1203 /**
Miao Chou658bf2f2015-06-26 17:14:35 -07001204 * Send enable message and set adapter name and address. Called when the boot phase becomes
1205 * PHASE_SYSTEM_SERVICES_READY.
1206 */
1207 public void handleOnBootPhase() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001208 if (DBG) {
1209 Slog.d(TAG, "Bluetooth boot completed");
1210 }
Jack Hea80cead2019-04-23 20:00:18 -07001211 mAppOps = mContext.getSystemService(AppOpsManager.class);
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001212 UserManagerInternal userManagerInternal =
1213 LocalServices.getService(UserManagerInternal.class);
1214 userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001215 final boolean isBluetoothDisallowed = isBluetoothDisallowed();
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001216 if (isBluetoothDisallowed) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001217 return;
1218 }
Zongheng Wang79e0bf62019-07-08 15:22:04 -07001219 final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
1220 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001221 if (DBG) {
1222 Slog.d(TAG, "Auto-enabling Bluetooth.");
1223 }
Jack He8caab152018-03-02 13:08:36 -08001224 sendEnableMsg(mQuietEnableExternal,
1225 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
1226 mContext.getPackageName());
Ajay Panickerbf796d82016-03-11 13:47:20 -08001227 } else if (!isNameAndAddressSet()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001228 if (DBG) {
1229 Slog.d(TAG, "Getting adapter name and address");
1230 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001231 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1232 mHandler.sendMessage(getMsg);
Miao Chou658bf2f2015-06-26 17:14:35 -07001233 }
Ugo Yufd8efab2019-10-16 20:27:23 +08001234 if (mBluetoothAirplaneModeListener != null) {
1235 mBluetoothAirplaneModeListener.start(
1236 new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext));
1237 }
Miao Chou658bf2f2015-06-26 17:14:35 -07001238 }
1239
1240 /**
1241 * Called when switching to a different foreground user.
1242 */
1243 public void handleOnSwitchUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001244 if (DBG) {
1245 Slog.d(TAG, "User " + userHandle + " switched");
1246 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001247 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1248 }
1249
1250 /**
1251 * Called when user is unlocked.
1252 */
1253 public void handleOnUnlockUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001254 if (DBG) {
1255 Slog.d(TAG, "User " + userHandle + " unlocked");
1256 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001257 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
Miao Chou658bf2f2015-06-26 17:14:35 -07001258 }
1259
1260 /**
Benjamin Franze8b98922014-11-12 15:57:54 +00001261 * This class manages the clients connected to a given ProfileService
1262 * and maintains the connection with that service.
1263 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001264 private final class ProfileServiceConnections
1265 implements ServiceConnection, IBinder.DeathRecipient {
Benjamin Franze8b98922014-11-12 15:57:54 +00001266 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001267 new RemoteCallbackList<IBluetoothProfileServiceConnection>();
Benjamin Franze8b98922014-11-12 15:57:54 +00001268 IBinder mService;
1269 ComponentName mClassName;
1270 Intent mIntent;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001271 boolean mInvokingProxyCallbacks = false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001272
1273 ProfileServiceConnections(Intent intent) {
1274 mService = null;
1275 mClassName = null;
1276 mIntent = intent;
1277 }
1278
Benjamin Franz5b614592014-12-09 18:58:45 +00001279 private boolean bindService() {
jonerlin37fc85d2018-08-09 16:39:43 +08001280 int state = BluetoothAdapter.STATE_OFF;
1281 try {
1282 mBluetoothLock.readLock().lock();
1283 if (mBluetooth != null) {
1284 state = mBluetooth.getState();
1285 }
1286 } catch (RemoteException e) {
1287 Slog.e(TAG, "Unable to call getState", e);
1288 return false;
1289 } finally {
1290 mBluetoothLock.readLock().unlock();
1291 }
1292
1293 if (!mEnable || state != BluetoothAdapter.STATE_ON) {
1294 if (DBG) {
1295 Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
1296 }
1297 return false;
1298 }
1299
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001300 if (mIntent != null && mService == null && doBind(mIntent, this, 0,
1301 UserHandle.CURRENT_OR_SELF)) {
Benjamin Franze8b98922014-11-12 15:57:54 +00001302 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1303 msg.obj = this;
1304 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
Benjamin Franz5b614592014-12-09 18:58:45 +00001305 return true;
Benjamin Franze8b98922014-11-12 15:57:54 +00001306 }
Jeff Sharkey67609c72016-03-05 14:29:13 -07001307 Slog.w(TAG, "Unable to bind with intent: " + mIntent);
Benjamin Franz5b614592014-12-09 18:58:45 +00001308 return false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001309 }
1310
1311 private void addProxy(IBluetoothProfileServiceConnection proxy) {
1312 mProxies.register(proxy);
1313 if (mService != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001314 try {
Benjamin Franze8b98922014-11-12 15:57:54 +00001315 proxy.onServiceConnected(mClassName, mService);
1316 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001317 Slog.e(TAG, "Unable to connect to proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001318 }
1319 } else {
1320 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1321 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1322 msg.obj = this;
1323 mHandler.sendMessage(msg);
1324 }
1325 }
1326 }
1327
1328 private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1329 if (proxy != null) {
1330 if (mProxies.unregister(proxy)) {
1331 try {
1332 proxy.onServiceDisconnected(mClassName);
1333 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001334 Slog.e(TAG, "Unable to disconnect proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001335 }
1336 }
1337 } else {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001338 Slog.w(TAG, "Trying to remove a null proxy");
Benjamin Franze8b98922014-11-12 15:57:54 +00001339 }
1340 }
1341
1342 private void removeAllProxies() {
1343 onServiceDisconnected(mClassName);
1344 mProxies.kill();
1345 }
1346
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001347 private boolean isEmpty() {
1348 return mProxies.getRegisteredCallbackCount() == 0;
1349 }
1350
Benjamin Franze8b98922014-11-12 15:57:54 +00001351 @Override
1352 public void onServiceConnected(ComponentName className, IBinder service) {
1353 // remove timeout message
1354 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1355 mService = service;
1356 mClassName = className;
1357 try {
1358 mService.linkToDeath(this, 0);
1359 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001360 Slog.e(TAG, "Unable to linkToDeath", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001361 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001362
1363 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001364 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001365 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001366 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001367 mInvokingProxyCallbacks = true;
1368
1369 final int n = mProxies.beginBroadcast();
1370 try {
1371 for (int i = 0; i < n; i++) {
1372 try {
1373 mProxies.getBroadcastItem(i).onServiceConnected(className, service);
1374 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001375 Slog.e(TAG, "Unable to connect to proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001376 }
1377 }
1378 } finally {
1379 mProxies.finishBroadcast();
1380 mInvokingProxyCallbacks = false;
1381 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001382 }
1383
1384 @Override
1385 public void onServiceDisconnected(ComponentName className) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001386 if (mService == null) {
1387 return;
1388 }
Chienyuan177156b2018-12-18 10:40:25 +08001389 try {
1390 mService.unlinkToDeath(this, 0);
1391 } catch (NoSuchElementException e) {
1392 Log.e(TAG, "error unlinking to death", e);
1393 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001394 mService = null;
1395 mClassName = null;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001396
1397 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001398 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001399 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001400 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001401 mInvokingProxyCallbacks = true;
1402
1403 final int n = mProxies.beginBroadcast();
1404 try {
1405 for (int i = 0; i < n; i++) {
1406 try {
1407 mProxies.getBroadcastItem(i).onServiceDisconnected(className);
1408 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001409 Slog.e(TAG, "Unable to disconnect from proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001410 }
1411 }
1412 } finally {
1413 mProxies.finishBroadcast();
1414 mInvokingProxyCallbacks = false;
1415 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001416 }
1417
1418 @Override
1419 public void binderDied() {
1420 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001421 Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
Benjamin Franze8b98922014-11-12 15:57:54 +00001422 }
1423 onServiceDisconnected(mClassName);
1424 // Trigger rebind
1425 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1426 msg.obj = this;
1427 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1428 }
1429 }
1430
fredcbf072a72012-05-09 16:52:50 -07001431 private void sendBluetoothStateCallback(boolean isUp) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001432 try {
1433 int n = mStateChangeCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001434 if (DBG) {
1435 Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
1436 + " receivers.");
1437 }
1438 for (int i = 0; i < n; i++) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001439 try {
1440 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
1441 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001442 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001443 }
fredcbf072a72012-05-09 16:52:50 -07001444 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001445 } finally {
1446 mStateChangeCallbacks.finishBroadcast();
fredcbf072a72012-05-09 16:52:50 -07001447 }
fredcbf072a72012-05-09 16:52:50 -07001448 }
1449
1450 /**
Zhihai Xu40874a02012-10-08 17:57:03 -07001451 * Inform BluetoothAdapter instances that Adapter service is up
1452 */
1453 private void sendBluetoothServiceUpCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001454 try {
1455 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001456 Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1457 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001458 try {
1459 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001460 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001461 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
Zhihai Xu40874a02012-10-08 17:57:03 -07001462 }
1463 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001464 } finally {
1465 mCallbacks.finishBroadcast();
Zhihai Xu40874a02012-10-08 17:57:03 -07001466 }
1467 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001468
Zhihai Xu40874a02012-10-08 17:57:03 -07001469 /**
fredcbf072a72012-05-09 16:52:50 -07001470 * Inform BluetoothAdapter instances that Adapter service is down
1471 */
1472 private void sendBluetoothServiceDownCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001473 try {
1474 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001475 Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1476 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001477 try {
1478 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001479 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001480 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
fredcd6883532012-04-25 17:46:13 -07001481 }
1482 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001483 } finally {
1484 mCallbacks.finishBroadcast();
fredcd6883532012-04-25 17:46:13 -07001485 }
1486 }
Svet Ganov408abf72015-05-12 19:13:36 -07001487
fredc0f420372012-04-12 00:02:00 -07001488 public String getAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001489 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001490
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001491 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1492 Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001493 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001494 }
1495
Svet Ganov408abf72015-05-12 19:13:36 -07001496 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1497 != PackageManager.PERMISSION_GRANTED) {
1498 return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1499 }
1500
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001501 try {
1502 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001503 if (mBluetooth != null) {
1504 return mBluetooth.getAddress();
1505 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001506 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001507 Slog.e(TAG,
1508 "getAddress(): Unable to retrieve address remotely. Returning cached address",
1509 e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001510 } finally {
1511 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001512 }
Ajay Panickerbf796d82016-03-11 13:47:20 -08001513
Matthew Xiecdce0b92012-07-12 19:06:15 -07001514 // mAddress is accessed from outside.
1515 // It is alright without a lock. Here, bluetooth is off, no other thread is
1516 // changing mAddress
fredc0f420372012-04-12 00:02:00 -07001517 return mAddress;
1518 }
fredc649fe492012-04-19 01:07:18 -07001519
fredc0f420372012-04-12 00:02:00 -07001520 public String getName() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001521 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001522
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001523 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1524 Slog.w(TAG, "getName(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001525 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001526 }
1527
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001528 try {
1529 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001530 if (mBluetooth != null) {
1531 return mBluetooth.getName();
1532 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001533 } catch (RemoteException e) {
1534 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1535 } finally {
1536 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001537 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001538
Matthew Xiecdce0b92012-07-12 19:06:15 -07001539 // mName is accessed from outside.
1540 // It alright without a lock. Here, bluetooth is off, no other thread is
1541 // changing mName
fredc0f420372012-04-12 00:02:00 -07001542 return mName;
1543 }
1544
fredc0f420372012-04-12 00:02:00 -07001545 private class BluetoothServiceConnection implements ServiceConnection {
Marie Janssencb21ad72016-12-13 10:51:02 -08001546 public void onServiceConnected(ComponentName componentName, IBinder service) {
1547 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001548 if (DBG) {
1549 Slog.d(TAG, "BluetoothServiceConnection: " + name);
1550 }
fredc0f420372012-04-12 00:02:00 -07001551 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001552 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001553 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001554 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001555 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1556 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001557 Slog.e(TAG, "Unknown service connected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001558 return;
1559 }
fredc0f420372012-04-12 00:02:00 -07001560 msg.obj = service;
1561 mHandler.sendMessage(msg);
1562 }
1563
Marie Janssencb21ad72016-12-13 10:51:02 -08001564 public void onServiceDisconnected(ComponentName componentName) {
1565 // Called if we unexpectedly disconnect.
1566 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001567 if (DBG) {
1568 Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
1569 }
fredc0f420372012-04-12 00:02:00 -07001570 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001571 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001572 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001573 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001574 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1575 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001576 Slog.e(TAG, "Unknown service disconnected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001577 return;
1578 }
fredc0f420372012-04-12 00:02:00 -07001579 mHandler.sendMessage(msg);
1580 }
1581 }
1582
1583 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1584
Zhihai Xu40874a02012-10-08 17:57:03 -07001585 private class BluetoothHandler extends Handler {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001586 boolean mGetNameAddressOnly = false;
1587
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001588 BluetoothHandler(Looper looper) {
Zhihai Xu40874a02012-10-08 17:57:03 -07001589 super(looper);
1590 }
1591
fredc0f420372012-04-12 00:02:00 -07001592 @Override
1593 public void handleMessage(Message msg) {
fredc0f420372012-04-12 00:02:00 -07001594 switch (msg.what) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001595 case MESSAGE_GET_NAME_AND_ADDRESS:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001596 if (DBG) {
1597 Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1598 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001599 try {
1600 mBluetoothLock.writeLock().lock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001601 if ((mBluetooth == null) && (!mBinding)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001602 if (DBG) {
1603 Slog.d(TAG, "Binding to service to get name and address");
1604 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001605 mGetNameAddressOnly = true;
1606 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1607 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
1608 Intent i = new Intent(IBluetooth.class.getName());
1609 if (!doBind(i, mConnection,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001610 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1611 UserHandle.CURRENT)) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001612 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1613 } else {
1614 mBinding = true;
1615 }
1616 } else if (mBluetooth != null) {
1617 try {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001618 storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress());
Ajay Panicker4bb48302016-03-31 14:14:27 -07001619 } catch (RemoteException re) {
1620 Slog.e(TAG, "Unable to grab names", re);
1621 }
1622 if (mGetNameAddressOnly && !mEnable) {
1623 unbindAndFinish();
1624 }
1625 mGetNameAddressOnly = false;
1626 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001627 } finally {
1628 mBluetoothLock.writeLock().unlock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001629 }
1630 break;
1631
Matthew Xiecdce0b92012-07-12 19:06:15 -07001632 case MESSAGE_ENABLE:
fredcf2458862012-04-16 15:18:27 -07001633 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001634 Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
fredc649fe492012-04-19 01:07:18 -07001635 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001636 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1637 mEnable = true;
Calvin Ona0b91d72016-06-15 17:58:23 -07001638
1639 // Use service interface to get the exact state
1640 try {
1641 mBluetoothLock.readLock().lock();
1642 if (mBluetooth != null) {
1643 int state = mBluetooth.getState();
1644 if (state == BluetoothAdapter.STATE_BLE_ON) {
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001645 Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
Calvin Ona0b91d72016-06-15 17:58:23 -07001646 mBluetooth.onLeServiceUp();
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001647 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Calvin Ona0b91d72016-06-15 17:58:23 -07001648 break;
1649 }
1650 }
1651 } catch (RemoteException e) {
1652 Slog.e(TAG, "", e);
1653 } finally {
1654 mBluetoothLock.readLock().unlock();
1655 }
1656
1657 mQuietEnable = (msg.arg1 == 1);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001658 if (mBluetooth == null) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001659 handleEnable(mQuietEnable);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001660 } else {
1661 //
1662 // We need to wait until transitioned to STATE_OFF and
1663 // the previous Bluetooth process has exited. The
1664 // waiting period has three components:
1665 // (a) Wait until the local state is STATE_OFF. This
1666 // is accomplished by "waitForOnOff(false, true)".
1667 // (b) Wait until the STATE_OFF state is updated to
1668 // all components.
1669 // (c) Wait until the Bluetooth process exits, and
1670 // ActivityManager detects it.
1671 // The waiting for (b) and (c) is accomplished by
1672 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001673 // message. The delay time is backed off if Bluetooth
1674 // continuously failed to turn on itself.
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001675 //
1676 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001677 Message restartMsg =
1678 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001679 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001680 }
fredc649fe492012-04-19 01:07:18 -07001681 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001682
fredc0f420372012-04-12 00:02:00 -07001683 case MESSAGE_DISABLE:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001684 if (DBG) {
1685 Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
1686 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001687 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1688 if (mEnable && mBluetooth != null) {
1689 waitForOnOff(true, false);
1690 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001691 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001692 waitForOnOff(false, false);
1693 } else {
1694 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001695 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001696 }
fredc0f420372012-04-12 00:02:00 -07001697 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001698
Stanley Tng873b5702017-05-01 21:27:31 -07001699 case MESSAGE_RESTORE_USER_SETTING:
Jack He8caab152018-03-02 13:08:36 -08001700 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1701 if (DBG) {
1702 Slog.d(TAG, "Restore Bluetooth state to disabled");
Stanley Tng873b5702017-05-01 21:27:31 -07001703 }
Jack He8caab152018-03-02 13:08:36 -08001704 persistBluetoothSetting(BLUETOOTH_OFF);
1705 mEnableExternal = false;
1706 sendDisableMsg(
1707 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1708 mContext.getPackageName());
1709 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1710 if (DBG) {
1711 Slog.d(TAG, "Restore Bluetooth state to enabled");
1712 }
1713 mQuietEnableExternal = false;
1714 mEnableExternal = true;
1715 // waive WRITE_SECURE_SETTINGS permission check
1716 sendEnableMsg(false,
1717 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1718 mContext.getPackageName());
Stanley Tng873b5702017-05-01 21:27:31 -07001719 }
1720 break;
1721
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001722 case MESSAGE_REGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001723 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001724 mCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001725 break;
Marie Janssencb21ad72016-12-13 10:51:02 -08001726 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001727 case MESSAGE_UNREGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001728 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001729 mCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001730 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001731 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001732 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
1733 IBluetoothStateChangeCallback callback =
1734 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001735 mStateChangeCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001736 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001737 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001738 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
1739 IBluetoothStateChangeCallback callback =
1740 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001741 mStateChangeCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001742 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001743 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001744 case MESSAGE_ADD_PROXY_DELAYED: {
Jack He8caab152018-03-02 13:08:36 -08001745 ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
Benjamin Franze8b98922014-11-12 15:57:54 +00001746 if (psc == null) {
1747 break;
1748 }
1749 IBluetoothProfileServiceConnection proxy =
1750 (IBluetoothProfileServiceConnection) msg.obj;
1751 psc.addProxy(proxy);
1752 break;
1753 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001754 case MESSAGE_BIND_PROFILE_SERVICE: {
Benjamin Franze8b98922014-11-12 15:57:54 +00001755 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1756 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1757 if (psc == null) {
1758 break;
1759 }
1760 psc.bindService();
1761 break;
1762 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001763 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
1764 if (DBG) {
1765 Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
1766 }
fredc0f420372012-04-12 00:02:00 -07001767
1768 IBinder service = (IBinder) msg.obj;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001769 try {
1770 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001771 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001772 mBluetoothGatt =
1773 IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
Myles Watson304ebf22018-05-11 08:47:24 -07001774 continueFromBleOnState();
Matthew Xieddf7e472013-03-01 18:41:02 -08001775 break;
1776 } // else must be SERVICE_IBLUETOOTH
1777
1778 //Remove timeout
Zhihai Xuaf5971e2013-06-10 20:28:31 -07001779 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Matthew Xieddf7e472013-03-01 18:41:02 -08001780
fredc0f420372012-04-12 00:02:00 -07001781 mBinding = false;
Marie Janssen9db28eb2016-01-12 16:05:15 -08001782 mBluetoothBinder = service;
Jeff Sharkey0a17db12016-11-04 11:23:46 -06001783 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
fredc0f420372012-04-12 00:02:00 -07001784
Ajay Panicker4bb48302016-03-31 14:14:27 -07001785 if (!isNameAndAddressSet()) {
1786 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1787 mHandler.sendMessage(getMsg);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001788 if (mGetNameAddressOnly) {
1789 return;
1790 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001791 }
1792
Matthew Xiecdce0b92012-07-12 19:06:15 -07001793 //Register callback object
fredcbf072a72012-05-09 16:52:50 -07001794 try {
Matthew Xiecdce0b92012-07-12 19:06:15 -07001795 mBluetooth.registerCallback(mBluetoothCallback);
1796 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001797 Slog.e(TAG, "Unable to register BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001798 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001799 //Inform BluetoothAdapter instances that service is up
Zhihai Xu40874a02012-10-08 17:57:03 -07001800 sendBluetoothServiceUpCallback();
1801
Matthew Xiecdce0b92012-07-12 19:06:15 -07001802 //Do enable request
1803 try {
Zach Johnson1c86ed12019-11-26 21:46:08 -08001804 if (!mBluetooth.enable(mQuietEnable)) {
1805 Slog.e(TAG, "IBluetooth.enable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07001806 }
1807 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001808 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07001809 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001810 } finally {
1811 mBluetoothLock.writeLock().unlock();
Freda8c6df02012-07-11 10:25:23 -07001812 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001813
1814 if (!mEnable) {
1815 waitForOnOff(true, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001816 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001817 waitForOnOff(false, false);
1818 }
fredc649fe492012-04-19 01:07:18 -07001819 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001820 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001821 case MESSAGE_BLUETOOTH_STATE_CHANGE: {
fredcbf072a72012-05-09 16:52:50 -07001822 int prevState = msg.arg1;
1823 int newState = msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08001824 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001825 Slog.d(TAG,
1826 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
1827 prevState) + " > " + BluetoothAdapter.nameForState(
1828 newState));
Marie Janssencb21ad72016-12-13 10:51:02 -08001829 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001830 mState = newState;
1831 bluetoothStateChangeHandler(prevState, newState);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001832 // handle error state transition case from TURNING_ON to OFF
1833 // unbind and rebind bluetooth service and enable bluetooth
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001834 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
1835 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001836 recoverBluetoothServiceFromError(false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001837 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001838 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
1839 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001840 recoverBluetoothServiceFromError(true);
Nitin Arorad055adb2015-03-02 15:03:51 -08001841 }
Calvin Ona0b91d72016-06-15 17:58:23 -07001842 // If we tried to enable BT while BT was in the process of shutting down,
1843 // wait for the BT process to fully tear down and then force a restart
1844 // here. This is a bit of a hack (b/29363429).
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001845 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
1846 == BluetoothAdapter.STATE_OFF)) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001847 if (mEnable) {
1848 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1849 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001850 Message restartMsg =
1851 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001852 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Calvin Ona0b91d72016-06-15 17:58:23 -07001853 }
1854 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001855 if (newState == BluetoothAdapter.STATE_ON
1856 || newState == BluetoothAdapter.STATE_BLE_ON) {
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001857 // bluetooth is working, reset the counter
1858 if (mErrorRecoveryRetryCounter != 0) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001859 Slog.w(TAG, "bluetooth is recovered from error");
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001860 mErrorRecoveryRetryCounter = 0;
1861 }
1862 }
fredc649fe492012-04-19 01:07:18 -07001863 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001864 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001865 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
Marie Janssencb21ad72016-12-13 10:51:02 -08001866 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001867 try {
1868 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001869 if (msg.arg1 == SERVICE_IBLUETOOTH) {
1870 // if service is unbinded already, do nothing and return
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001871 if (mBluetooth == null) {
1872 break;
1873 }
Matthew Xieddf7e472013-03-01 18:41:02 -08001874 mBluetooth = null;
1875 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1876 mBluetoothGatt = null;
1877 break;
1878 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001879 Slog.e(TAG, "Unknown argument for service disconnect!");
Matthew Xieddf7e472013-03-01 18:41:02 -08001880 break;
1881 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001882 } finally {
1883 mBluetoothLock.writeLock().unlock();
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301884 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001885
Marie Janssene54b4222017-03-16 18:10:59 -07001886 // log the unexpected crash
1887 addCrashLog();
Jack He8caab152018-03-02 13:08:36 -08001888 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
1889 mContext.getPackageName(), false);
Zhihai Xu40874a02012-10-08 17:57:03 -07001890 if (mEnable) {
1891 mEnable = false;
1892 // Send a Bluetooth Restart message
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001893 Message restartMsg =
1894 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001895 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Zhihai Xu40874a02012-10-08 17:57:03 -07001896 }
1897
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001898 sendBluetoothServiceDownCallback();
Zhihai Xu40874a02012-10-08 17:57:03 -07001899
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001900 // Send BT state broadcast to update
1901 // the BT icon correctly
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001902 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
1903 == BluetoothAdapter.STATE_ON)) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001904 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001905 BluetoothAdapter.STATE_TURNING_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001906 mState = BluetoothAdapter.STATE_TURNING_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07001907 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001908 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1909 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001910 BluetoothAdapter.STATE_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001911 }
1912
1913 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1914 mState = BluetoothAdapter.STATE_OFF;
fredc649fe492012-04-19 01:07:18 -07001915 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001916 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001917 case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001918 mErrorRecoveryRetryCounter++;
1919 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
1920 + mErrorRecoveryRetryCounter);
1921 if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
1922 /* Enable without persisting the setting as
1923 it doesnt change when IBluetooth
1924 service restarts */
1925 mEnable = true;
1926 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
1927 mContext.getPackageName(), true);
1928 handleEnable(mQuietEnable);
1929 } else {
1930 Slog.e(TAG, "Reach maximum retry to restart Bluetooth!");
1931 }
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301932 break;
1933 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001934 case MESSAGE_TIMEOUT_BIND: {
1935 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1936 mBluetoothLock.writeLock().lock();
1937 mBinding = false;
1938 mBluetoothLock.writeLock().unlock();
1939 break;
1940 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001941 case MESSAGE_TIMEOUT_UNBIND: {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001942 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001943 mBluetoothLock.writeLock().lock();
1944 mUnbinding = false;
1945 mBluetoothLock.writeLock().unlock();
fredc649fe492012-04-19 01:07:18 -07001946 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001947 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001948
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001949 case MESSAGE_USER_SWITCHED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001950 if (DBG) {
1951 Slog.d(TAG, "MESSAGE_USER_SWITCHED");
1952 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001953 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001954
Zhihai Xu40874a02012-10-08 17:57:03 -07001955 /* disable and enable BT when detect a user switch */
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07001956 if (mBluetooth != null && isEnabled()) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001957 try {
1958 mBluetoothLock.readLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001959 if (mBluetooth != null) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001960 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xu40874a02012-10-08 17:57:03 -07001961 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001962 } catch (RemoteException re) {
1963 Slog.e(TAG, "Unable to unregister", re);
1964 } finally {
1965 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001966 }
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001967
1968 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1969 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
1970 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
1971 mState = BluetoothAdapter.STATE_OFF;
1972 }
1973 if (mState == BluetoothAdapter.STATE_OFF) {
1974 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
1975 mState = BluetoothAdapter.STATE_TURNING_ON;
1976 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001977
1978 waitForOnOff(true, false);
1979
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001980 if (mState == BluetoothAdapter.STATE_TURNING_ON) {
1981 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
1982 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001983
Benjamin Franze8b98922014-11-12 15:57:54 +00001984 unbindAllBluetoothProfileServices();
Zhihai Xu40874a02012-10-08 17:57:03 -07001985 // disable
Jack He8caab152018-03-02 13:08:36 -08001986 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
1987 mContext.getPackageName(), false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001988 handleDisable();
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001989 // Pbap service need receive STATE_TURNING_OFF intent to close
1990 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001991 BluetoothAdapter.STATE_TURNING_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001992
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001993 boolean didDisableTimeout = !waitForOnOff(false, true);
Zhihai Xu40874a02012-10-08 17:57:03 -07001994
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001995 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001996 BluetoothAdapter.STATE_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001997 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001998
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07001999 try {
2000 mBluetoothLock.writeLock().lock();
2001 if (mBluetooth != null) {
2002 mBluetooth = null;
2003 // Unbind
2004 mContext.unbindService(mConnection);
2005 }
2006 mBluetoothGatt = null;
2007 } finally {
2008 mBluetoothLock.writeLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002009 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002010
Pavlin Radoslavov41401112016-06-27 15:25:18 -07002011 //
2012 // If disabling Bluetooth times out, wait for an
2013 // additional amount of time to ensure the process is
2014 // shut down completely before attempting to restart.
2015 //
2016 if (didDisableTimeout) {
2017 SystemClock.sleep(3000);
2018 } else {
2019 SystemClock.sleep(100);
2020 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002021
Zhihai Xu4e22ad32012-11-13 15:11:26 -08002022 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2023 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07002024 // enable
Jack He8caab152018-03-02 13:08:36 -08002025 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
2026 mContext.getPackageName(), true);
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07002027 // mEnable flag could have been reset on disableBLE. Reenable it.
2028 mEnable = true;
Zhihai Xu401202b2012-12-03 11:36:21 -08002029 handleEnable(mQuietEnable);
John Spurlock8a985d22014-02-25 09:40:05 -05002030 } else if (mBinding || mBluetooth != null) {
Zhihai Xu40874a02012-10-08 17:57:03 -07002031 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
2032 userMsg.arg2 = 1 + msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08002033 // if user is switched when service is binding retry after a delay
Zhihai Xu40874a02012-10-08 17:57:03 -07002034 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
2035 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002036 Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
Zhihai Xu40874a02012-10-08 17:57:03 -07002037 }
John Spurlock8a985d22014-02-25 09:40:05 -05002038 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002039 break;
2040 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002041 case MESSAGE_USER_UNLOCKED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002042 if (DBG) {
2043 Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
2044 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002045 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
2046
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002047 if (mEnable && !mBinding && (mBluetooth == null)) {
2048 // We should be connected, but we gave up for some
2049 // reason; maybe the Bluetooth service wasn't encryption
2050 // aware, so try binding again.
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002051 if (DBG) {
2052 Slog.d(TAG, "Enabled but not bound; retrying after unlock");
2053 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002054 handleEnable(mQuietEnable);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002055 }
2056 }
fredc0f420372012-04-12 00:02:00 -07002057 }
2058 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002059 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002060
Zhihai Xu401202b2012-12-03 11:36:21 -08002061 private void handleEnable(boolean quietMode) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002062 mQuietEnable = quietMode;
2063
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002064 try {
2065 mBluetoothLock.writeLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002066 if ((mBluetooth == null) && (!mBinding)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002067 //Start bind timeout and bind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002068 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
2069 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002070 Intent i = new Intent(IBluetooth.class.getName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002071 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
Dianne Hackbornce09f5a2014-10-10 15:03:13 -07002072 UserHandle.CURRENT)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002073 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Zhihai Xu40874a02012-10-08 17:57:03 -07002074 } else {
2075 mBinding = true;
Matthew Xiecdce0b92012-07-12 19:06:15 -07002076 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002077 } else if (mBluetooth != null) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002078 //Enable bluetooth
2079 try {
Zach Johnson1c86ed12019-11-26 21:46:08 -08002080 if (!mBluetooth.enable(mQuietEnable)) {
2081 Slog.e(TAG, "IBluetooth.enable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002082 }
2083 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002084 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002085 }
2086 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002087 } finally {
2088 mBluetoothLock.writeLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002089 }
2090 }
2091
Dianne Hackborn221ea892013-08-04 16:50:16 -07002092 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
2093 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
2094 intent.setComponent(comp);
2095 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07002096 Slog.e(TAG, "Fail to bind to: " + intent);
Dianne Hackborn221ea892013-08-04 16:50:16 -07002097 return false;
2098 }
2099 return true;
2100 }
2101
Zhihai Xu401202b2012-12-03 11:36:21 -08002102 private void handleDisable() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002103 try {
2104 mBluetoothLock.readLock().lock();
Andre Eisenbach305fdab2015-11-11 21:43:26 -08002105 if (mBluetooth != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002106 if (DBG) {
2107 Slog.d(TAG, "Sending off request.");
2108 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002109 if (!mBluetooth.disable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002110 Slog.e(TAG, "IBluetooth.disable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002111 }
2112 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002113 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002114 Slog.e(TAG, "Unable to call disable()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002115 } finally {
2116 mBluetoothLock.readLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002117 }
2118 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002119
2120 private boolean checkIfCallerIsForegroundUser() {
2121 int foregroundUser;
2122 int callingUser = UserHandle.getCallingUserId();
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002123 int callingUid = Binder.getCallingUid();
Zhihai Xu40874a02012-10-08 17:57:03 -07002124 long callingIdentity = Binder.clearCallingIdentity();
Benjamin Franze8b98922014-11-12 15:57:54 +00002125 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2126 UserInfo ui = um.getProfileParent(callingUser);
2127 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002128 int callingAppId = UserHandle.getAppId(callingUid);
Zhihai Xu40874a02012-10-08 17:57:03 -07002129 boolean valid = false;
2130 try {
2131 foregroundUser = ActivityManager.getCurrentUser();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002132 valid = (callingUser == foregroundUser) || parentUser == foregroundUser
2133 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid;
Marie Janssencb21ad72016-12-13 10:51:02 -08002134 if (DBG && !valid) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002135 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
2136 + callingUser + " parentUser=" + parentUser + " foregroundUser="
2137 + foregroundUser);
Zhihai Xu40874a02012-10-08 17:57:03 -07002138 }
2139 } finally {
2140 Binder.restoreCallingIdentity(callingIdentity);
2141 }
2142 return valid;
2143 }
2144
Nitin Arorad055adb2015-03-02 15:03:51 -08002145 private void sendBleStateChanged(int prevState, int newState) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002146 if (DBG) {
2147 Slog.d(TAG,
2148 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
2149 + BluetoothAdapter.nameForState(newState));
2150 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002151 // Send broadcast message to everyone else
2152 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
2153 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2154 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2155 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2156 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
2157 }
2158
Zhihai Xu40874a02012-10-08 17:57:03 -07002159 private void bluetoothStateChangeHandler(int prevState, int newState) {
Nitin Arorad055adb2015-03-02 15:03:51 -08002160 boolean isStandardBroadcast = true;
Marie Janssencb21ad72016-12-13 10:51:02 -08002161 if (prevState == newState) { // No change. Nothing to do.
2162 return;
2163 }
2164 // Notify all proxy objects first of adapter state change
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002165 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002166 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002167 && newState == BluetoothAdapter.STATE_BLE_ON);
Zhihai Xu40874a02012-10-08 17:57:03 -07002168
Marie Janssencb21ad72016-12-13 10:51:02 -08002169 if (newState == BluetoothAdapter.STATE_OFF) {
2170 // If Bluetooth is off, send service down event to proxy objects, and unbind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002171 if (DBG) {
2172 Slog.d(TAG, "Bluetooth is complete send Service Down");
2173 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002174 sendBluetoothServiceDownCallback();
2175 unbindAndFinish();
Nitin Arorad055adb2015-03-02 15:03:51 -08002176 sendBleStateChanged(prevState, newState);
Marie Janssencb21ad72016-12-13 10:51:02 -08002177 // Don't broadcast as it has already been broadcast before
Nitin Arorad055adb2015-03-02 15:03:51 -08002178 isStandardBroadcast = false;
2179
Marie Janssencb21ad72016-12-13 10:51:02 -08002180 } else if (!intermediate_off) {
2181 // connect to GattService
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002182 if (DBG) {
2183 Slog.d(TAG, "Bluetooth is in LE only mode");
2184 }
Myles Watson304ebf22018-05-11 08:47:24 -07002185 if (mBluetoothGatt != null || !mContext.getPackageManager()
2186 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
2187 continueFromBleOnState();
Marie Janssencb21ad72016-12-13 10:51:02 -08002188 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002189 if (DBG) {
2190 Slog.d(TAG, "Binding Bluetooth GATT service");
2191 }
Myles Watson304ebf22018-05-11 08:47:24 -07002192 Intent i = new Intent(IBluetoothGatt.class.getName());
2193 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
2194 UserHandle.CURRENT);
Nitin Arorad055adb2015-03-02 15:03:51 -08002195 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002196 sendBleStateChanged(prevState, newState);
2197 //Don't broadcase this as std intent
2198 isStandardBroadcast = false;
2199
2200 } else if (intermediate_off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002201 if (DBG) {
2202 Slog.d(TAG, "Intermediate off, back to LE only mode");
2203 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002204 // For LE only mode, broadcast as is
2205 sendBleStateChanged(prevState, newState);
2206 sendBluetoothStateCallback(false); // BT is OFF for general users
2207 // Broadcast as STATE_OFF
2208 newState = BluetoothAdapter.STATE_OFF;
2209 sendBrEdrDownCallback();
Nitin Arorad055adb2015-03-02 15:03:51 -08002210 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002211 } else if (newState == BluetoothAdapter.STATE_ON) {
2212 boolean isUp = (newState == BluetoothAdapter.STATE_ON);
2213 sendBluetoothStateCallback(isUp);
2214 sendBleStateChanged(prevState, newState);
2215
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002216 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
2217 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002218 sendBleStateChanged(prevState, newState);
2219 isStandardBroadcast = false;
2220
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002221 } else if (newState == BluetoothAdapter.STATE_TURNING_ON
2222 || newState == BluetoothAdapter.STATE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002223 sendBleStateChanged(prevState, newState);
2224 }
2225
2226 if (isStandardBroadcast) {
2227 if (prevState == BluetoothAdapter.STATE_BLE_ON) {
2228 // Show prevState of BLE_ON as OFF to standard users
2229 prevState = BluetoothAdapter.STATE_OFF;
2230 }
2231 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
2232 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2233 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2234 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2235 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
Zhihai Xu40874a02012-10-08 17:57:03 -07002236 }
2237 }
2238
2239 /**
2240 * if on is true, wait for state become ON
2241 * if off is true, wait for state become OFF
2242 * if both on and off are false, wait for state not ON
2243 */
2244 private boolean waitForOnOff(boolean on, boolean off) {
2245 int i = 0;
2246 while (i < 10) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002247 try {
2248 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002249 if (mBluetooth == null) {
2250 break;
2251 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002252 if (on) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002253 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
2254 return true;
2255 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002256 } else if (off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002257 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) {
2258 return true;
2259 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002260 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002261 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) {
2262 return true;
2263 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002264 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002265 } catch (RemoteException e) {
2266 Slog.e(TAG, "getState()", e);
2267 break;
2268 } finally {
2269 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002270 }
2271 if (on || off) {
2272 SystemClock.sleep(300);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002273 } else {
Zhihai Xu40874a02012-10-08 17:57:03 -07002274 SystemClock.sleep(50);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002275 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002276 i++;
2277 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002278 Slog.e(TAG, "waitForOnOff time out");
Zhihai Xu40874a02012-10-08 17:57:03 -07002279 return false;
2280 }
Zhihai Xu681ae7f2012-11-12 15:14:18 -08002281
Jack He8caab152018-03-02 13:08:36 -08002282 private void sendDisableMsg(int reason, String packageName) {
Zhihai Xu401202b2012-12-03 11:36:21 -08002283 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
Jack He8caab152018-03-02 13:08:36 -08002284 addActiveLog(reason, packageName, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08002285 }
2286
Jack He8caab152018-03-02 13:08:36 -08002287 private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002288 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
Jack He8caab152018-03-02 13:08:36 -08002289 addActiveLog(reason, packageName, true);
Marie Janssen12a35012017-06-26 07:21:03 -07002290 mLastEnabledTime = SystemClock.elapsedRealtime();
Marie Janssen59804562016-12-28 14:13:21 -08002291 }
2292
Jack He8caab152018-03-02 13:08:36 -08002293 private void addActiveLog(int reason, String packageName, boolean enable) {
Marie Janssen59804562016-12-28 14:13:21 -08002294 synchronized (mActiveLogs) {
Marie Janssene54b4222017-03-16 18:10:59 -07002295 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
Marie Janssen59804562016-12-28 14:13:21 -08002296 mActiveLogs.remove();
2297 }
Jack He8caab152018-03-02 13:08:36 -08002298 mActiveLogs.add(
2299 new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
Marie Janssen59804562016-12-28 14:13:21 -08002300 }
Tej Singhd8e7cc62018-03-22 18:30:31 +00002301
Muhammad Qureshie2b24322020-01-28 10:54:17 -08002302 int state = enable ? FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
2303 FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2304 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
Tej Singhd8e7cc62018-03-22 18:30:31 +00002305 Binder.getCallingUid(), null, state, reason, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08002306 }
2307
Marie Janssene54b4222017-03-16 18:10:59 -07002308 private void addCrashLog() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002309 synchronized (mCrashTimestamps) {
2310 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
2311 mCrashTimestamps.removeFirst();
2312 }
2313 mCrashTimestamps.add(System.currentTimeMillis());
2314 mCrashes++;
2315 }
Marie Janssene54b4222017-03-16 18:10:59 -07002316 }
2317
Marie Janssen2977c3e2016-11-09 12:01:24 -08002318 private void recoverBluetoothServiceFromError(boolean clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002319 Slog.e(TAG, "recoverBluetoothServiceFromError");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002320 try {
2321 mBluetoothLock.readLock().lock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002322 if (mBluetooth != null) {
2323 //Unregister callback object
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002324 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002325 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002326 } catch (RemoteException re) {
2327 Slog.e(TAG, "Unable to unregister", re);
2328 } finally {
2329 mBluetoothLock.readLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002330 }
2331
2332 SystemClock.sleep(500);
2333
2334 // disable
Jack He8caab152018-03-02 13:08:36 -08002335 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
2336 mContext.getPackageName(), false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002337 handleDisable();
2338
2339 waitForOnOff(false, true);
2340
2341 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002342
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002343 try {
2344 mBluetoothLock.writeLock().lock();
2345 if (mBluetooth != null) {
2346 mBluetooth = null;
2347 // Unbind
2348 mContext.unbindService(mConnection);
2349 }
2350 mBluetoothGatt = null;
2351 } finally {
2352 mBluetoothLock.writeLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002353 }
2354
2355 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2356 mState = BluetoothAdapter.STATE_OFF;
2357
Marie Janssen2977c3e2016-11-09 12:01:24 -08002358 if (clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002359 clearBleApps();
Marie Janssen2977c3e2016-11-09 12:01:24 -08002360 }
2361
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002362 mEnable = false;
2363
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002364 // Send a Bluetooth Restart message to reenable bluetooth
2365 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
2366 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002367 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002368
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01002369 private boolean isBluetoothDisallowed() {
2370 long callingIdentity = Binder.clearCallingIdentity();
2371 try {
2372 return mContext.getSystemService(UserManager.class)
2373 .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2374 } finally {
2375 Binder.restoreCallingIdentity(callingIdentity);
2376 }
2377 }
2378
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002379 /**
2380 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002381 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2382 * state if Bluetooth is not disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002383 *
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002384 * @param userId user to disable bluetooth sharing for.
2385 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002386 */
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002387 private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002388 final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2389 "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002390 final int newState =
2391 bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2392 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002393 try {
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002394 final IPackageManager imp = AppGlobals.getPackageManager();
Myles Watson6291fae2017-06-29 03:12:02 -07002395 imp.setComponentEnabledSetting(oppLauncherComponent, newState,
2396 PackageManager.DONT_KILL_APP, userId);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002397 } catch (Exception e) {
2398 // The component was not found, do nothing.
2399 }
2400 }
2401
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002402 private int getServiceRestartMs() {
2403 return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
2404 }
2405
Mike Lockwood726d4de2014-10-28 14:06:28 -07002406 @Override
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002407 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002408 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
2409 return;
2410 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002411 String errorMsg = null;
Marie Janssen59804562016-12-28 14:13:21 -08002412
2413 boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
2414
2415 if (!protoOut) {
2416 writer.println("Bluetooth Status");
2417 writer.println(" enabled: " + isEnabled());
2418 writer.println(" state: " + BluetoothAdapter.nameForState(mState));
2419 writer.println(" address: " + mAddress);
2420 writer.println(" name: " + mName);
2421 if (mEnable) {
Marie Janssen12a35012017-06-26 07:21:03 -07002422 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002423 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
2424 (int) (onDuration / (1000 * 60 * 60)),
2425 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
2426 (int) (onDuration % 1000));
Andre Eisenbache66e1682017-04-10 13:49:13 -07002427 writer.println(" time since enabled: " + onDurationString);
Marie Janssen59804562016-12-28 14:13:21 -08002428 }
2429
Marie Janssena95924d2017-01-18 09:37:52 -08002430 if (mActiveLogs.size() == 0) {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002431 writer.println("\nBluetooth never enabled!");
Marie Janssena95924d2017-01-18 09:37:52 -08002432 } else {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002433 writer.println("\nEnable log:");
Marie Janssena95924d2017-01-18 09:37:52 -08002434 for (ActiveLog log : mActiveLogs) {
2435 writer.println(" " + log);
2436 }
Marie Janssen59804562016-12-28 14:13:21 -08002437 }
2438
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002439 writer.println(
2440 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2441 if (mCrashes == CRASH_LOG_MAX_SIZE) {
2442 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2443 }
Marie Janssene54b4222017-03-16 18:10:59 -07002444 for (Long time : mCrashTimestamps) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002445 writer.println(" " + timeToLog(time));
Marie Janssene54b4222017-03-16 18:10:59 -07002446 }
2447
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002448 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
2449 + "registered");
Marie Janssen59804562016-12-28 14:13:21 -08002450 for (ClientDeathRecipient app : mBleApps.values()) {
Marie Janssena95924d2017-01-18 09:37:52 -08002451 writer.println(" " + app.getPackageName());
Marie Janssen59804562016-12-28 14:13:21 -08002452 }
2453
Marie Janssena95924d2017-01-18 09:37:52 -08002454 writer.println("");
Marie Janssen59804562016-12-28 14:13:21 -08002455 writer.flush();
Marie Janssenf5ec5382017-01-03 11:37:38 -08002456 if (args.length == 0) {
Marie Janssena95924d2017-01-18 09:37:52 -08002457 // Add arg to produce output
2458 args = new String[1];
2459 args[0] = "--print";
Marie Janssenf5ec5382017-01-03 11:37:38 -08002460 }
Marie Janssen59804562016-12-28 14:13:21 -08002461 }
2462
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002463 if (mBluetoothBinder == null) {
2464 errorMsg = "Bluetooth Service not connected";
2465 } else {
2466 try {
2467 mBluetoothBinder.dump(fd, args);
2468 } catch (RemoteException re) {
Marie Janssen59804562016-12-28 14:13:21 -08002469 errorMsg = "RemoteException while dumping Bluetooth Service";
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002470 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002471 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002472 if (errorMsg != null) {
2473 // Silently return if we are extracting metrics in Protobuf format
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002474 if (protoOut) {
2475 return;
2476 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002477 writer.println(errorMsg);
2478 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002479 }
Jack He8caab152018-03-02 13:08:36 -08002480
2481 private static String getEnableDisableReasonString(int reason) {
2482 switch (reason) {
2483 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
2484 return "APPLICATION_REQUEST";
2485 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
2486 return "AIRPLANE_MODE";
2487 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
2488 return "DISALLOWED";
2489 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
2490 return "RESTARTED";
2491 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
2492 return "START_ERROR";
2493 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
2494 return "SYSTEM_BOOT";
2495 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
2496 return "CRASH";
2497 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
2498 return "USER_SWITCH";
2499 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
2500 return "RESTORE_USER_SETTING";
2501 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
2502 default: return "UNKNOWN[" + reason + "]";
2503 }
2504 }
fredc0f420372012-04-12 00:02:00 -07002505}