blob: a3188443591fbb1fb6cf716543b396871363c57f [file] [log] [blame]
fredc0f420372012-04-12 00:02:00 -07001/*
Zhihai Xufa0fd392012-10-23 17:31:56 -07002 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
fredc0f420372012-04-12 00:02:00 -070015 */
16
17package com.android.server;
18
Svet Ganov408abf72015-05-12 19:13:36 -070019import android.Manifest;
Zhihai Xu40874a02012-10-08 17:57:03 -070020import android.app.ActivityManager;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010021import android.app.AppGlobals;
Jack Hea80cead2019-04-23 20:00:18 -070022import android.app.AppOpsManager;
fredc0f420372012-04-12 00:02:00 -070023import android.bluetooth.BluetoothAdapter;
Benjamin Franze8b98922014-11-12 15:57:54 +000024import android.bluetooth.BluetoothProfile;
Jack He8caab152018-03-02 13:08:36 -080025import android.bluetooth.BluetoothProtoEnums;
fredc0f420372012-04-12 00:02:00 -070026import android.bluetooth.IBluetooth;
fredcbf072a72012-05-09 16:52:50 -070027import android.bluetooth.IBluetoothCallback;
Wei Wange4a744b2015-06-11 17:50:29 -070028import android.bluetooth.IBluetoothGatt;
Benjamin Franze8b98922014-11-12 15:57:54 +000029import android.bluetooth.IBluetoothHeadset;
fredc0f420372012-04-12 00:02:00 -070030import android.bluetooth.IBluetoothManager;
31import android.bluetooth.IBluetoothManagerCallback;
Benjamin Franze8b98922014-11-12 15:57:54 +000032import android.bluetooth.IBluetoothProfileServiceConnection;
fredc0f420372012-04-12 00:02:00 -070033import android.bluetooth.IBluetoothStateChangeCallback;
Svet Ganov77df6f32016-08-17 11:46:34 -070034import android.content.ActivityNotFoundException;
fredc0f420372012-04-12 00:02:00 -070035import android.content.BroadcastReceiver;
36import android.content.ComponentName;
37import android.content.ContentResolver;
38import android.content.Context;
39import android.content.Intent;
40import android.content.IntentFilter;
41import android.content.ServiceConnection;
Svetoslav Ganovac69be52016-06-29 17:31:44 -070042import android.content.pm.ApplicationInfo;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010043import android.content.pm.IPackageManager;
Matthew Xie32ab77b2013-05-08 19:26:57 -070044import android.content.pm.PackageManager;
Benjamin Franze8b98922014-11-12 15:57:54 +000045import android.content.pm.UserInfo;
Wei Wange4a744b2015-06-11 17:50:29 -070046import android.database.ContentObserver;
Zhihai Xu40874a02012-10-08 17:57:03 -070047import android.os.Binder;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010048import android.os.Bundle;
fredc0f420372012-04-12 00:02:00 -070049import android.os.Handler;
fredc0f420372012-04-12 00:02:00 -070050import android.os.IBinder;
Zhihai Xu40874a02012-10-08 17:57:03 -070051import android.os.Looper;
fredc0f420372012-04-12 00:02:00 -070052import android.os.Message;
Zhihai Xu40874a02012-10-08 17:57:03 -070053import android.os.Process;
fredcd6883532012-04-25 17:46:13 -070054import android.os.RemoteCallbackList;
fredc0f420372012-04-12 00:02:00 -070055import android.os.RemoteException;
Zhihai Xu40874a02012-10-08 17:57:03 -070056import android.os.SystemClock;
Stanley Tngfe8c8332018-06-19 08:48:10 -070057import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070058import android.os.UserHandle;
Benjamin Franze8b98922014-11-12 15:57:54 +000059import android.os.UserManager;
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +010060import android.os.UserManagerInternal;
61import android.os.UserManagerInternal.UserRestrictionsListener;
fredc0f420372012-04-12 00:02:00 -070062import android.provider.Settings;
Wei Wang67d84162015-04-26 17:04:29 -070063import android.provider.Settings.SettingNotFoundException;
Stanley Tngfe8c8332018-06-19 08:48:10 -070064import android.text.TextUtils;
65import android.util.FeatureFlagUtils;
66import android.util.Log;
Jeff Sharkey67609c72016-03-05 14:29:13 -070067import android.util.Slog;
Tej Singhd8e7cc62018-03-22 18:30:31 +000068import android.util.StatsLog;
Mike Lockwood726d4de2014-10-28 14:06:28 -070069
Arthur Hsuf3f95a92018-01-11 16:46:22 -080070import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060071import com.android.internal.util.DumpUtils;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010072import com.android.server.pm.UserRestrictionsUtils;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +010073
Mike Lockwood726d4de2014-10-28 14:06:28 -070074import java.io.FileDescriptor;
75import java.io.PrintWriter;
Benjamin Franze8b98922014-11-12 15:57:54 +000076import java.util.HashMap;
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +010077import java.util.ArrayList;
Marie Janssen59804562016-12-28 14:13:21 -080078import java.util.LinkedList;
Myles Watsonb5cd11a2017-11-27 16:42:11 -080079import java.util.Locale;
Benjamin Franze8b98922014-11-12 15:57:54 +000080import java.util.Map;
Chienyuan177156b2018-12-18 10:40:25 +080081import java.util.NoSuchElementException;
Pavel Grafov4f4f6f82017-03-28 13:44:04 +010082import java.util.concurrent.ConcurrentHashMap;
83import java.util.concurrent.locks.ReentrantReadWriteLock;
Miao Chou658bf2f2015-06-26 17:14:35 -070084
Marie Janssen59804562016-12-28 14:13:21 -080085
fredc0f420372012-04-12 00:02:00 -070086class BluetoothManagerService extends IBluetoothManager.Stub {
87 private static final String TAG = "BluetoothManagerService";
Pavlin Radoslavov41401112016-06-27 15:25:18 -070088 private static final boolean DBG = true;
fredc0f420372012-04-12 00:02:00 -070089
fredc0f420372012-04-12 00:02:00 -070090 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
91 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
Marie Janssene54b4222017-03-16 18:10:59 -070092
Myles Watsonb5cd11a2017-11-27 16:42:11 -080093 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
94 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
95 private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name";
Marie Janssene54b4222017-03-16 18:10:59 -070096
97 private static final int ACTIVE_LOG_MAX_SIZE = 20;
98 private static final int CRASH_LOG_MAX_SIZE = 100;
Marie Janssene54b4222017-03-16 18:10:59 -070099
fredc0f420372012-04-12 00:02:00 -0700100 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530101 //Maximum msec to wait for service restart
Ugo Yu1ff6fd32019-11-20 17:59:11 +0800102 private static final int SERVICE_RESTART_TIME_MS = 400;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800103 //Maximum msec to wait for restart due to error
104 private static final int ERROR_RESTART_TIME_MS = 3000;
Zhihai Xu40874a02012-10-08 17:57:03 -0700105 //Maximum msec to delay MESSAGE_USER_SWITCHED
106 private static final int USER_SWITCHED_TIME_MS = 200;
Benjamin Franze8b98922014-11-12 15:57:54 +0000107 // Delay for the addProxy function in msec
108 private static final int ADD_PROXY_DELAY_MS = 100;
fredc0f420372012-04-12 00:02:00 -0700109
110 private static final int MESSAGE_ENABLE = 1;
111 private static final int MESSAGE_DISABLE = 2;
fredc649fe492012-04-19 01:07:18 -0700112 private static final int MESSAGE_REGISTER_ADAPTER = 20;
113 private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
114 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
115 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
116 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
117 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +0530118 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700119 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
120 private static final int MESSAGE_TIMEOUT_BIND = 100;
121 private static final int MESSAGE_TIMEOUT_UNBIND = 101;
Ajay Panicker4bb48302016-03-31 14:14:27 -0700122 private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
Zhihai Xu40874a02012-10-08 17:57:03 -0700123 private static final int MESSAGE_USER_SWITCHED = 300;
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700124 private static final int MESSAGE_USER_UNLOCKED = 301;
Benjamin Franze8b98922014-11-12 15:57:54 +0000125 private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
126 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
Stanley Tng873b5702017-05-01 21:27:31 -0700127 private static final int MESSAGE_RESTORE_USER_SETTING = 500;
128
129 private static final int RESTORE_SETTING_TO_ON = 1;
130 private static final int RESTORE_SETTING_TO_OFF = 0;
Marie Janssencb21ad72016-12-13 10:51:02 -0800131
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -0700132 private static final int MAX_ERROR_RESTART_RETRIES = 6;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800133
Zhihai Xu401202b2012-12-03 11:36:21 -0800134 // Bluetooth persisted setting is off
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800135 private static final int BLUETOOTH_OFF = 0;
Zhihai Xu401202b2012-12-03 11:36:21 -0800136 // Bluetooth persisted setting is on
137 // and Airplane mode won't affect Bluetooth state at start up
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800138 private static final int BLUETOOTH_ON_BLUETOOTH = 1;
Zhihai Xu401202b2012-12-03 11:36:21 -0800139 // Bluetooth persisted setting is on
140 // but Airplane mode will affect Bluetooth state at start up
141 // and Airplane mode will have higher priority.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800142 private static final int BLUETOOTH_ON_AIRPLANE = 2;
fredc0f420372012-04-12 00:02:00 -0700143
Matthew Xieddf7e472013-03-01 18:41:02 -0800144 private static final int SERVICE_IBLUETOOTH = 1;
145 private static final int SERVICE_IBLUETOOTHGATT = 2;
146
fredc0f420372012-04-12 00:02:00 -0700147 private final Context mContext;
Matthew Xiecdce0b92012-07-12 19:06:15 -0700148
149 // Locks are not provided for mName and mAddress.
150 // They are accessed in handler or broadcast receiver, same thread context.
fredc0f420372012-04-12 00:02:00 -0700151 private String mAddress;
152 private String mName;
Matthew Xie6fde3092012-07-11 17:10:07 -0700153 private final ContentResolver mContentResolver;
154 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
155 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800156 private IBinder mBluetoothBinder;
fredc649fe492012-04-19 01:07:18 -0700157 private IBluetooth mBluetooth;
Matthew Xieddf7e472013-03-01 18:41:02 -0800158 private IBluetoothGatt mBluetoothGatt;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800159 private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
fredc649fe492012-04-19 01:07:18 -0700160 private boolean mBinding;
161 private boolean mUnbinding;
Marie Janssen59804562016-12-28 14:13:21 -0800162
Zhihai Xu401202b2012-12-03 11:36:21 -0800163 // used inside handler thread
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700164 private boolean mQuietEnable = false;
Marie Janssen59804562016-12-28 14:13:21 -0800165 private boolean mEnable;
166
Jack He8caab152018-03-02 13:08:36 -0800167 private static CharSequence timeToLog(long timestamp) {
Marie Janssene54b4222017-03-16 18:10:59 -0700168 return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
169 }
170
Marie Janssen59804562016-12-28 14:13:21 -0800171 /**
172 * Used for tracking apps that enabled / disabled Bluetooth.
173 */
174 private class ActiveLog {
Jack He8caab152018-03-02 13:08:36 -0800175 private int mReason;
Marie Janssen59804562016-12-28 14:13:21 -0800176 private String mPackageName;
177 private boolean mEnable;
178 private long mTimestamp;
179
Jack He8caab152018-03-02 13:08:36 -0800180 ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
181 mReason = reason;
Marie Janssen59804562016-12-28 14:13:21 -0800182 mPackageName = packageName;
183 mEnable = enable;
184 mTimestamp = timestamp;
185 }
186
Marie Janssen59804562016-12-28 14:13:21 -0800187 public String toString() {
Jack He8caab152018-03-02 13:08:36 -0800188 return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
189 + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
Marie Janssen59804562016-12-28 14:13:21 -0800190 }
191
192 }
193
Jack He8caab152018-03-02 13:08:36 -0800194 private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
195 private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
Marie Janssene54b4222017-03-16 18:10:59 -0700196 private int mCrashes;
Marie Janssen12a35012017-06-26 07:21:03 -0700197 private long mLastEnabledTime;
Marie Janssen59804562016-12-28 14:13:21 -0800198
199 // configuration from external IBinder call which is used to
Zhihai Xu401202b2012-12-03 11:36:21 -0800200 // synchronize with broadcast receiver.
201 private boolean mQuietEnableExternal;
Zhihai Xu401202b2012-12-03 11:36:21 -0800202 private boolean mEnableExternal;
Marie Janssen59804562016-12-28 14:13:21 -0800203
204 // Map of apps registered to keep BLE scanning on.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800205 private Map<IBinder, ClientDeathRecipient> mBleApps =
206 new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
Marie Janssen59804562016-12-28 14:13:21 -0800207
Zhihai Xu40874a02012-10-08 17:57:03 -0700208 private int mState;
Zhihai Xu40874a02012-10-08 17:57:03 -0700209 private final BluetoothHandler mHandler;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800210 private int mErrorRecoveryRetryCounter;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200211 private final int mSystemUiUid;
fredc0f420372012-04-12 00:02:00 -0700212
Stanley Tng61dbd812019-01-13 16:04:31 -0800213 private boolean mIsHearingAidProfileSupported;
214
Jack Hea80cead2019-04-23 20:00:18 -0700215 private AppOpsManager mAppOps;
216
Benjamin Franze8b98922014-11-12 15:57:54 +0000217 // Save a ProfileServiceConnections object for each of the bound
218 // bluetooth profile services
Jack He8caab152018-03-02 13:08:36 -0800219 private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
Benjamin Franze8b98922014-11-12 15:57:54 +0000220
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700221 private final boolean mWirelessConsentRequired;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700222
Marie Janssen59804562016-12-28 14:13:21 -0800223 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
fredcbf072a72012-05-09 16:52:50 -0700224 @Override
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800225 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
226 Message msg =
227 mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
fredcbf072a72012-05-09 16:52:50 -0700228 mHandler.sendMessage(msg);
229 }
230 };
231
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100232 private final UserRestrictionsListener mUserRestrictionsListener =
233 new UserRestrictionsListener() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800234 @Override
235 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
236 Bundle prevRestrictions) {
Myles Watson6291fae2017-06-29 03:12:02 -0700237
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800238 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
239 UserManager.DISALLOW_BLUETOOTH_SHARING)) {
240 updateOppLauncherComponentState(userId,
241 newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
242 }
Pavel Grafov4f4f6f82017-03-28 13:44:04 +0100243
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800244 // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
245 if (userId == UserHandle.USER_SYSTEM
246 && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
247 newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
248 if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
249 UserManager.DISALLOW_BLUETOOTH)) {
250 updateOppLauncherComponentState(userId, true); // Sharing disallowed
Jack He8caab152018-03-02 13:08:36 -0800251 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
252 mContext.getPackageName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800253 } else {
254 updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
255 UserManager.DISALLOW_BLUETOOTH_SHARING));
256 }
257 }
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100258 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800259 };
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100260
Ajay Panicker467bc042017-02-22 12:23:15 -0800261 private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
262 @Override
263 public void onChange(boolean unused) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800264 synchronized (this) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800265 if (isBluetoothPersistedStateOn()) {
266 if (isAirplaneModeOn()) {
267 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
268 } else {
269 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
270 }
271 }
272
273 int st = BluetoothAdapter.STATE_OFF;
274 try {
275 mBluetoothLock.readLock().lock();
276 if (mBluetooth != null) {
277 st = mBluetooth.getState();
278 }
279 } catch (RemoteException e) {
280 Slog.e(TAG, "Unable to call getState", e);
281 return;
282 } finally {
283 mBluetoothLock.readLock().unlock();
284 }
285
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800286 Slog.d(TAG,
287 "Airplane Mode change - current state: " + BluetoothAdapter.nameForState(
Rene Mayrhofer7d6c8e52018-11-28 11:32:40 -0800288 st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
Ajay Panicker467bc042017-02-22 12:23:15 -0800289
290 if (isAirplaneModeOn()) {
291 // Clear registered LE apps to force shut-off
292 clearBleApps();
293
294 // If state is BLE_ON make sure we trigger disableBLE
295 if (st == BluetoothAdapter.STATE_BLE_ON) {
296 try {
297 mBluetoothLock.readLock().lock();
298 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700299 addActiveLog(
300 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
301 mContext.getPackageName(), false);
Ajay Panicker467bc042017-02-22 12:23:15 -0800302 mBluetooth.onBrEdrDown();
303 mEnable = false;
304 mEnableExternal = false;
305 }
306 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800307 Slog.e(TAG, "Unable to call onBrEdrDown", e);
Ajay Panicker467bc042017-02-22 12:23:15 -0800308 } finally {
309 mBluetoothLock.readLock().unlock();
310 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800311 } else if (st == BluetoothAdapter.STATE_ON) {
Jack He8caab152018-03-02 13:08:36 -0800312 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
313 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800314 }
315 } else if (mEnableExternal) {
Jack He8caab152018-03-02 13:08:36 -0800316 sendEnableMsg(mQuietEnableExternal,
317 BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
318 mContext.getPackageName());
Ajay Panicker467bc042017-02-22 12:23:15 -0800319 }
320 }
321 }
322 };
323
fredcbf072a72012-05-09 16:52:50 -0700324 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
fredc0f420372012-04-12 00:02:00 -0700325 @Override
326 public void onReceive(Context context, Intent intent) {
327 String action = intent.getAction();
fredcbf072a72012-05-09 16:52:50 -0700328 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
fredc0f420372012-04-12 00:02:00 -0700329 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800330 if (DBG) {
331 Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
332 }
fredc0f420372012-04-12 00:02:00 -0700333 if (newName != null) {
334 storeNameAndAddress(newName, null);
335 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700336 } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
337 String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
338 if (newAddress != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800339 if (DBG) {
340 Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
341 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700342 storeNameAndAddress(null, newAddress);
343 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800344 if (DBG) {
345 Slog.e(TAG, "No Bluetooth Adapter address parameter found");
346 }
Stanley Tngdd749b02017-04-17 22:35:45 -0700347 }
Stanley Tng873b5702017-05-01 21:27:31 -0700348 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
349 final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
350 if (Settings.Global.BLUETOOTH_ON.equals(name)) {
351 // The Bluetooth On state may be changed during system restore.
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800352 final String prevValue =
353 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
354 final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
Stanley Tng873b5702017-05-01 21:27:31 -0700355
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800356 if (DBG) {
357 Slog.d(TAG,
358 "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue
359 + ", newValue=" + newValue);
360 }
Stanley Tng873b5702017-05-01 21:27:31 -0700361
362 if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
363 Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800364 newValue.equals("0") ? RESTORE_SETTING_TO_OFF
365 : RESTORE_SETTING_TO_ON, 0);
Stanley Tng873b5702017-05-01 21:27:31 -0700366 mHandler.sendMessage(msg);
367 }
368 }
fredc0f420372012-04-12 00:02:00 -0700369 }
370 }
371 };
372
373 BluetoothManagerService(Context context) {
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700374 mHandler = new BluetoothHandler(IoThread.get().getLooper());
Zhihai Xu40874a02012-10-08 17:57:03 -0700375
fredc0f420372012-04-12 00:02:00 -0700376 mContext = context;
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700377
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700378 mWirelessConsentRequired = context.getResources()
379 .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700380
Marie Janssene54b4222017-03-16 18:10:59 -0700381 mCrashes = 0;
fredc0f420372012-04-12 00:02:00 -0700382 mBluetooth = null;
Marie Janssen9db28eb2016-01-12 16:05:15 -0800383 mBluetoothBinder = null;
Nitin Arorad055adb2015-03-02 15:03:51 -0800384 mBluetoothGatt = null;
fredc0f420372012-04-12 00:02:00 -0700385 mBinding = false;
386 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -0700387 mEnable = false;
388 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800389 mQuietEnableExternal = false;
390 mEnableExternal = false;
fredc0f420372012-04-12 00:02:00 -0700391 mAddress = null;
392 mName = null;
Zhihai Xudd9d17d2013-01-08 17:05:58 -0800393 mErrorRecoveryRetryCounter = 0;
fredc0f420372012-04-12 00:02:00 -0700394 mContentResolver = context.getContentResolver();
Wei Wange4a744b2015-06-11 17:50:29 -0700395 // Observe BLE scan only mode settings change.
396 registerForBleScanModeChange();
fredcd6883532012-04-25 17:46:13 -0700397 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
398 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
Stanley Tng873b5702017-05-01 21:27:31 -0700399
Stanley Tng61dbd812019-01-13 16:04:31 -0800400 mIsHearingAidProfileSupported = context.getResources()
401 .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);
402
Stanley Tngfe8c8332018-06-19 08:48:10 -0700403 // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
Stanley Tngfe8c8332018-06-19 08:48:10 -0700404 String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
405 if (!TextUtils.isEmpty(value)) {
Stanley Tng61dbd812019-01-13 16:04:31 -0800406 boolean isHearingAidEnabled = Boolean.parseBoolean(value);
Stanley Tngfe8c8332018-06-19 08:48:10 -0700407 Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
408 FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
Stanley Tng61dbd812019-01-13 16:04:31 -0800409 if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
410 // Overwrite to enable support by FeatureFlag
411 mIsHearingAidProfileSupported = true;
412 }
Stanley Tngfe8c8332018-06-19 08:48:10 -0700413 }
414
Stanley Tng873b5702017-05-01 21:27:31 -0700415 IntentFilter filter = new IntentFilter();
416 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
417 filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
418 filter.addAction(Intent.ACTION_SETTING_RESTORED);
Dianne Hackbornd83a0962014-05-02 16:28:33 -0700419 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Matthew Xie6fde3092012-07-11 17:10:07 -0700420 mContext.registerReceiver(mReceiver, filter);
Stanley Tng873b5702017-05-01 21:27:31 -0700421
fredc0f420372012-04-12 00:02:00 -0700422 loadStoredNameAndAddress();
Zhihai Xu401202b2012-12-03 11:36:21 -0800423 if (isBluetoothPersistedStateOn()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800424 if (DBG) {
425 Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
426 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800427 mEnableExternal = true;
fredc0f420372012-04-12 00:02:00 -0700428 }
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200429
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800430 String airplaneModeRadios =
431 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
432 if (airplaneModeRadios == null || airplaneModeRadios.contains(
433 Settings.Global.RADIO_BLUETOOTH)) {
Ajay Panicker467bc042017-02-22 12:23:15 -0800434 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800435 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
436 mAirplaneModeObserver);
Ajay Panicker467bc042017-02-22 12:23:15 -0800437 }
438
Marie Janssen59804562016-12-28 14:13:21 -0800439 int systemUiUid = -1;
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200440 try {
Arthur Hsuf3f95a92018-01-11 16:46:22 -0800441 // Check if device is configured with no home screen, which implies no SystemUI.
442 boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
443 if (!noHome) {
444 systemUiUid = mContext.getPackageManager()
445 .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
446 UserHandle.USER_SYSTEM);
447 }
448 Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200449 } catch (PackageManager.NameNotFoundException e) {
Joe LaPennaacddf2b2015-09-04 12:52:42 -0700450 // Some platforms, such as wearables do not have a system ui.
Jeff Sharkey67609c72016-03-05 14:29:13 -0700451 Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
Adrian Roosbd9a9a52014-08-18 15:31:57 +0200452 }
Marie Janssen59804562016-12-28 14:13:21 -0800453 mSystemUiUid = systemUiUid;
fredc0f420372012-04-12 00:02:00 -0700454 }
455
fredc649fe492012-04-19 01:07:18 -0700456 /**
457 * Returns true if airplane mode is currently on
458 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800459 private boolean isAirplaneModeOn() {
Christopher Tatec09cdce2012-09-10 16:50:14 -0700460 return Settings.Global.getInt(mContext.getContentResolver(),
461 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
fredc649fe492012-04-19 01:07:18 -0700462 }
463
Arthur Hsu2433baf2018-01-11 11:05:11 -0800464 private boolean supportBluetoothPersistedState() {
465 return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
466 }
467
fredc649fe492012-04-19 01:07:18 -0700468 /**
469 * Returns true if the Bluetooth saved state is "on"
470 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800471 private boolean isBluetoothPersistedStateOn() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800472 if (!supportBluetoothPersistedState()) {
473 return false;
474 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800475 int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
476 if (DBG) {
477 Slog.d(TAG, "Bluetooth persisted state: " + state);
478 }
Marie Janssen9fa24912016-10-18 10:04:24 -0700479 return state != BLUETOOTH_OFF;
Zhihai Xu401202b2012-12-03 11:36:21 -0800480 }
481
482 /**
483 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
484 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800485 private boolean isBluetoothPersistedStateOnBluetooth() {
Arthur Hsu2433baf2018-01-11 11:05:11 -0800486 if (!supportBluetoothPersistedState()) {
487 return false;
488 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800489 return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
490 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
fredc649fe492012-04-19 01:07:18 -0700491 }
492
493 /**
494 * Save the Bluetooth on/off state
fredc649fe492012-04-19 01:07:18 -0700495 */
Zhihai Xu401202b2012-12-03 11:36:21 -0800496 private void persistBluetoothSetting(int value) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800497 if (DBG) {
498 Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
499 }
Marie Janssenfa630682016-12-15 13:51:30 -0800500 // waive WRITE_SECURE_SETTINGS permission check
501 long callingIdentity = Binder.clearCallingIdentity();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800502 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value);
Marie Janssenfa630682016-12-15 13:51:30 -0800503 Binder.restoreCallingIdentity(callingIdentity);
fredc649fe492012-04-19 01:07:18 -0700504 }
505
506 /**
507 * Returns true if the Bluetooth Adapter's name and address is
508 * locally cached
509 * @return
510 */
fredc0f420372012-04-12 00:02:00 -0700511 private boolean isNameAndAddressSet() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800512 return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
fredc0f420372012-04-12 00:02:00 -0700513 }
514
fredc649fe492012-04-19 01:07:18 -0700515 /**
516 * Retrieve the Bluetooth Adapter's name and address and save it in
517 * in the local cache
518 */
fredc0f420372012-04-12 00:02:00 -0700519 private void loadStoredNameAndAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800520 if (DBG) {
521 Slog.d(TAG, "Loading stored name and address");
522 }
523 if (mContext.getResources()
524 .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
525 && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0)
526 == 0) {
Zhihai Xud31c3222012-10-31 16:08:57 -0700527 // if the valid flag is not set, don't load the address and name
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800528 if (DBG) {
529 Slog.d(TAG, "invalid bluetooth name and address stored");
530 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700531 return;
532 }
fredc0f420372012-04-12 00:02:00 -0700533 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
534 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800535 if (DBG) {
536 Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
537 }
fredc0f420372012-04-12 00:02:00 -0700538 }
539
fredc649fe492012-04-19 01:07:18 -0700540 /**
541 * Save the Bluetooth name and address in the persistent store.
542 * Only non-null values will be saved.
543 * @param name
544 * @param address
545 */
fredc0f420372012-04-12 00:02:00 -0700546 private void storeNameAndAddress(String name, String address) {
547 if (name != null) {
548 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
fredc0f420372012-04-12 00:02:00 -0700549 mName = name;
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800550 if (DBG) {
551 Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver,
552 SECURE_SETTINGS_BLUETOOTH_NAME));
553 }
fredc0f420372012-04-12 00:02:00 -0700554 }
555
556 if (address != null) {
557 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800558 mAddress = address;
559 if (DBG) {
560 Slog.d(TAG,
561 "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver,
562 SECURE_SETTINGS_BLUETOOTH_ADDRESS));
563 }
fredc0f420372012-04-12 00:02:00 -0700564 }
Zhihai Xud31c3222012-10-31 16:08:57 -0700565
566 if ((name != null) && (address != null)) {
567 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
568 }
fredc0f420372012-04-12 00:02:00 -0700569 }
570
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800571 public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700572 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700573 Slog.w(TAG, "Callback is null in registerAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700574 return null;
575 }
fredc0f420372012-04-12 00:02:00 -0700576 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
577 msg.obj = callback;
578 mHandler.sendMessage(msg);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700579
580 return mBluetooth;
fredc0f420372012-04-12 00:02:00 -0700581 }
582
583 public void unregisterAdapter(IBluetoothManagerCallback callback) {
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700584 if (callback == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700585 Slog.w(TAG, "Callback is null in unregisterAdapter");
Natalie Silvanovich55db6462014-05-01 16:12:23 -0700586 return;
587 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800588 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
fredc0f420372012-04-12 00:02:00 -0700589 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
590 msg.obj = callback;
591 mHandler.sendMessage(msg);
592 }
593
594 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800595 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800596 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800597 Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
598 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800599 }
fredc0f420372012-04-12 00:02:00 -0700600 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
601 msg.obj = callback;
602 mHandler.sendMessage(msg);
603 }
604
605 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800606 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Marie Janssencb21ad72016-12-13 10:51:02 -0800607 if (callback == null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800608 Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
609 return;
Marie Janssencb21ad72016-12-13 10:51:02 -0800610 }
fredc0f420372012-04-12 00:02:00 -0700611 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
612 msg.obj = callback;
613 mHandler.sendMessage(msg);
614 }
615
616 public boolean isEnabled() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800617 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
618 Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user");
Zhihai Xu40874a02012-10-08 17:57:03 -0700619 return false;
620 }
621
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700622 try {
623 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800624 if (mBluetooth != null) {
625 return mBluetooth.isEnabled();
626 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700627 } catch (RemoteException e) {
628 Slog.e(TAG, "isEnabled()", e);
629 } finally {
630 mBluetoothLock.readLock().unlock();
fredc0f420372012-04-12 00:02:00 -0700631 }
632 return false;
633 }
634
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700635 public int getState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800636 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
Marie Janssencb21ad72016-12-13 10:51:02 -0800637 Slog.w(TAG, "getState(): report OFF for non-active and non system user");
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700638 return BluetoothAdapter.STATE_OFF;
639 }
640
641 try {
642 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800643 if (mBluetooth != null) {
644 return mBluetooth.getState();
645 }
Christine Hallstrom995c90a2016-05-25 15:49:08 -0700646 } catch (RemoteException e) {
647 Slog.e(TAG, "getState()", e);
648 } finally {
649 mBluetoothLock.readLock().unlock();
650 }
651 return BluetoothAdapter.STATE_OFF;
652 }
653
Nitin Arorad055adb2015-03-02 15:03:51 -0800654 class ClientDeathRecipient implements IBinder.DeathRecipient {
Marie Janssen59804562016-12-28 14:13:21 -0800655 private String mPackageName;
656
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800657 ClientDeathRecipient(String packageName) {
Marie Janssen59804562016-12-28 14:13:21 -0800658 mPackageName = packageName;
659 }
660
Nitin Arorad055adb2015-03-02 15:03:51 -0800661 public void binderDied() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800662 if (DBG) {
663 Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
Marie Janssen2977c3e2016-11-09 12:01:24 -0800664 }
Stanley Tng2c5fd282018-03-19 13:06:45 -0700665
666 for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
667 IBinder token = entry.getKey();
668 ClientDeathRecipient deathRec = entry.getValue();
669 if (deathRec.equals(this)) {
Stanley Tng600109c2018-03-20 16:54:27 -0700670 updateBleAppCount(token, false, mPackageName);
Stanley Tng2c5fd282018-03-19 13:06:45 -0700671 break;
672 }
673 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800674 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800675
Marie Janssen59804562016-12-28 14:13:21 -0800676 public String getPackageName() {
677 return mPackageName;
678 }
679 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800680
Wei Wang67d84162015-04-26 17:04:29 -0700681 @Override
682 public boolean isBleScanAlwaysAvailable() {
Marie Janssena80d7452016-10-25 10:47:51 -0700683 if (isAirplaneModeOn() && !mEnable) {
684 return false;
685 }
Wei Wang67d84162015-04-26 17:04:29 -0700686 try {
Jack He8caab152018-03-02 13:08:36 -0800687 return Settings.Global.getInt(mContentResolver,
688 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
Wei Wang67d84162015-04-26 17:04:29 -0700689 } catch (SettingNotFoundException e) {
690 }
691 return false;
692 }
693
Stanley Tng61dbd812019-01-13 16:04:31 -0800694 @Override
695 public boolean isHearingAidProfileSupported() {
696 return mIsHearingAidProfileSupported;
697 }
698
Jakub Pawlowski3f0ce982019-11-29 22:11:11 +0100699 @Override
700 /** @hide */
701 public java.util.List<String> getSystemConfigEnabledProfilesForPackage(String packageName) {
702 if (Binder.getCallingUid() != Process.BLUETOOTH_UID) {
703 Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth");
704 return null;
705 }
706
707 SystemConfig systemConfig = SystemConfig.getInstance();
708 if (systemConfig == null) {
709 return null;
710 }
711
712 android.util.ArrayMap<String, Boolean> componentEnabledStates =
713 systemConfig.getComponentsEnabledStates(packageName);
714 if (componentEnabledStates == null) {
715 return null;
716 }
717
718 ArrayList enabledProfiles = new ArrayList<String>();
719 for (Map.Entry<String, Boolean> entry : componentEnabledStates.entrySet()) {
720 if (entry.getValue()) {
721 enabledProfiles.add(entry.getKey());
722 }
723 }
724
725 return enabledProfiles;
726 }
727
Wei Wange4a744b2015-06-11 17:50:29 -0700728 // Monitor change of BLE scan only mode settings.
729 private void registerForBleScanModeChange() {
730 ContentObserver contentObserver = new ContentObserver(null) {
731 @Override
732 public void onChange(boolean selfChange) {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800733 if (isBleScanAlwaysAvailable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800734 // Nothing to do
735 return;
Marie Janssen2977c3e2016-11-09 12:01:24 -0800736 }
737 // BLE scan is not available.
738 disableBleScanMode();
739 clearBleApps();
740 try {
741 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800742 if (mBluetooth != null) {
Hansong Zhang276eb1b2018-04-23 11:17:17 -0700743 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
744 mContext.getPackageName(), false);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800745 mBluetooth.onBrEdrDown();
746 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800747 } catch (RemoteException e) {
748 Slog.e(TAG, "error when disabling bluetooth", e);
749 } finally {
750 mBluetoothLock.readLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700751 }
752 }
753 };
754
755 mContentResolver.registerContentObserver(
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800756 Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
757 contentObserver);
Wei Wange4a744b2015-06-11 17:50:29 -0700758 }
759
760 // Disable ble scan only mode.
761 private void disableBleScanMode() {
762 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700763 mBluetoothLock.writeLock().lock();
Wei Wange4a744b2015-06-11 17:50:29 -0700764 if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800765 if (DBG) {
766 Slog.d(TAG, "Reseting the mEnable flag for clean disable");
767 }
Wei Wange4a744b2015-06-11 17:50:29 -0700768 mEnable = false;
769 }
770 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700771 Slog.e(TAG, "getState()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700772 } finally {
773 mBluetoothLock.writeLock().unlock();
Wei Wange4a744b2015-06-11 17:50:29 -0700774 }
775 }
776
Marie Janssen59804562016-12-28 14:13:21 -0800777 public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
Jack Hea80cead2019-04-23 20:00:18 -0700778 // Check if packageName belongs to callingUid
779 final int callingUid = Binder.getCallingUid();
780 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
781 if (!isCallerSystem) {
782 checkPackage(callingUid, packageName);
783 }
Marie Janssen59804562016-12-28 14:13:21 -0800784 ClientDeathRecipient r = mBleApps.get(token);
785 if (r == null && enable) {
786 ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
787 try {
788 token.linkToDeath(deathRec, 0);
789 } catch (RemoteException ex) {
790 throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
Nitin Arorad055adb2015-03-02 15:03:51 -0800791 }
Marie Janssen59804562016-12-28 14:13:21 -0800792 mBleApps.put(token, deathRec);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800793 if (DBG) {
794 Slog.d(TAG, "Registered for death of " + packageName);
795 }
Marie Janssen59804562016-12-28 14:13:21 -0800796 } else if (!enable && r != null) {
797 // Unregister death recipient as the app goes away.
798 token.unlinkToDeath(r, 0);
799 mBleApps.remove(token);
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800800 if (DBG) {
801 Slog.d(TAG, "Unregistered for death of " + packageName);
802 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800803 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800804 int appCount = mBleApps.size();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800805 if (DBG) {
806 Slog.d(TAG, appCount + " registered Ble Apps");
807 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800808 if (appCount == 0 && mEnable) {
Wei Wange4a744b2015-06-11 17:50:29 -0700809 disableBleScanMode();
Nitin Arorad055adb2015-03-02 15:03:51 -0800810 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800811 if (appCount == 0 && !mEnableExternal) {
812 sendBrEdrDownCallback();
813 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800814 return appCount;
Nitin Arorad055adb2015-03-02 15:03:51 -0800815 }
816
Wei Wange4a744b2015-06-11 17:50:29 -0700817 // Clear all apps using BLE scan only mode.
818 private void clearBleApps() {
Marie Janssen2977c3e2016-11-09 12:01:24 -0800819 mBleApps.clear();
Wei Wange4a744b2015-06-11 17:50:29 -0700820 }
821
Marie Janssen59804562016-12-28 14:13:21 -0800822 /** @hide */
Nitin Arorad055adb2015-03-02 15:03:51 -0800823 public boolean isBleAppPresent() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800824 if (DBG) {
825 Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
826 }
Marie Janssen2977c3e2016-11-09 12:01:24 -0800827 return mBleApps.size() > 0;
Nitin Arorad055adb2015-03-02 15:03:51 -0800828 }
829
830 /**
Myles Watson304ebf22018-05-11 08:47:24 -0700831 * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
Nitin Arorad055adb2015-03-02 15:03:51 -0800832 */
Myles Watson304ebf22018-05-11 08:47:24 -0700833 private void continueFromBleOnState() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800834 if (DBG) {
Myles Watson304ebf22018-05-11 08:47:24 -0700835 Slog.d(TAG, "continueFromBleOnState()");
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800836 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700837 try {
838 mBluetoothLock.readLock().lock();
Marie Janssenfa630682016-12-15 13:51:30 -0800839 if (mBluetooth == null) {
Myles Watson304ebf22018-05-11 08:47:24 -0700840 Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
Marie Janssenfa630682016-12-15 13:51:30 -0800841 return;
842 }
843 if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
844 // This triggers transition to STATE_ON
Nitin Arorad055adb2015-03-02 15:03:51 -0800845 mBluetooth.onLeServiceUp();
Nitin Arorad055adb2015-03-02 15:03:51 -0800846 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Nitin Arorad055adb2015-03-02 15:03:51 -0800847 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700848 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800849 Slog.e(TAG, "Unable to call onServiceUp", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700850 } finally {
851 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800852 }
853 }
854
855 /**
856 * Inform BluetoothAdapter instances that BREDR part is down
857 * and turn off all service and stack if no LE app needs it
858 */
859 private void sendBrEdrDownCallback() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800860 if (DBG) {
861 Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
862 }
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700863
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700864 if (mBluetooth == null) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700865 Slog.w(TAG, "Bluetooth handle is null");
Nitin Arorabdfaa7f2015-04-29 12:35:03 -0700866 return;
867 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800868
Martin Brabhamc2b06222017-02-27 16:55:07 -0800869 if (isBleAppPresent()) {
870 // Need to stay at BLE ON. Disconnect all Gatt connections
871 try {
872 mBluetoothGatt.unregAll();
873 } catch (RemoteException e) {
874 Slog.e(TAG, "Unable to disconnect all apps.", e);
875 }
876 } else {
Nitin Arorad055adb2015-03-02 15:03:51 -0800877 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700878 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800879 if (mBluetooth != null) {
880 mBluetooth.onBrEdrDown();
881 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700882 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -0700883 Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700884 } finally {
885 mBluetoothLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -0800886 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800887 }
Martin Brabhamc2b06222017-02-27 16:55:07 -0800888
Nitin Arorad055adb2015-03-02 15:03:51 -0800889 }
890
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800891 public boolean enableNoAutoConnect(String packageName) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100892 if (isBluetoothDisallowed()) {
893 if (DBG) {
894 Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
895 }
896 return false;
897 }
898
Jack Hea80cead2019-04-23 20:00:18 -0700899 // Check if packageName belongs to callingUid
900 final int callingUid = Binder.getCallingUid();
901 final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
902 if (!isCallerSystem) {
903 checkPackage(callingUid, packageName);
904 }
905
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700906 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800907 "Need BLUETOOTH ADMIN permission");
Zhihai Xu40874a02012-10-08 17:57:03 -0700908
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700909 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800910 Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = "
911 + mBinding);
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700912 }
Jack Hea80cead2019-04-23 20:00:18 -0700913 int callingAppId = UserHandle.getAppId(callingUid);
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800914
915 if (callingAppId != Process.NFC_UID) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700916 throw new SecurityException("no permission to enable Bluetooth quietly");
917 }
Martijn Coenen8385c5a2012-11-29 10:14:16 -0800918
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800919 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800920 mQuietEnableExternal = true;
921 mEnableExternal = true;
Jack He8caab152018-03-02 13:08:36 -0800922 sendEnableMsg(true,
923 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800924 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700925 return true;
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -0700926 }
Ajay Panicker4bb48302016-03-31 14:14:27 -0700927
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700928 public boolean enable(String packageName) throws RemoteException {
929 final int callingUid = Binder.getCallingUid();
930 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
931
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100932 if (isBluetoothDisallowed()) {
933 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800934 Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +0100935 }
936 return false;
937 }
938
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700939 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700940 // Check if packageName belongs to callingUid
941 checkPackage(callingUid, packageName);
942
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700943 if (!checkIfCallerIsForegroundUser()) {
944 Slog.w(TAG, "enable(): not allowed for non-active and non system user");
945 return false;
946 }
947
948 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
949 "Need BLUETOOTH ADMIN permission");
950
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700951 if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800952 callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700953 return false;
954 }
fredcf2458862012-04-16 15:18:27 -0700955 }
956
Zhihai Xu401202b2012-12-03 11:36:21 -0800957 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800958 Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
959 + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
Sanket Agarwal090bf552016-04-21 14:10:55 -0700960 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800961
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800962 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -0800963 mQuietEnableExternal = false;
964 mEnableExternal = true;
965 // waive WRITE_SECURE_SETTINGS permission check
Jack He8caab152018-03-02 13:08:36 -0800966 sendEnableMsg(false,
967 BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -0800968 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800969 if (DBG) {
970 Slog.d(TAG, "enable returning");
971 }
Zhihai Xu401202b2012-12-03 11:36:21 -0800972 return true;
fredc0f420372012-04-12 00:02:00 -0700973 }
974
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700975 public boolean disable(String packageName, boolean persist) throws RemoteException {
976 final int callingUid = Binder.getCallingUid();
977 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
Zhihai Xu40874a02012-10-08 17:57:03 -0700978
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700979 if (!callerSystem) {
Jack Hea80cead2019-04-23 20:00:18 -0700980 // Check if packageName belongs to callingUid
981 checkPackage(callingUid, packageName);
982
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700983 if (!checkIfCallerIsForegroundUser()) {
984 Slog.w(TAG, "disable(): not allowed for non-active and non system user");
985 return false;
986 }
987
988 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
989 "Need BLUETOOTH ADMIN permission");
990
Philip P. Moltmann6c644e62018-07-18 15:41:24 -0700991 if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800992 callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700993 return false;
994 }
Zhihai Xu40874a02012-10-08 17:57:03 -0700995 }
996
fredcf2458862012-04-16 15:18:27 -0700997 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -0800998 Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
Matthew Xiecdce0b92012-07-12 19:06:15 -0700999 }
fredcf2458862012-04-16 15:18:27 -07001000
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001001 synchronized (mReceiver) {
Zhihai Xu401202b2012-12-03 11:36:21 -08001002 if (persist) {
Zhihai Xu401202b2012-12-03 11:36:21 -08001003 persistBluetoothSetting(BLUETOOTH_OFF);
Zhihai Xu401202b2012-12-03 11:36:21 -08001004 }
1005 mEnableExternal = false;
Jack He8caab152018-03-02 13:08:36 -08001006 sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
1007 packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08001008 }
fredc0f420372012-04-12 00:02:00 -07001009 return true;
1010 }
1011
baishengf62d8692018-01-25 18:07:24 +08001012 private boolean startConsentUiIfNeeded(String packageName,
1013 int callingUid, String intentAction) throws RemoteException {
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001014 if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
baishengf62d8692018-01-25 18:07:24 +08001015 return false;
1016 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001017 try {
1018 // Validate the package only if we are going to use it
1019 ApplicationInfo applicationInfo = mContext.getPackageManager()
1020 .getApplicationInfoAsUser(packageName,
1021 PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
1022 UserHandle.getUserId(callingUid));
1023 if (applicationInfo.uid != callingUid) {
baishengf62d8692018-01-25 18:07:24 +08001024 throw new SecurityException("Package " + packageName
1025 + " not in uid " + callingUid);
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001026 }
1027
Ivan Podogovd2d32b12016-12-05 16:46:52 +00001028 Intent intent = new Intent(intentAction);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001029 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001030 intent.setFlags(
1031 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Ivan Podogov1ab87252017-01-03 12:02:18 +00001032 try {
1033 mContext.startActivity(intent);
1034 } catch (ActivityNotFoundException e) {
1035 // Shouldn't happen
1036 Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
1037 return false;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001038 }
Ivan Podogov1ab87252017-01-03 12:02:18 +00001039 return true;
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001040 } catch (PackageManager.NameNotFoundException e) {
1041 throw new RemoteException(e.getMessage());
1042 }
Svetoslav Ganovac69be52016-06-29 17:31:44 -07001043 }
1044
baishengf62d8692018-01-25 18:07:24 +08001045 /**
Jack Hea80cead2019-04-23 20:00:18 -07001046 * Check if AppOpsManager is available and the packageName belongs to uid
1047 *
1048 * A null package belongs to any uid
1049 */
1050 private void checkPackage(int uid, String packageName) {
1051 if (mAppOps == null) {
1052 Slog.w(TAG, "checkPackage(): called before system boot up, uid "
1053 + uid + ", packageName " + packageName);
1054 throw new IllegalStateException("System has not boot yet");
1055 }
1056 if (packageName == null) {
1057 Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
1058 return;
1059 }
1060 try {
1061 mAppOps.checkPackage(uid, packageName);
1062 } catch (SecurityException e) {
1063 Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
Jack Hea80cead2019-04-23 20:00:18 -07001064 throw new SecurityException(e.getMessage());
1065 }
1066 }
1067
1068 /**
baishengf62d8692018-01-25 18:07:24 +08001069 * Check if the caller must still pass permission check or if the caller is exempted
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001070 * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
baishengf62d8692018-01-25 18:07:24 +08001071 *
1072 * Commands from some callers may be exempted from triggering the consent UI when
1073 * enabling bluetooth. This exemption is checked via the
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001074 * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
baishengf62d8692018-01-25 18:07:24 +08001075 * the consent UI where it may otherwise be required.
1076 *
1077 * @hide
1078 */
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001079 private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
baishengf62d8692018-01-25 18:07:24 +08001080 int result = mContext.checkCallingPermission(
Philip P. Moltmann6c644e62018-07-18 15:41:24 -07001081 android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
baishengf62d8692018-01-25 18:07:24 +08001082 return result == PackageManager.PERMISSION_GRANTED;
1083 }
1084
fredc649fe492012-04-19 01:07:18 -07001085 public void unbindAndFinish() {
fredcf2458862012-04-16 15:18:27 -07001086 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001087 Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
1088 + " mUnbinding = " + mUnbinding);
fredcf2458862012-04-16 15:18:27 -07001089 }
1090
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001091 try {
1092 mBluetoothLock.writeLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001093 if (mUnbinding) {
1094 return;
1095 }
fredc0f420372012-04-12 00:02:00 -07001096 mUnbinding = true;
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001097 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
Pavlin Radoslavov74f60c02016-09-21 17:28:11 -07001098 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
Zhihai Xu40874a02012-10-08 17:57:03 -07001099 if (mBluetooth != null) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001100 //Unregister callback object
1101 try {
1102 mBluetooth.unregisterCallback(mBluetoothCallback);
1103 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001104 Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001105 }
Marie Janssen9db28eb2016-01-12 16:05:15 -08001106 mBluetoothBinder = null;
fredcd6883532012-04-25 17:46:13 -07001107 mBluetooth = null;
fredc0f420372012-04-12 00:02:00 -07001108 mContext.unbindService(mConnection);
fredcd6883532012-04-25 17:46:13 -07001109 mUnbinding = false;
Zhihai Xu40874a02012-10-08 17:57:03 -07001110 mBinding = false;
fredcf2458862012-04-16 15:18:27 -07001111 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001112 mUnbinding = false;
fredc0f420372012-04-12 00:02:00 -07001113 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001114 mBluetoothGatt = null;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001115 } finally {
1116 mBluetoothLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -07001117 }
1118 }
1119
Matthew Xieddf7e472013-03-01 18:41:02 -08001120 public IBluetoothGatt getBluetoothGatt() {
1121 // sync protection
1122 return mBluetoothGatt;
1123 }
1124
Benjamin Franze8b98922014-11-12 15:57:54 +00001125 @Override
1126 public boolean bindBluetoothProfileService(int bluetoothProfile,
1127 IBluetoothProfileServiceConnection proxy) {
1128 if (!mEnable) {
1129 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001130 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
1131 + ", while Bluetooth was disabled");
Benjamin Franze8b98922014-11-12 15:57:54 +00001132 }
1133 return false;
1134 }
1135 synchronized (mProfileServices) {
1136 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
1137 if (psc == null) {
1138 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001139 Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
1140 + bluetoothProfile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001141 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001142
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001143 if (bluetoothProfile != BluetoothProfile.HEADSET) {
1144 return false;
1145 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001146
1147 Intent intent = new Intent(IBluetoothHeadset.class.getName());
Benjamin Franze8b98922014-11-12 15:57:54 +00001148 psc = new ProfileServiceConnections(intent);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001149 if (!psc.bindService()) {
1150 return false;
1151 }
Benjamin Franz5b614592014-12-09 18:58:45 +00001152
Benjamin Franze8b98922014-11-12 15:57:54 +00001153 mProfileServices.put(new Integer(bluetoothProfile), psc);
Benjamin Franze8b98922014-11-12 15:57:54 +00001154 }
1155 }
1156
1157 // Introducing a delay to give the client app time to prepare
1158 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
1159 addProxyMsg.arg1 = bluetoothProfile;
1160 addProxyMsg.obj = proxy;
1161 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
1162 return true;
1163 }
1164
1165 @Override
1166 public void unbindBluetoothProfileService(int bluetoothProfile,
1167 IBluetoothProfileServiceConnection proxy) {
1168 synchronized (mProfileServices) {
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001169 Integer profile = new Integer(bluetoothProfile);
1170 ProfileServiceConnections psc = mProfileServices.get(profile);
Benjamin Franze8b98922014-11-12 15:57:54 +00001171 if (psc == null) {
1172 return;
1173 }
1174 psc.removeProxy(proxy);
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001175 if (psc.isEmpty()) {
1176 // All prxoies are disconnected, unbind with the service.
1177 try {
1178 mContext.unbindService(psc);
1179 } catch (IllegalArgumentException e) {
1180 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
1181 }
1182 mProfileServices.remove(profile);
1183 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001184 }
1185 }
1186
1187 private void unbindAllBluetoothProfileServices() {
1188 synchronized (mProfileServices) {
1189 for (Integer i : mProfileServices.keySet()) {
1190 ProfileServiceConnections psc = mProfileServices.get(i);
Benjamin Franz5b614592014-12-09 18:58:45 +00001191 try {
1192 mContext.unbindService(psc);
1193 } catch (IllegalArgumentException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001194 Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
Benjamin Franz5b614592014-12-09 18:58:45 +00001195 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001196 psc.removeAllProxies();
1197 }
1198 mProfileServices.clear();
1199 }
1200 }
1201
1202 /**
Miao Chou658bf2f2015-06-26 17:14:35 -07001203 * Send enable message and set adapter name and address. Called when the boot phase becomes
1204 * PHASE_SYSTEM_SERVICES_READY.
1205 */
1206 public void handleOnBootPhase() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001207 if (DBG) {
1208 Slog.d(TAG, "Bluetooth boot completed");
1209 }
Jack Hea80cead2019-04-23 20:00:18 -07001210 mAppOps = mContext.getSystemService(AppOpsManager.class);
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001211 UserManagerInternal userManagerInternal =
1212 LocalServices.getService(UserManagerInternal.class);
1213 userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001214 final boolean isBluetoothDisallowed = isBluetoothDisallowed();
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01001215 if (isBluetoothDisallowed) {
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01001216 return;
1217 }
Zongheng Wang79e0bf62019-07-08 15:22:04 -07001218 final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
1219 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001220 if (DBG) {
1221 Slog.d(TAG, "Auto-enabling Bluetooth.");
1222 }
Jack He8caab152018-03-02 13:08:36 -08001223 sendEnableMsg(mQuietEnableExternal,
1224 BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
1225 mContext.getPackageName());
Ajay Panickerbf796d82016-03-11 13:47:20 -08001226 } else if (!isNameAndAddressSet()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001227 if (DBG) {
1228 Slog.d(TAG, "Getting adapter name and address");
1229 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001230 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1231 mHandler.sendMessage(getMsg);
Miao Chou658bf2f2015-06-26 17:14:35 -07001232 }
Miao Chou658bf2f2015-06-26 17:14:35 -07001233 }
1234
1235 /**
1236 * Called when switching to a different foreground user.
1237 */
1238 public void handleOnSwitchUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001239 if (DBG) {
1240 Slog.d(TAG, "User " + userHandle + " switched");
1241 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001242 mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1243 }
1244
1245 /**
1246 * Called when user is unlocked.
1247 */
1248 public void handleOnUnlockUser(int userHandle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001249 if (DBG) {
1250 Slog.d(TAG, "User " + userHandle + " unlocked");
1251 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001252 mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
Miao Chou658bf2f2015-06-26 17:14:35 -07001253 }
1254
1255 /**
Benjamin Franze8b98922014-11-12 15:57:54 +00001256 * This class manages the clients connected to a given ProfileService
1257 * and maintains the connection with that service.
1258 */
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001259 private final class ProfileServiceConnections
1260 implements ServiceConnection, IBinder.DeathRecipient {
Benjamin Franze8b98922014-11-12 15:57:54 +00001261 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001262 new RemoteCallbackList<IBluetoothProfileServiceConnection>();
Benjamin Franze8b98922014-11-12 15:57:54 +00001263 IBinder mService;
1264 ComponentName mClassName;
1265 Intent mIntent;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001266 boolean mInvokingProxyCallbacks = false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001267
1268 ProfileServiceConnections(Intent intent) {
1269 mService = null;
1270 mClassName = null;
1271 mIntent = intent;
1272 }
1273
Benjamin Franz5b614592014-12-09 18:58:45 +00001274 private boolean bindService() {
jonerlin37fc85d2018-08-09 16:39:43 +08001275 int state = BluetoothAdapter.STATE_OFF;
1276 try {
1277 mBluetoothLock.readLock().lock();
1278 if (mBluetooth != null) {
1279 state = mBluetooth.getState();
1280 }
1281 } catch (RemoteException e) {
1282 Slog.e(TAG, "Unable to call getState", e);
1283 return false;
1284 } finally {
1285 mBluetoothLock.readLock().unlock();
1286 }
1287
1288 if (!mEnable || state != BluetoothAdapter.STATE_ON) {
1289 if (DBG) {
1290 Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
1291 }
1292 return false;
1293 }
1294
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001295 if (mIntent != null && mService == null && doBind(mIntent, this, 0,
1296 UserHandle.CURRENT_OR_SELF)) {
Benjamin Franze8b98922014-11-12 15:57:54 +00001297 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1298 msg.obj = this;
1299 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
Benjamin Franz5b614592014-12-09 18:58:45 +00001300 return true;
Benjamin Franze8b98922014-11-12 15:57:54 +00001301 }
Jeff Sharkey67609c72016-03-05 14:29:13 -07001302 Slog.w(TAG, "Unable to bind with intent: " + mIntent);
Benjamin Franz5b614592014-12-09 18:58:45 +00001303 return false;
Benjamin Franze8b98922014-11-12 15:57:54 +00001304 }
1305
1306 private void addProxy(IBluetoothProfileServiceConnection proxy) {
1307 mProxies.register(proxy);
1308 if (mService != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001309 try {
Benjamin Franze8b98922014-11-12 15:57:54 +00001310 proxy.onServiceConnected(mClassName, mService);
1311 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001312 Slog.e(TAG, "Unable to connect to proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001313 }
1314 } else {
1315 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1316 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1317 msg.obj = this;
1318 mHandler.sendMessage(msg);
1319 }
1320 }
1321 }
1322
1323 private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1324 if (proxy != null) {
1325 if (mProxies.unregister(proxy)) {
1326 try {
1327 proxy.onServiceDisconnected(mClassName);
1328 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001329 Slog.e(TAG, "Unable to disconnect proxy", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001330 }
1331 }
1332 } else {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001333 Slog.w(TAG, "Trying to remove a null proxy");
Benjamin Franze8b98922014-11-12 15:57:54 +00001334 }
1335 }
1336
1337 private void removeAllProxies() {
1338 onServiceDisconnected(mClassName);
1339 mProxies.kill();
1340 }
1341
Ugo Yu6d9cfce2019-03-26 21:38:08 +08001342 private boolean isEmpty() {
1343 return mProxies.getRegisteredCallbackCount() == 0;
1344 }
1345
Benjamin Franze8b98922014-11-12 15:57:54 +00001346 @Override
1347 public void onServiceConnected(ComponentName className, IBinder service) {
1348 // remove timeout message
1349 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1350 mService = service;
1351 mClassName = className;
1352 try {
1353 mService.linkToDeath(this, 0);
1354 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001355 Slog.e(TAG, "Unable to linkToDeath", e);
Benjamin Franze8b98922014-11-12 15:57:54 +00001356 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001357
1358 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001359 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001360 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001361 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001362 mInvokingProxyCallbacks = true;
1363
1364 final int n = mProxies.beginBroadcast();
1365 try {
1366 for (int i = 0; i < n; i++) {
1367 try {
1368 mProxies.getBroadcastItem(i).onServiceConnected(className, service);
1369 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001370 Slog.e(TAG, "Unable to connect to proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001371 }
1372 }
1373 } finally {
1374 mProxies.finishBroadcast();
1375 mInvokingProxyCallbacks = false;
1376 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001377 }
1378
1379 @Override
1380 public void onServiceDisconnected(ComponentName className) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001381 if (mService == null) {
1382 return;
1383 }
Chienyuan177156b2018-12-18 10:40:25 +08001384 try {
1385 mService.unlinkToDeath(this, 0);
1386 } catch (NoSuchElementException e) {
1387 Log.e(TAG, "error unlinking to death", e);
1388 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001389 mService = null;
1390 mClassName = null;
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001391
1392 if (mInvokingProxyCallbacks) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001393 Slog.e(TAG, "Proxy callbacks already in progress.");
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001394 return;
Benjamin Franze8b98922014-11-12 15:57:54 +00001395 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001396 mInvokingProxyCallbacks = true;
1397
1398 final int n = mProxies.beginBroadcast();
1399 try {
1400 for (int i = 0; i < n; i++) {
1401 try {
1402 mProxies.getBroadcastItem(i).onServiceDisconnected(className);
1403 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001404 Slog.e(TAG, "Unable to disconnect from proxy", e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001405 }
1406 }
1407 } finally {
1408 mProxies.finishBroadcast();
1409 mInvokingProxyCallbacks = false;
1410 }
Benjamin Franze8b98922014-11-12 15:57:54 +00001411 }
1412
1413 @Override
1414 public void binderDied() {
1415 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001416 Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
Benjamin Franze8b98922014-11-12 15:57:54 +00001417 }
1418 onServiceDisconnected(mClassName);
1419 // Trigger rebind
1420 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1421 msg.obj = this;
1422 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1423 }
1424 }
1425
fredcbf072a72012-05-09 16:52:50 -07001426 private void sendBluetoothStateCallback(boolean isUp) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001427 try {
1428 int n = mStateChangeCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001429 if (DBG) {
1430 Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
1431 + " receivers.");
1432 }
1433 for (int i = 0; i < n; i++) {
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001434 try {
1435 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
1436 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001437 Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001438 }
fredcbf072a72012-05-09 16:52:50 -07001439 }
Andre Eisenbach3bf1ac52015-07-30 08:59:32 -07001440 } finally {
1441 mStateChangeCallbacks.finishBroadcast();
fredcbf072a72012-05-09 16:52:50 -07001442 }
fredcbf072a72012-05-09 16:52:50 -07001443 }
1444
1445 /**
Zhihai Xu40874a02012-10-08 17:57:03 -07001446 * Inform BluetoothAdapter instances that Adapter service is up
1447 */
1448 private void sendBluetoothServiceUpCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001449 try {
1450 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001451 Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1452 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001453 try {
1454 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001455 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001456 Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
Zhihai Xu40874a02012-10-08 17:57:03 -07001457 }
1458 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001459 } finally {
1460 mCallbacks.finishBroadcast();
Zhihai Xu40874a02012-10-08 17:57:03 -07001461 }
1462 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001463
Zhihai Xu40874a02012-10-08 17:57:03 -07001464 /**
fredcbf072a72012-05-09 16:52:50 -07001465 * Inform BluetoothAdapter instances that Adapter service is down
1466 */
1467 private void sendBluetoothServiceDownCallback() {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001468 try {
1469 int n = mCallbacks.beginBroadcast();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001470 Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1471 for (int i = 0; i < n; i++) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001472 try {
1473 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001474 } catch (RemoteException e) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001475 Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
fredcd6883532012-04-25 17:46:13 -07001476 }
1477 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001478 } finally {
1479 mCallbacks.finishBroadcast();
fredcd6883532012-04-25 17:46:13 -07001480 }
1481 }
Svet Ganov408abf72015-05-12 19:13:36 -07001482
fredc0f420372012-04-12 00:02:00 -07001483 public String getAddress() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001484 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001485
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001486 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1487 Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001488 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001489 }
1490
Svet Ganov408abf72015-05-12 19:13:36 -07001491 if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1492 != PackageManager.PERMISSION_GRANTED) {
1493 return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1494 }
1495
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001496 try {
1497 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001498 if (mBluetooth != null) {
1499 return mBluetooth.getAddress();
1500 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001501 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001502 Slog.e(TAG,
1503 "getAddress(): Unable to retrieve address remotely. Returning cached address",
1504 e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001505 } finally {
1506 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001507 }
Ajay Panickerbf796d82016-03-11 13:47:20 -08001508
Matthew Xiecdce0b92012-07-12 19:06:15 -07001509 // mAddress is accessed from outside.
1510 // It is alright without a lock. Here, bluetooth is off, no other thread is
1511 // changing mAddress
fredc0f420372012-04-12 00:02:00 -07001512 return mAddress;
1513 }
fredc649fe492012-04-19 01:07:18 -07001514
fredc0f420372012-04-12 00:02:00 -07001515 public String getName() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001516 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Zhihai Xu40874a02012-10-08 17:57:03 -07001517
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001518 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
1519 Slog.w(TAG, "getName(): not allowed for non-active and non system user");
Zhihai Xu6eb76522012-11-29 15:41:04 -08001520 return null;
Zhihai Xu40874a02012-10-08 17:57:03 -07001521 }
1522
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001523 try {
1524 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001525 if (mBluetooth != null) {
1526 return mBluetooth.getName();
1527 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001528 } catch (RemoteException e) {
1529 Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1530 } finally {
1531 mBluetoothLock.readLock().unlock();
fredc116d1d462012-04-20 14:47:08 -07001532 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001533
Matthew Xiecdce0b92012-07-12 19:06:15 -07001534 // mName is accessed from outside.
1535 // It alright without a lock. Here, bluetooth is off, no other thread is
1536 // changing mName
fredc0f420372012-04-12 00:02:00 -07001537 return mName;
1538 }
1539
fredc0f420372012-04-12 00:02:00 -07001540 private class BluetoothServiceConnection implements ServiceConnection {
Marie Janssencb21ad72016-12-13 10:51:02 -08001541 public void onServiceConnected(ComponentName componentName, IBinder service) {
1542 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001543 if (DBG) {
1544 Slog.d(TAG, "BluetoothServiceConnection: " + name);
1545 }
fredc0f420372012-04-12 00:02:00 -07001546 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001547 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001548 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001549 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001550 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1551 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001552 Slog.e(TAG, "Unknown service connected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001553 return;
1554 }
fredc0f420372012-04-12 00:02:00 -07001555 msg.obj = service;
1556 mHandler.sendMessage(msg);
1557 }
1558
Marie Janssencb21ad72016-12-13 10:51:02 -08001559 public void onServiceDisconnected(ComponentName componentName) {
1560 // Called if we unexpectedly disconnect.
1561 String name = componentName.getClassName();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001562 if (DBG) {
1563 Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
1564 }
fredc0f420372012-04-12 00:02:00 -07001565 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
Marie Janssencb21ad72016-12-13 10:51:02 -08001566 if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001567 msg.arg1 = SERVICE_IBLUETOOTH;
Marie Janssencb21ad72016-12-13 10:51:02 -08001568 } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
Matthew Xieddf7e472013-03-01 18:41:02 -08001569 msg.arg1 = SERVICE_IBLUETOOTHGATT;
1570 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001571 Slog.e(TAG, "Unknown service disconnected: " + name);
Matthew Xieddf7e472013-03-01 18:41:02 -08001572 return;
1573 }
fredc0f420372012-04-12 00:02:00 -07001574 mHandler.sendMessage(msg);
1575 }
1576 }
1577
1578 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1579
Zhihai Xu40874a02012-10-08 17:57:03 -07001580 private class BluetoothHandler extends Handler {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001581 boolean mGetNameAddressOnly = false;
1582
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001583 BluetoothHandler(Looper looper) {
Zhihai Xu40874a02012-10-08 17:57:03 -07001584 super(looper);
1585 }
1586
fredc0f420372012-04-12 00:02:00 -07001587 @Override
1588 public void handleMessage(Message msg) {
fredc0f420372012-04-12 00:02:00 -07001589 switch (msg.what) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001590 case MESSAGE_GET_NAME_AND_ADDRESS:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001591 if (DBG) {
1592 Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1593 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001594 try {
1595 mBluetoothLock.writeLock().lock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001596 if ((mBluetooth == null) && (!mBinding)) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001597 if (DBG) {
1598 Slog.d(TAG, "Binding to service to get name and address");
1599 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001600 mGetNameAddressOnly = true;
1601 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1602 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
1603 Intent i = new Intent(IBluetooth.class.getName());
1604 if (!doBind(i, mConnection,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001605 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1606 UserHandle.CURRENT)) {
Ajay Panicker4bb48302016-03-31 14:14:27 -07001607 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1608 } else {
1609 mBinding = true;
1610 }
1611 } else if (mBluetooth != null) {
1612 try {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001613 storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress());
Ajay Panicker4bb48302016-03-31 14:14:27 -07001614 } catch (RemoteException re) {
1615 Slog.e(TAG, "Unable to grab names", re);
1616 }
1617 if (mGetNameAddressOnly && !mEnable) {
1618 unbindAndFinish();
1619 }
1620 mGetNameAddressOnly = false;
1621 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001622 } finally {
1623 mBluetoothLock.writeLock().unlock();
Ajay Panicker4bb48302016-03-31 14:14:27 -07001624 }
1625 break;
1626
Matthew Xiecdce0b92012-07-12 19:06:15 -07001627 case MESSAGE_ENABLE:
fredcf2458862012-04-16 15:18:27 -07001628 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001629 Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
fredc649fe492012-04-19 01:07:18 -07001630 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001631 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1632 mEnable = true;
Calvin Ona0b91d72016-06-15 17:58:23 -07001633
1634 // Use service interface to get the exact state
1635 try {
1636 mBluetoothLock.readLock().lock();
1637 if (mBluetooth != null) {
1638 int state = mBluetooth.getState();
1639 if (state == BluetoothAdapter.STATE_BLE_ON) {
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001640 Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
Calvin Ona0b91d72016-06-15 17:58:23 -07001641 mBluetooth.onLeServiceUp();
Marie Janssene0bfa2e2016-12-20 11:21:12 -08001642 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
Calvin Ona0b91d72016-06-15 17:58:23 -07001643 break;
1644 }
1645 }
1646 } catch (RemoteException e) {
1647 Slog.e(TAG, "", e);
1648 } finally {
1649 mBluetoothLock.readLock().unlock();
1650 }
1651
1652 mQuietEnable = (msg.arg1 == 1);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001653 if (mBluetooth == null) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001654 handleEnable(mQuietEnable);
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001655 } else {
1656 //
1657 // We need to wait until transitioned to STATE_OFF and
1658 // the previous Bluetooth process has exited. The
1659 // waiting period has three components:
1660 // (a) Wait until the local state is STATE_OFF. This
1661 // is accomplished by "waitForOnOff(false, true)".
1662 // (b) Wait until the STATE_OFF state is updated to
1663 // all components.
1664 // (c) Wait until the Bluetooth process exits, and
1665 // ActivityManager detects it.
1666 // The waiting for (b) and (c) is accomplished by
1667 // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001668 // message. The delay time is backed off if Bluetooth
1669 // continuously failed to turn on itself.
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001670 //
1671 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001672 Message restartMsg =
1673 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001674 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Pavlin Radoslavove47ec142016-06-01 22:25:18 -07001675 }
fredc649fe492012-04-19 01:07:18 -07001676 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001677
fredc0f420372012-04-12 00:02:00 -07001678 case MESSAGE_DISABLE:
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001679 if (DBG) {
1680 Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
1681 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001682 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1683 if (mEnable && mBluetooth != null) {
1684 waitForOnOff(true, false);
1685 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001686 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001687 waitForOnOff(false, false);
1688 } else {
1689 mEnable = false;
Zhihai Xu401202b2012-12-03 11:36:21 -08001690 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001691 }
fredc0f420372012-04-12 00:02:00 -07001692 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001693
Stanley Tng873b5702017-05-01 21:27:31 -07001694 case MESSAGE_RESTORE_USER_SETTING:
Jack He8caab152018-03-02 13:08:36 -08001695 if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1696 if (DBG) {
1697 Slog.d(TAG, "Restore Bluetooth state to disabled");
Stanley Tng873b5702017-05-01 21:27:31 -07001698 }
Jack He8caab152018-03-02 13:08:36 -08001699 persistBluetoothSetting(BLUETOOTH_OFF);
1700 mEnableExternal = false;
1701 sendDisableMsg(
1702 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1703 mContext.getPackageName());
1704 } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1705 if (DBG) {
1706 Slog.d(TAG, "Restore Bluetooth state to enabled");
1707 }
1708 mQuietEnableExternal = false;
1709 mEnableExternal = true;
1710 // waive WRITE_SECURE_SETTINGS permission check
1711 sendEnableMsg(false,
1712 BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
1713 mContext.getPackageName());
Stanley Tng873b5702017-05-01 21:27:31 -07001714 }
1715 break;
1716
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001717 case MESSAGE_REGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001718 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001719 mCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001720 break;
Marie Janssencb21ad72016-12-13 10:51:02 -08001721 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001722 case MESSAGE_UNREGISTER_ADAPTER: {
fredc0f420372012-04-12 00:02:00 -07001723 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001724 mCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001725 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001726 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001727 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
1728 IBluetoothStateChangeCallback callback =
1729 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001730 mStateChangeCallbacks.register(callback);
fredc0f420372012-04-12 00:02:00 -07001731 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001732 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001733 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
1734 IBluetoothStateChangeCallback callback =
1735 (IBluetoothStateChangeCallback) msg.obj;
Marie Janssencb21ad72016-12-13 10:51:02 -08001736 mStateChangeCallbacks.unregister(callback);
fredc0f420372012-04-12 00:02:00 -07001737 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001738 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001739 case MESSAGE_ADD_PROXY_DELAYED: {
Jack He8caab152018-03-02 13:08:36 -08001740 ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
Benjamin Franze8b98922014-11-12 15:57:54 +00001741 if (psc == null) {
1742 break;
1743 }
1744 IBluetoothProfileServiceConnection proxy =
1745 (IBluetoothProfileServiceConnection) msg.obj;
1746 psc.addProxy(proxy);
1747 break;
1748 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001749 case MESSAGE_BIND_PROFILE_SERVICE: {
Benjamin Franze8b98922014-11-12 15:57:54 +00001750 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1751 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1752 if (psc == null) {
1753 break;
1754 }
1755 psc.bindService();
1756 break;
1757 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001758 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
1759 if (DBG) {
1760 Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
1761 }
fredc0f420372012-04-12 00:02:00 -07001762
1763 IBinder service = (IBinder) msg.obj;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001764 try {
1765 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001766 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001767 mBluetoothGatt =
1768 IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
Myles Watson304ebf22018-05-11 08:47:24 -07001769 continueFromBleOnState();
Matthew Xieddf7e472013-03-01 18:41:02 -08001770 break;
1771 } // else must be SERVICE_IBLUETOOTH
1772
1773 //Remove timeout
Zhihai Xuaf5971e2013-06-10 20:28:31 -07001774 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Matthew Xieddf7e472013-03-01 18:41:02 -08001775
fredc0f420372012-04-12 00:02:00 -07001776 mBinding = false;
Marie Janssen9db28eb2016-01-12 16:05:15 -08001777 mBluetoothBinder = service;
Jeff Sharkey0a17db12016-11-04 11:23:46 -06001778 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
fredc0f420372012-04-12 00:02:00 -07001779
Ajay Panicker4bb48302016-03-31 14:14:27 -07001780 if (!isNameAndAddressSet()) {
1781 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1782 mHandler.sendMessage(getMsg);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001783 if (mGetNameAddressOnly) {
1784 return;
1785 }
Ajay Panicker4bb48302016-03-31 14:14:27 -07001786 }
1787
Matthew Xiecdce0b92012-07-12 19:06:15 -07001788 //Register callback object
fredcbf072a72012-05-09 16:52:50 -07001789 try {
Matthew Xiecdce0b92012-07-12 19:06:15 -07001790 mBluetooth.registerCallback(mBluetoothCallback);
1791 } catch (RemoteException re) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001792 Slog.e(TAG, "Unable to register BluetoothCallback", re);
fredcbf072a72012-05-09 16:52:50 -07001793 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001794 //Inform BluetoothAdapter instances that service is up
Zhihai Xu40874a02012-10-08 17:57:03 -07001795 sendBluetoothServiceUpCallback();
1796
Matthew Xiecdce0b92012-07-12 19:06:15 -07001797 //Do enable request
1798 try {
Jack Hea6e031c2017-12-08 12:21:37 -08001799 if (!mQuietEnable) {
Marie Janssencb21ad72016-12-13 10:51:02 -08001800 if (!mBluetooth.enable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001801 Slog.e(TAG, "IBluetooth.enable() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001802 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001803 } else {
1804 if (!mBluetooth.enableNoAutoConnect()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001805 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001806 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07001807 }
1808 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001809 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07001810 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001811 } finally {
1812 mBluetoothLock.writeLock().unlock();
Freda8c6df02012-07-11 10:25:23 -07001813 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001814
1815 if (!mEnable) {
1816 waitForOnOff(true, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001817 handleDisable();
Zhihai Xu40874a02012-10-08 17:57:03 -07001818 waitForOnOff(false, false);
1819 }
fredc649fe492012-04-19 01:07:18 -07001820 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001821 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001822 case MESSAGE_BLUETOOTH_STATE_CHANGE: {
fredcbf072a72012-05-09 16:52:50 -07001823 int prevState = msg.arg1;
1824 int newState = msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08001825 if (DBG) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001826 Slog.d(TAG,
1827 "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
1828 prevState) + " > " + BluetoothAdapter.nameForState(
1829 newState));
Marie Janssencb21ad72016-12-13 10:51:02 -08001830 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001831 mState = newState;
1832 bluetoothStateChangeHandler(prevState, newState);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001833 // handle error state transition case from TURNING_ON to OFF
1834 // unbind and rebind bluetooth service and enable bluetooth
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001835 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
1836 == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001837 recoverBluetoothServiceFromError(false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001838 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001839 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
1840 == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
Marie Janssen2977c3e2016-11-09 12:01:24 -08001841 recoverBluetoothServiceFromError(true);
Nitin Arorad055adb2015-03-02 15:03:51 -08001842 }
Calvin Ona0b91d72016-06-15 17:58:23 -07001843 // If we tried to enable BT while BT was in the process of shutting down,
1844 // wait for the BT process to fully tear down and then force a restart
1845 // here. This is a bit of a hack (b/29363429).
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001846 if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
1847 == BluetoothAdapter.STATE_OFF)) {
Calvin Ona0b91d72016-06-15 17:58:23 -07001848 if (mEnable) {
1849 Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1850 waitForOnOff(false, true);
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001851 Message restartMsg =
1852 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001853 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Calvin Ona0b91d72016-06-15 17:58:23 -07001854 }
1855 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001856 if (newState == BluetoothAdapter.STATE_ON
1857 || newState == BluetoothAdapter.STATE_BLE_ON) {
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001858 // bluetooth is working, reset the counter
1859 if (mErrorRecoveryRetryCounter != 0) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001860 Slog.w(TAG, "bluetooth is recovered from error");
Zhihai Xudd9d17d2013-01-08 17:05:58 -08001861 mErrorRecoveryRetryCounter = 0;
1862 }
1863 }
fredc649fe492012-04-19 01:07:18 -07001864 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001865 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001866 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
Marie Janssencb21ad72016-12-13 10:51:02 -08001867 Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001868 try {
1869 mBluetoothLock.writeLock().lock();
Matthew Xieddf7e472013-03-01 18:41:02 -08001870 if (msg.arg1 == SERVICE_IBLUETOOTH) {
1871 // if service is unbinded already, do nothing and return
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001872 if (mBluetooth == null) {
1873 break;
1874 }
Matthew Xieddf7e472013-03-01 18:41:02 -08001875 mBluetooth = null;
1876 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1877 mBluetoothGatt = null;
1878 break;
1879 } else {
Marie Janssencb21ad72016-12-13 10:51:02 -08001880 Slog.e(TAG, "Unknown argument for service disconnect!");
Matthew Xieddf7e472013-03-01 18:41:02 -08001881 break;
1882 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001883 } finally {
1884 mBluetoothLock.writeLock().unlock();
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301885 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001886
Marie Janssene54b4222017-03-16 18:10:59 -07001887 // log the unexpected crash
1888 addCrashLog();
Jack He8caab152018-03-02 13:08:36 -08001889 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
1890 mContext.getPackageName(), false);
Zhihai Xu40874a02012-10-08 17:57:03 -07001891 if (mEnable) {
1892 mEnable = false;
1893 // Send a Bluetooth Restart message
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001894 Message restartMsg =
1895 mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001896 mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
Zhihai Xu40874a02012-10-08 17:57:03 -07001897 }
1898
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001899 sendBluetoothServiceDownCallback();
Zhihai Xu40874a02012-10-08 17:57:03 -07001900
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001901 // Send BT state broadcast to update
1902 // the BT icon correctly
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001903 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
1904 == BluetoothAdapter.STATE_ON)) {
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001905 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001906 BluetoothAdapter.STATE_TURNING_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001907 mState = BluetoothAdapter.STATE_TURNING_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07001908 }
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001909 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1910 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001911 BluetoothAdapter.STATE_OFF);
Andre Eisenbach305fdab2015-11-11 21:43:26 -08001912 }
1913
1914 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1915 mState = BluetoothAdapter.STATE_OFF;
fredc649fe492012-04-19 01:07:18 -07001916 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001917 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001918 case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
Ugo Yu1ff6fd32019-11-20 17:59:11 +08001919 mErrorRecoveryRetryCounter++;
1920 Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
1921 + mErrorRecoveryRetryCounter);
1922 if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
1923 /* Enable without persisting the setting as
1924 it doesnt change when IBluetooth
1925 service restarts */
1926 mEnable = true;
1927 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
1928 mContext.getPackageName(), true);
1929 handleEnable(mQuietEnable);
1930 } else {
1931 Slog.e(TAG, "Reach maximum retry to restart Bluetooth!");
1932 }
Syed Ibrahim M1223e5a2012-08-29 18:07:26 +05301933 break;
1934 }
Marie Janssencb21ad72016-12-13 10:51:02 -08001935 case MESSAGE_TIMEOUT_BIND: {
1936 Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1937 mBluetoothLock.writeLock().lock();
1938 mBinding = false;
1939 mBluetoothLock.writeLock().unlock();
1940 break;
1941 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001942 case MESSAGE_TIMEOUT_UNBIND: {
Jeff Sharkey67609c72016-03-05 14:29:13 -07001943 Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001944 mBluetoothLock.writeLock().lock();
1945 mUnbinding = false;
1946 mBluetoothLock.writeLock().unlock();
fredc649fe492012-04-19 01:07:18 -07001947 break;
Matthew Xiecdce0b92012-07-12 19:06:15 -07001948 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001949
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001950 case MESSAGE_USER_SWITCHED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001951 if (DBG) {
1952 Slog.d(TAG, "MESSAGE_USER_SWITCHED");
1953 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001954 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07001955
Zhihai Xu40874a02012-10-08 17:57:03 -07001956 /* disable and enable BT when detect a user switch */
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07001957 if (mBluetooth != null && isEnabled()) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001958 try {
1959 mBluetoothLock.readLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001960 if (mBluetooth != null) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001961 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xu40874a02012-10-08 17:57:03 -07001962 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001963 } catch (RemoteException re) {
1964 Slog.e(TAG, "Unable to unregister", re);
1965 } finally {
1966 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07001967 }
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001968
1969 if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1970 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
1971 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
1972 mState = BluetoothAdapter.STATE_OFF;
1973 }
1974 if (mState == BluetoothAdapter.STATE_OFF) {
1975 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
1976 mState = BluetoothAdapter.STATE_TURNING_ON;
1977 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001978
1979 waitForOnOff(true, false);
1980
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001981 if (mState == BluetoothAdapter.STATE_TURNING_ON) {
1982 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
1983 }
Zhihai Xu40874a02012-10-08 17:57:03 -07001984
Benjamin Franze8b98922014-11-12 15:57:54 +00001985 unbindAllBluetoothProfileServices();
Zhihai Xu40874a02012-10-08 17:57:03 -07001986 // disable
Jack He8caab152018-03-02 13:08:36 -08001987 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
1988 mContext.getPackageName(), false);
Zhihai Xu401202b2012-12-03 11:36:21 -08001989 handleDisable();
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001990 // Pbap service need receive STATE_TURNING_OFF intent to close
1991 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001992 BluetoothAdapter.STATE_TURNING_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001993
Pavlin Radoslavov41401112016-06-27 15:25:18 -07001994 boolean didDisableTimeout = !waitForOnOff(false, true);
Zhihai Xu40874a02012-10-08 17:57:03 -07001995
Zhihai Xu4e22ad32012-11-13 15:11:26 -08001996 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
Myles Watsonb5cd11a2017-11-27 16:42:11 -08001997 BluetoothAdapter.STATE_OFF);
Zhihai Xu40874a02012-10-08 17:57:03 -07001998 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001999
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002000 try {
2001 mBluetoothLock.writeLock().lock();
2002 if (mBluetooth != null) {
2003 mBluetooth = null;
2004 // Unbind
2005 mContext.unbindService(mConnection);
2006 }
2007 mBluetoothGatt = null;
2008 } finally {
2009 mBluetoothLock.writeLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002010 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002011
Pavlin Radoslavov41401112016-06-27 15:25:18 -07002012 //
2013 // If disabling Bluetooth times out, wait for an
2014 // additional amount of time to ensure the process is
2015 // shut down completely before attempting to restart.
2016 //
2017 if (didDisableTimeout) {
2018 SystemClock.sleep(3000);
2019 } else {
2020 SystemClock.sleep(100);
2021 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002022
Zhihai Xu4e22ad32012-11-13 15:11:26 -08002023 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2024 mState = BluetoothAdapter.STATE_OFF;
Zhihai Xu40874a02012-10-08 17:57:03 -07002025 // enable
Jack He8caab152018-03-02 13:08:36 -08002026 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
2027 mContext.getPackageName(), true);
Ram Periathiruvadi88256d12017-05-03 19:11:20 -07002028 // mEnable flag could have been reset on disableBLE. Reenable it.
2029 mEnable = true;
Zhihai Xu401202b2012-12-03 11:36:21 -08002030 handleEnable(mQuietEnable);
John Spurlock8a985d22014-02-25 09:40:05 -05002031 } else if (mBinding || mBluetooth != null) {
Zhihai Xu40874a02012-10-08 17:57:03 -07002032 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
2033 userMsg.arg2 = 1 + msg.arg2;
Marie Janssencb21ad72016-12-13 10:51:02 -08002034 // if user is switched when service is binding retry after a delay
Zhihai Xu40874a02012-10-08 17:57:03 -07002035 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
2036 if (DBG) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002037 Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
Zhihai Xu40874a02012-10-08 17:57:03 -07002038 }
John Spurlock8a985d22014-02-25 09:40:05 -05002039 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002040 break;
2041 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002042 case MESSAGE_USER_UNLOCKED: {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002043 if (DBG) {
2044 Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
2045 }
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002046 mHandler.removeMessages(MESSAGE_USER_SWITCHED);
2047
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002048 if (mEnable && !mBinding && (mBluetooth == null)) {
2049 // We should be connected, but we gave up for some
2050 // reason; maybe the Bluetooth service wasn't encryption
2051 // aware, so try binding again.
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002052 if (DBG) {
2053 Slog.d(TAG, "Enabled but not bound; retrying after unlock");
2054 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002055 handleEnable(mQuietEnable);
Jeff Sharkeyaacb89e2016-03-05 14:42:58 -07002056 }
2057 }
fredc0f420372012-04-12 00:02:00 -07002058 }
2059 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002060 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002061
Zhihai Xu401202b2012-12-03 11:36:21 -08002062 private void handleEnable(boolean quietMode) {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002063 mQuietEnable = quietMode;
2064
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002065 try {
2066 mBluetoothLock.writeLock().lock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002067 if ((mBluetooth == null) && (!mBinding)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002068 //Start bind timeout and bind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002069 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
2070 mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002071 Intent i = new Intent(IBluetooth.class.getName());
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002072 if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
Dianne Hackbornce09f5a2014-10-10 15:03:13 -07002073 UserHandle.CURRENT)) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002074 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Zhihai Xu40874a02012-10-08 17:57:03 -07002075 } else {
2076 mBinding = true;
Matthew Xiecdce0b92012-07-12 19:06:15 -07002077 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002078 } else if (mBluetooth != null) {
Matthew Xiecdce0b92012-07-12 19:06:15 -07002079 //Enable bluetooth
2080 try {
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002081 if (!mQuietEnable) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002082 if (!mBluetooth.enable()) {
2083 Slog.e(TAG, "IBluetooth.enable() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002084 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002085 } else {
2086 if (!mBluetooth.enableNoAutoConnect()) {
2087 Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002088 }
Matthew Xiecdce0b92012-07-12 19:06:15 -07002089 }
2090 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002091 Slog.e(TAG, "Unable to call enable()", e);
Matthew Xiecdce0b92012-07-12 19:06:15 -07002092 }
2093 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002094 } finally {
2095 mBluetoothLock.writeLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002096 }
2097 }
2098
Dianne Hackborn221ea892013-08-04 16:50:16 -07002099 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
2100 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
2101 intent.setComponent(comp);
2102 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
Jeff Sharkey67609c72016-03-05 14:29:13 -07002103 Slog.e(TAG, "Fail to bind to: " + intent);
Dianne Hackborn221ea892013-08-04 16:50:16 -07002104 return false;
2105 }
2106 return true;
2107 }
2108
Zhihai Xu401202b2012-12-03 11:36:21 -08002109 private void handleDisable() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002110 try {
2111 mBluetoothLock.readLock().lock();
Andre Eisenbach305fdab2015-11-11 21:43:26 -08002112 if (mBluetooth != null) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002113 if (DBG) {
2114 Slog.d(TAG, "Sending off request.");
2115 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002116 if (!mBluetooth.disable()) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002117 Slog.e(TAG, "IBluetooth.disable() returned false");
Matthew Xiecdce0b92012-07-12 19:06:15 -07002118 }
2119 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002120 } catch (RemoteException e) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002121 Slog.e(TAG, "Unable to call disable()", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002122 } finally {
2123 mBluetoothLock.readLock().unlock();
Matthew Xiecdce0b92012-07-12 19:06:15 -07002124 }
2125 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002126
2127 private boolean checkIfCallerIsForegroundUser() {
2128 int foregroundUser;
2129 int callingUser = UserHandle.getCallingUserId();
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002130 int callingUid = Binder.getCallingUid();
Zhihai Xu40874a02012-10-08 17:57:03 -07002131 long callingIdentity = Binder.clearCallingIdentity();
Benjamin Franze8b98922014-11-12 15:57:54 +00002132 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2133 UserInfo ui = um.getProfileParent(callingUser);
2134 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
Martijn Coenen8385c5a2012-11-29 10:14:16 -08002135 int callingAppId = UserHandle.getAppId(callingUid);
Zhihai Xu40874a02012-10-08 17:57:03 -07002136 boolean valid = false;
2137 try {
2138 foregroundUser = ActivityManager.getCurrentUser();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002139 valid = (callingUser == foregroundUser) || parentUser == foregroundUser
2140 || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid;
Marie Janssencb21ad72016-12-13 10:51:02 -08002141 if (DBG && !valid) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002142 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
2143 + callingUser + " parentUser=" + parentUser + " foregroundUser="
2144 + foregroundUser);
Zhihai Xu40874a02012-10-08 17:57:03 -07002145 }
2146 } finally {
2147 Binder.restoreCallingIdentity(callingIdentity);
2148 }
2149 return valid;
2150 }
2151
Nitin Arorad055adb2015-03-02 15:03:51 -08002152 private void sendBleStateChanged(int prevState, int newState) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002153 if (DBG) {
2154 Slog.d(TAG,
2155 "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
2156 + BluetoothAdapter.nameForState(newState));
2157 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002158 // Send broadcast message to everyone else
2159 Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
2160 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2161 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2162 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2163 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
2164 }
2165
Zhihai Xu40874a02012-10-08 17:57:03 -07002166 private void bluetoothStateChangeHandler(int prevState, int newState) {
Nitin Arorad055adb2015-03-02 15:03:51 -08002167 boolean isStandardBroadcast = true;
Marie Janssencb21ad72016-12-13 10:51:02 -08002168 if (prevState == newState) { // No change. Nothing to do.
2169 return;
2170 }
2171 // Notify all proxy objects first of adapter state change
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002172 if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002173 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002174 && newState == BluetoothAdapter.STATE_BLE_ON);
Zhihai Xu40874a02012-10-08 17:57:03 -07002175
Marie Janssencb21ad72016-12-13 10:51:02 -08002176 if (newState == BluetoothAdapter.STATE_OFF) {
2177 // If Bluetooth is off, send service down event to proxy objects, and unbind
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002178 if (DBG) {
2179 Slog.d(TAG, "Bluetooth is complete send Service Down");
2180 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002181 sendBluetoothServiceDownCallback();
2182 unbindAndFinish();
Nitin Arorad055adb2015-03-02 15:03:51 -08002183 sendBleStateChanged(prevState, newState);
Marie Janssencb21ad72016-12-13 10:51:02 -08002184 // Don't broadcast as it has already been broadcast before
Nitin Arorad055adb2015-03-02 15:03:51 -08002185 isStandardBroadcast = false;
2186
Marie Janssencb21ad72016-12-13 10:51:02 -08002187 } else if (!intermediate_off) {
2188 // connect to GattService
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002189 if (DBG) {
2190 Slog.d(TAG, "Bluetooth is in LE only mode");
2191 }
Myles Watson304ebf22018-05-11 08:47:24 -07002192 if (mBluetoothGatt != null || !mContext.getPackageManager()
2193 .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
2194 continueFromBleOnState();
Marie Janssencb21ad72016-12-13 10:51:02 -08002195 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002196 if (DBG) {
2197 Slog.d(TAG, "Binding Bluetooth GATT service");
2198 }
Myles Watson304ebf22018-05-11 08:47:24 -07002199 Intent i = new Intent(IBluetoothGatt.class.getName());
2200 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
2201 UserHandle.CURRENT);
Nitin Arorad055adb2015-03-02 15:03:51 -08002202 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002203 sendBleStateChanged(prevState, newState);
2204 //Don't broadcase this as std intent
2205 isStandardBroadcast = false;
2206
2207 } else if (intermediate_off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002208 if (DBG) {
2209 Slog.d(TAG, "Intermediate off, back to LE only mode");
2210 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002211 // For LE only mode, broadcast as is
2212 sendBleStateChanged(prevState, newState);
2213 sendBluetoothStateCallback(false); // BT is OFF for general users
2214 // Broadcast as STATE_OFF
2215 newState = BluetoothAdapter.STATE_OFF;
2216 sendBrEdrDownCallback();
Nitin Arorad055adb2015-03-02 15:03:51 -08002217 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002218 } else if (newState == BluetoothAdapter.STATE_ON) {
2219 boolean isUp = (newState == BluetoothAdapter.STATE_ON);
2220 sendBluetoothStateCallback(isUp);
2221 sendBleStateChanged(prevState, newState);
2222
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002223 } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
2224 || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002225 sendBleStateChanged(prevState, newState);
2226 isStandardBroadcast = false;
2227
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002228 } else if (newState == BluetoothAdapter.STATE_TURNING_ON
2229 || newState == BluetoothAdapter.STATE_TURNING_OFF) {
Marie Janssencb21ad72016-12-13 10:51:02 -08002230 sendBleStateChanged(prevState, newState);
2231 }
2232
2233 if (isStandardBroadcast) {
2234 if (prevState == BluetoothAdapter.STATE_BLE_ON) {
2235 // Show prevState of BLE_ON as OFF to standard users
2236 prevState = BluetoothAdapter.STATE_OFF;
2237 }
2238 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
2239 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
2240 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
2241 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2242 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
Zhihai Xu40874a02012-10-08 17:57:03 -07002243 }
2244 }
2245
2246 /**
2247 * if on is true, wait for state become ON
2248 * if off is true, wait for state become OFF
2249 * if both on and off are false, wait for state not ON
2250 */
2251 private boolean waitForOnOff(boolean on, boolean off) {
2252 int i = 0;
2253 while (i < 10) {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002254 try {
2255 mBluetoothLock.readLock().lock();
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002256 if (mBluetooth == null) {
2257 break;
2258 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002259 if (on) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002260 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
2261 return true;
2262 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002263 } else if (off) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002264 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) {
2265 return true;
2266 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002267 } else {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002268 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) {
2269 return true;
2270 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002271 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002272 } catch (RemoteException e) {
2273 Slog.e(TAG, "getState()", e);
2274 break;
2275 } finally {
2276 mBluetoothLock.readLock().unlock();
Zhihai Xu40874a02012-10-08 17:57:03 -07002277 }
2278 if (on || off) {
2279 SystemClock.sleep(300);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002280 } else {
Zhihai Xu40874a02012-10-08 17:57:03 -07002281 SystemClock.sleep(50);
Robert Greenwalt665e1ae2012-08-21 19:27:00 -07002282 }
Zhihai Xu40874a02012-10-08 17:57:03 -07002283 i++;
2284 }
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002285 Slog.e(TAG, "waitForOnOff time out");
Zhihai Xu40874a02012-10-08 17:57:03 -07002286 return false;
2287 }
Zhihai Xu681ae7f2012-11-12 15:14:18 -08002288
Jack He8caab152018-03-02 13:08:36 -08002289 private void sendDisableMsg(int reason, String packageName) {
Zhihai Xu401202b2012-12-03 11:36:21 -08002290 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
Jack He8caab152018-03-02 13:08:36 -08002291 addActiveLog(reason, packageName, false);
Zhihai Xu401202b2012-12-03 11:36:21 -08002292 }
2293
Jack He8caab152018-03-02 13:08:36 -08002294 private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002295 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
Jack He8caab152018-03-02 13:08:36 -08002296 addActiveLog(reason, packageName, true);
Marie Janssen12a35012017-06-26 07:21:03 -07002297 mLastEnabledTime = SystemClock.elapsedRealtime();
Marie Janssen59804562016-12-28 14:13:21 -08002298 }
2299
Jack He8caab152018-03-02 13:08:36 -08002300 private void addActiveLog(int reason, String packageName, boolean enable) {
Marie Janssen59804562016-12-28 14:13:21 -08002301 synchronized (mActiveLogs) {
Marie Janssene54b4222017-03-16 18:10:59 -07002302 if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
Marie Janssen59804562016-12-28 14:13:21 -08002303 mActiveLogs.remove();
2304 }
Jack He8caab152018-03-02 13:08:36 -08002305 mActiveLogs.add(
2306 new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
Marie Janssen59804562016-12-28 14:13:21 -08002307 }
Tej Singhd8e7cc62018-03-22 18:30:31 +00002308
2309 int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
2310 StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
2311 StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
2312 Binder.getCallingUid(), null, state, reason, packageName);
Zhihai Xu401202b2012-12-03 11:36:21 -08002313 }
2314
Marie Janssene54b4222017-03-16 18:10:59 -07002315 private void addCrashLog() {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002316 synchronized (mCrashTimestamps) {
2317 if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
2318 mCrashTimestamps.removeFirst();
2319 }
2320 mCrashTimestamps.add(System.currentTimeMillis());
2321 mCrashes++;
2322 }
Marie Janssene54b4222017-03-16 18:10:59 -07002323 }
2324
Marie Janssen2977c3e2016-11-09 12:01:24 -08002325 private void recoverBluetoothServiceFromError(boolean clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002326 Slog.e(TAG, "recoverBluetoothServiceFromError");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002327 try {
2328 mBluetoothLock.readLock().lock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002329 if (mBluetooth != null) {
2330 //Unregister callback object
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002331 mBluetooth.unregisterCallback(mBluetoothCallback);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002332 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002333 } catch (RemoteException re) {
2334 Slog.e(TAG, "Unable to unregister", re);
2335 } finally {
2336 mBluetoothLock.readLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002337 }
2338
2339 SystemClock.sleep(500);
2340
2341 // disable
Jack He8caab152018-03-02 13:08:36 -08002342 addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
2343 mContext.getPackageName(), false);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002344 handleDisable();
2345
2346 waitForOnOff(false, true);
2347
2348 sendBluetoothServiceDownCallback();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002349
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002350 try {
2351 mBluetoothLock.writeLock().lock();
2352 if (mBluetooth != null) {
2353 mBluetooth = null;
2354 // Unbind
2355 mContext.unbindService(mConnection);
2356 }
2357 mBluetoothGatt = null;
2358 } finally {
2359 mBluetoothLock.writeLock().unlock();
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002360 }
2361
2362 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2363 mState = BluetoothAdapter.STATE_OFF;
2364
Marie Janssen2977c3e2016-11-09 12:01:24 -08002365 if (clearBle) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002366 clearBleApps();
Marie Janssen2977c3e2016-11-09 12:01:24 -08002367 }
2368
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002369 mEnable = false;
2370
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002371 // Send a Bluetooth Restart message to reenable bluetooth
2372 Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
2373 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
Zhihai Xudd9d17d2013-01-08 17:05:58 -08002374 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002375
Lenka Trochtova63d5e4a72016-12-02 12:19:39 +01002376 private boolean isBluetoothDisallowed() {
2377 long callingIdentity = Binder.clearCallingIdentity();
2378 try {
2379 return mContext.getSystemService(UserManager.class)
2380 .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2381 } finally {
2382 Binder.restoreCallingIdentity(callingIdentity);
2383 }
2384 }
2385
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002386 /**
2387 * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002388 * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2389 * state if Bluetooth is not disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002390 *
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002391 * @param userId user to disable bluetooth sharing for.
2392 * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002393 */
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002394 private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002395 final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2396 "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002397 final int newState =
2398 bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2399 : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002400 try {
Pavel Grafov4f4f6f82017-03-28 13:44:04 +01002401 final IPackageManager imp = AppGlobals.getPackageManager();
Myles Watson6291fae2017-06-29 03:12:02 -07002402 imp.setComponentEnabledSetting(oppLauncherComponent, newState,
2403 PackageManager.DONT_KILL_APP, userId);
Lenka Trochtovac6f0e232017-01-17 10:35:49 +01002404 } catch (Exception e) {
2405 // The component was not found, do nothing.
2406 }
2407 }
2408
Ugo Yu1ff6fd32019-11-20 17:59:11 +08002409 private int getServiceRestartMs() {
2410 return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
2411 }
2412
Mike Lockwood726d4de2014-10-28 14:06:28 -07002413 @Override
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002414 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002415 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
2416 return;
2417 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002418 String errorMsg = null;
Marie Janssen59804562016-12-28 14:13:21 -08002419
2420 boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
2421
2422 if (!protoOut) {
2423 writer.println("Bluetooth Status");
2424 writer.println(" enabled: " + isEnabled());
2425 writer.println(" state: " + BluetoothAdapter.nameForState(mState));
2426 writer.println(" address: " + mAddress);
2427 writer.println(" name: " + mName);
2428 if (mEnable) {
Marie Janssen12a35012017-06-26 07:21:03 -07002429 long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002430 String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
2431 (int) (onDuration / (1000 * 60 * 60)),
2432 (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
2433 (int) (onDuration % 1000));
Andre Eisenbache66e1682017-04-10 13:49:13 -07002434 writer.println(" time since enabled: " + onDurationString);
Marie Janssen59804562016-12-28 14:13:21 -08002435 }
2436
Marie Janssena95924d2017-01-18 09:37:52 -08002437 if (mActiveLogs.size() == 0) {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002438 writer.println("\nBluetooth never enabled!");
Marie Janssena95924d2017-01-18 09:37:52 -08002439 } else {
Andre Eisenbache66e1682017-04-10 13:49:13 -07002440 writer.println("\nEnable log:");
Marie Janssena95924d2017-01-18 09:37:52 -08002441 for (ActiveLog log : mActiveLogs) {
2442 writer.println(" " + log);
2443 }
Marie Janssen59804562016-12-28 14:13:21 -08002444 }
2445
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002446 writer.println(
2447 "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2448 if (mCrashes == CRASH_LOG_MAX_SIZE) {
2449 writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2450 }
Marie Janssene54b4222017-03-16 18:10:59 -07002451 for (Long time : mCrashTimestamps) {
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002452 writer.println(" " + timeToLog(time));
Marie Janssene54b4222017-03-16 18:10:59 -07002453 }
2454
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002455 writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
2456 + "registered");
Marie Janssen59804562016-12-28 14:13:21 -08002457 for (ClientDeathRecipient app : mBleApps.values()) {
Marie Janssena95924d2017-01-18 09:37:52 -08002458 writer.println(" " + app.getPackageName());
Marie Janssen59804562016-12-28 14:13:21 -08002459 }
2460
Marie Janssena95924d2017-01-18 09:37:52 -08002461 writer.println("");
Marie Janssen59804562016-12-28 14:13:21 -08002462 writer.flush();
Marie Janssenf5ec5382017-01-03 11:37:38 -08002463 if (args.length == 0) {
Marie Janssena95924d2017-01-18 09:37:52 -08002464 // Add arg to produce output
2465 args = new String[1];
2466 args[0] = "--print";
Marie Janssenf5ec5382017-01-03 11:37:38 -08002467 }
Marie Janssen59804562016-12-28 14:13:21 -08002468 }
2469
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002470 if (mBluetoothBinder == null) {
2471 errorMsg = "Bluetooth Service not connected";
2472 } else {
2473 try {
2474 mBluetoothBinder.dump(fd, args);
2475 } catch (RemoteException re) {
Marie Janssen59804562016-12-28 14:13:21 -08002476 errorMsg = "RemoteException while dumping Bluetooth Service";
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002477 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002478 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002479 if (errorMsg != null) {
2480 // Silently return if we are extracting metrics in Protobuf format
Myles Watsonb5cd11a2017-11-27 16:42:11 -08002481 if (protoOut) {
2482 return;
2483 }
Pavlin Radoslavov6e8faff2016-02-23 11:54:37 -08002484 writer.println(errorMsg);
2485 }
Mike Lockwood726d4de2014-10-28 14:06:28 -07002486 }
Jack He8caab152018-03-02 13:08:36 -08002487
2488 private static String getEnableDisableReasonString(int reason) {
2489 switch (reason) {
2490 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
2491 return "APPLICATION_REQUEST";
2492 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
2493 return "AIRPLANE_MODE";
2494 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
2495 return "DISALLOWED";
2496 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
2497 return "RESTARTED";
2498 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
2499 return "START_ERROR";
2500 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
2501 return "SYSTEM_BOOT";
2502 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
2503 return "CRASH";
2504 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
2505 return "USER_SWITCH";
2506 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
2507 return "RESTORE_USER_SETTING";
2508 case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
2509 default: return "UNKNOWN[" + reason + "]";
2510 }
2511 }
fredc0f420372012-04-12 00:02:00 -07002512}