blob: 58aff1692d57abfb8fc963668fa2811d658409e2 [file] [log] [blame]
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -08001/*
2 * Copyright (C) 2017 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.
15 */
16
17package com.android.car;
18
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080019import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothDevice;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070021import android.car.VehicleAreaSeat;
22import android.car.VehicleAreaType;
23import android.car.VehiclePropertyIds;
24import android.car.VehicleSeatOccupancyState;
25import android.car.drivingstate.CarDrivingStateEvent;
Andrew Cheng04a95552021-04-01 14:42:14 -070026import android.car.hardware.CarPropertyConfig;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070027import android.car.hardware.CarPropertyValue;
Eric Jeong07a81f12021-02-12 17:58:13 -080028import android.car.hardware.power.CarPowerPolicy;
29import android.car.hardware.power.CarPowerPolicyFilter;
Eric Jeongd48f7072021-02-25 18:21:06 -080030import android.car.hardware.power.ICarPowerPolicyListener;
Eric Jeong07a81f12021-02-12 17:58:13 -080031import android.car.hardware.power.PowerComponent;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070032import android.car.hardware.property.CarPropertyEvent;
33import android.car.hardware.property.CarPropertyManager;
34import android.car.hardware.property.ICarPropertyEventListener;
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080035import android.content.BroadcastReceiver;
36import android.content.Context;
37import android.content.Intent;
38import android.content.IntentFilter;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070039import android.os.RemoteException;
Ram Periathiruvadie011a402018-03-22 18:54:33 -070040import android.os.UserHandle;
Joseph Pirozzo6b5c8dd2021-01-22 10:01:17 -080041import android.os.UserManager;
Ram Periathiruvadie011a402018-03-22 18:54:33 -070042import android.provider.Settings;
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080043import android.util.Log;
Eric Jeongbd5fb562020-12-21 13:49:40 -080044import android.util.Slog;
Ram Periathiruvadi83ee9012017-07-18 19:21:06 -070045
Eric Jeong07a81f12021-02-12 17:58:13 -080046import com.android.car.power.CarPowerManagementService;
Jim Kaye9c2a1552020-06-04 13:48:54 -070047import com.android.internal.annotations.VisibleForTesting;
48
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080049import java.io.PrintWriter;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070050import java.util.List;
Justin Pauporec813ead2018-12-28 20:18:25 -080051import java.util.Objects;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070052
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080053/**
Sal Savage703c46f2019-04-15 08:39:25 -070054 * A Bluetooth Device Connection policy that is specific to the use cases of a Car. Contains policy
55 * for deciding when to trigger connection and disconnection events.
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080056 */
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080057public class BluetoothDeviceConnectionPolicy {
Mayank Garg72c71d22021-02-03 23:54:45 -080058 private static final String TAG = CarLog.tagFor(BluetoothDeviceConnectionPolicy.class);
Sal Savage703c46f2019-04-15 08:39:25 -070059 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Justin Paupore7b17ea62018-12-28 20:27:33 -080060
Sal Savage703c46f2019-04-15 08:39:25 -070061 private final int mUserId;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070062 private final Context mContext;
Ram Periathiruvadiee28c002017-02-07 21:35:01 -080063 private final BluetoothAdapter mBluetoothAdapter;
Sal Savage703c46f2019-04-15 08:39:25 -070064 private final CarBluetoothService mCarBluetoothService;
Andrew Chengb7eaebe2020-10-02 08:31:55 -070065 private final CarServicesHelper mCarHelper;
Joseph Pirozzo6b5c8dd2021-01-22 10:01:17 -080066 private final UserManager mUserManager;
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -080067
Eric Jeongd48f7072021-02-25 18:21:06 -080068 private final ICarPowerPolicyListener mPowerPolicyListener =
69 new ICarPowerPolicyListener.Stub() {
Jim Kaye9c2a1552020-06-04 13:48:54 -070070 @Override
Eric Jeong8f0d3c42021-03-16 20:12:24 -070071 public void onPolicyChanged(CarPowerPolicy appliedPolicy,
72 CarPowerPolicy accumulatedPolicy) {
73 boolean isOn = accumulatedPolicy.isComponentEnabled(PowerComponent.BLUETOOTH);
Joseph Pirozzo6b5c8dd2021-01-22 10:01:17 -080074 if (!mUserManager.isUserUnlocked(mUserId)) {
Eric Jeong07a81f12021-02-12 17:58:13 -080075 logd("User " + mUserId + " is locked, ignoring bluetooth power change "
76 + (isOn ? "on" : "off"));
Joseph Pirozzo6b5c8dd2021-01-22 10:01:17 -080077 return;
78 }
Eric Jeong07a81f12021-02-12 17:58:13 -080079 if (isOn) {
Jim Kaye9c2a1552020-06-04 13:48:54 -070080 if (isBluetoothPersistedOn()) {
81 enableBluetooth();
82 }
83 // The above isBluetoothPersistedOn() call is always true when the
84 // adapter is on, but can be true or false if the adapter is off. If we
85 // turned the adapter back on then this connectDevices() call would fail
86 // at first here but be caught by the following adapter on broadcast
87 // below. We'll only do this if the adapter is on.
88 if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
89 connectDevices();
90 }
Eric Jeong07a81f12021-02-12 17:58:13 -080091 } else {
92 // we'll turn off Bluetooth to disconnect devices and better the "off"
93 // illusion
94 logd("Car power policy turns off bluetooth. Disable bluetooth adapter");
95 disableBluetooth();
Jim Kaye9c2a1552020-06-04 13:48:54 -070096 }
Sal Savageed6b04e2019-03-15 13:27:27 -070097 }
Sal Savageed6b04e2019-03-15 13:27:27 -070098 };
99
Jim Kaye9c2a1552020-06-04 13:48:54 -0700100 @VisibleForTesting
Eric Jeongd48f7072021-02-25 18:21:06 -0800101 public ICarPowerPolicyListener getPowerPolicyListener() {
102 return mPowerPolicyListener;
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800103 }
104
105 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700106 * A BroadcastReceiver that listens specifically for actions related to the profile we're
107 * tracking and uses them to update the status.
108 *
109 * On BluetoothAdapter.ACTION_STATE_CHANGED:
110 * If the adapter is going into the ON state, then commit trigger auto connection.
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800111 */
Sal Savage703c46f2019-04-15 08:39:25 -0700112 private class BluetoothBroadcastReceiver extends BroadcastReceiver {
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800113 @Override
114 public void onReceive(Context context, Intent intent) {
115 String action = intent.getAction();
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800116 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Sal Savage703c46f2019-04-15 08:39:25 -0700117 if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
118 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700119 logd("Bluetooth Adapter state changed: ", Utils.getAdapterStateName(state));
Sal Savage703c46f2019-04-15 08:39:25 -0700120 if (state == BluetoothAdapter.STATE_ON) {
121 connectDevices();
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700122 }
123 }
Sal Savage703c46f2019-04-15 08:39:25 -0700124 }
125 }
Sal Savage6c101292019-11-14 15:30:18 -0800126 private final BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800127
Sal Savage703c46f2019-04-15 08:39:25 -0700128 /**
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700129 * A helper class to interact with the VHAL and the rest of the car.
130 */
Andrew Cheng04a95552021-04-01 14:42:14 -0700131 final class CarServicesHelper {
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700132 private final CarPropertyService mCarPropertyService;
133 private final CarDrivingStateService mCarDrivingStateService;
134
135 // Location of the driver's seat, e.g., left or right side.
136 private final int mDriverSeat;
137
138 CarServicesHelper() {
139 mCarPropertyService = CarLocalServices.getService(CarPropertyService.class);
Eric Jeongbd5fb562020-12-21 13:49:40 -0800140 if (mCarPropertyService == null) Slog.w(TAG, "Cannot find CarPropertyService");
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700141 mDriverSeat = getDriverSeatLocationFromVhal();
142 mCarDrivingStateService = CarLocalServices.getService(CarDrivingStateService.class);
Eric Jeongbd5fb562020-12-21 13:49:40 -0800143 if (mCarDrivingStateService == null) Slog.w(TAG, "Cannot find mCarDrivingStateService");
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700144 }
145
146 /**
147 * Set up vehicle event listeners. Remember to call {@link release()} when done.
148 */
149 public void init() {
150 if (mCarPropertyService != null) {
151 mCarPropertyService.registerListener(VehiclePropertyIds.SEAT_OCCUPANCY,
152 CarPropertyManager.SENSOR_RATE_ONCHANGE, mSeatOnOccupiedListener);
153 }
154 }
155
156 public void release() {
157 if (mCarPropertyService != null) {
158 mCarPropertyService.unregisterListener(VehiclePropertyIds.SEAT_OCCUPANCY,
159 mSeatOnOccupiedListener);
160 }
161 }
162
163 /**
164 * A {@code ICarPropertyEventListener} that triggers the auto-connection process when
165 * {@code SEAT_OCCUPANCY} is {@code OCCUPIED}.
166 */
167 private final ICarPropertyEventListener mSeatOnOccupiedListener =
168 new ICarPropertyEventListener.Stub() {
169 @Override
170 public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
171 for (CarPropertyEvent event : events) {
172 onSeatOccupancyCarPropertyEvent(event);
173 }
174 }
175 };
176
177 /**
178 * Acts on {@link CarPropertyEvent} events marked with
179 * {@link CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE} and marked with {@link
180 * VehiclePropertyIds.SEAT_OCCUPANCY} by calling {@link connectDevices}.
181 * <p>
182 * Default implementation filters on driver's seat only, but can change to trigger on
183 * any front row seat, or any seat in the car.
184 * <p>
185 * Default implementation also restricts this trigger to when the car is in the
186 * parked state, to discourage drivers from exploiting to connect while driving, and to
187 * also filter out spurious seat sensor signals while driving.
188 * <p>
189 * This method does nothing if the event parameter is {@code null}.
190 *
191 * @param event - The {@link CarPropertyEvent} to be handled.
192 */
193 private void onSeatOccupancyCarPropertyEvent(CarPropertyEvent event) {
194 if ((event == null)
195 || (event.getEventType() != CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE)) {
196 return;
197 }
198 CarPropertyValue value = event.getCarPropertyValue();
199 logd("Car property changed: ", value.toString());
200 if (mBluetoothAdapter.isEnabled()
201 && (value.getPropertyId() == VehiclePropertyIds.SEAT_OCCUPANCY)
202 && ((int) value.getValue() == VehicleSeatOccupancyState.OCCUPIED)
203 && (value.getAreaId() == mDriverSeat)
204 && isParked()) {
205 connectDevices();
206 }
207 }
208
209 /**
210 * Gets the location of the driver's seat (e.g., front-left, front-right) from the VHAL.
211 * <p>
212 * Default implementation sets the driver's seat to front-left if mCarPropertyService is
213 * not found.
214 * <p>
215 * Note, comments for {@link CarPropertyManager#getIntProperty(int, int)} indicate it may
216 * take a couple of seconds to complete, whereas there are no such comments for
Kai Wang301dd472021-05-18 06:09:44 +0000217 * {@link CarPropertyService#getPropertySafe(int, int)}, but we assume there is also similar
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700218 * latency in querying VHAL properties.
219 *
220 * @return An {@code int} representing driver's seat location.
221 */
222 private int getDriverSeatLocationFromVhal() {
Andrew Cheng04a95552021-04-01 14:42:14 -0700223 int defaultLocation = VehicleAreaSeat.SEAT_ROW_1_LEFT;
224
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700225 if (mCarPropertyService == null) {
Andrew Cheng04a95552021-04-01 14:42:14 -0700226 return defaultLocation;
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700227 }
Kai Wang301dd472021-05-18 06:09:44 +0000228 CarPropertyValue value = mCarPropertyService.getPropertySafe(
Andrew Cheng04a95552021-04-01 14:42:14 -0700229 VehiclePropertyIds.INFO_DRIVER_SEAT, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
230 if (value == null) {
231 // Distinguish between two possible causes for null, based on
232 // {@code mConfigs.get(prop)} in {@link CarPropertyService#getProperty} and
233 // {@link CarPropertyService#getPropertyConfigList}
234 List<CarPropertyConfig> availableProp = mCarPropertyService.getPropertyConfigList(
235 new int[] {VehiclePropertyIds.INFO_DRIVER_SEAT});
236 if (availableProp.isEmpty() || availableProp.get(0) == null) {
237 logd("Driver seat location property is not in config list.");
238 } else {
239 logd("Driver seat location property is not ready yet.");
240 }
241 return defaultLocation;
242 }
243 return (int) value.getValue();
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700244 }
245
246 public int getDriverSeatLocation() {
247 return mDriverSeat;
248 }
249
250 /**
251 * Returns {@code true} if the car is in parked gear.
252 * <p>
253 * We are being conservative and only want to trigger when car is in parked state. Extending
254 * this conservative approach, we default return false if {@code mCarDrivingStateService}
Andrew Cheng04a95552021-04-01 14:42:14 -0700255 * is not found, or if we otherwise can't get the value.
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700256 */
257 public boolean isParked() {
258 if (mCarDrivingStateService == null) {
259 return false;
260 }
Andrew Cheng04a95552021-04-01 14:42:14 -0700261 CarDrivingStateEvent event = mCarDrivingStateService.getCurrentDrivingState();
262 if (event == null) {
263 return false;
264 }
265 return event.eventValue == CarDrivingStateEvent.DRIVING_STATE_PARKED;
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700266 }
267 }
268
269 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700270 * Create a new BluetoothDeviceConnectionPolicy object, responsible for encapsulating the
271 * default policy for when to initiate device connections given the list of prioritized devices
272 * for each profile.
273 *
274 * @param context - The context of the creating application
275 * @param userId - The user ID we're operating as
276 * @param bluetoothService - A reference to CarBluetoothService so we can connect devices
277 * @return A new instance of a BluetoothProfileDeviceManager, or null on any error
278 */
279 public static BluetoothDeviceConnectionPolicy create(Context context, int userId,
280 CarBluetoothService bluetoothService) {
281 try {
282 return new BluetoothDeviceConnectionPolicy(context, userId, bluetoothService);
283 } catch (NullPointerException e) {
284 return null;
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700285 }
286 }
287
288 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700289 * Create a new BluetoothDeviceConnectionPolicy object, responsible for encapsulating the
290 * default policy for when to initiate device connections given the list of prioritized devices
291 * for each profile.
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700292 *
Sal Savage703c46f2019-04-15 08:39:25 -0700293 * @param context - The context of the creating application
294 * @param userId - The user ID we're operating as
295 * @param bluetoothService - A reference to CarBluetoothService so we can connect devices
296 * @return A new instance of a BluetoothProfileDeviceManager
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700297 */
Sal Savage703c46f2019-04-15 08:39:25 -0700298 private BluetoothDeviceConnectionPolicy(Context context, int userId,
299 CarBluetoothService bluetoothService) {
300 mUserId = userId;
301 mContext = Objects.requireNonNull(context);
302 mCarBluetoothService = bluetoothService;
Sal Savage6c101292019-11-14 15:30:18 -0800303 mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
Sal Savage703c46f2019-04-15 08:39:25 -0700304 mBluetoothAdapter = Objects.requireNonNull(BluetoothAdapter.getDefaultAdapter());
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700305 mCarHelper = new CarServicesHelper();
Joseph Pirozzo6b5c8dd2021-01-22 10:01:17 -0800306 mUserManager = mContext.getSystemService(UserManager.class);
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700307 }
308
309 /**
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800310 * Setup the Bluetooth profile service connections and Vehicle Event listeners.
311 * and start the state machine -{@link BluetoothAutoConnectStateMachine}
312 */
Sal Savage6c101292019-11-14 15:30:18 -0800313 public void init() {
Sal Savage703c46f2019-04-15 08:39:25 -0700314 logd("init()");
Pavel Maltsevc9e86e82017-03-22 11:37:21 -0700315 IntentFilter profileFilter = new IntentFilter();
Pavel Maltsevc9e86e82017-03-22 11:37:21 -0700316 profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Sal Savage703c46f2019-04-15 08:39:25 -0700317 mContext.registerReceiverAsUser(mBluetoothBroadcastReceiver, UserHandle.CURRENT,
318 profileFilter, null, null);
Eric Jeong07a81f12021-02-12 17:58:13 -0800319 CarPowerManagementService cpms = CarLocalServices.getService(
320 CarPowerManagementService.class);
321 if (cpms != null) {
322 CarPowerPolicyFilter filter = new CarPowerPolicyFilter.Builder()
Eric Jeong72c850d2021-04-12 15:29:15 -0700323 .setComponents(PowerComponent.BLUETOOTH).build();
Eric Jeongd48f7072021-02-25 18:21:06 -0800324 cpms.addPowerPolicyListener(filter, mPowerPolicyListener);
Ram Periathiruvadie011a402018-03-22 18:54:33 -0700325 } else {
Eric Jeong07a81f12021-02-12 17:58:13 -0800326 Slog.w(TAG, "Cannot find CarPowerManagementService");
Sal Savage703c46f2019-04-15 08:39:25 -0700327 }
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700328 mCarHelper.init();
Sal Savage703c46f2019-04-15 08:39:25 -0700329
330 // Since we do this only on start up and on user switch, it's safe to kick off a connect on
331 // init. If we have a connect in progress, this won't hurt anything. If we already have
332 // devices connected, this will add on top of it. We _could_ enter this from a crash
333 // recovery, but that would at worst cause more devices to connect and wouldn't change the
334 // existing devices.
335 if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
336 // CarPowerManager doesn't provide a getState() or that would go here too.
337 connectDevices();
Ram Periathiruvadie011a402018-03-22 18:54:33 -0700338 }
339 }
340
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800341 /**
342 * Clean up slate. Close the Bluetooth profile service connections and quit the state machine -
343 * {@link BluetoothAutoConnectStateMachine}
344 */
Sal Savage6c101292019-11-14 15:30:18 -0800345 public void release() {
Sal Savage703c46f2019-04-15 08:39:25 -0700346 logd("release()");
Eric Jeong07a81f12021-02-12 17:58:13 -0800347 CarPowerManagementService cpms =
348 CarLocalServices.getService(CarPowerManagementService.class);
349 if (cpms != null) {
Eric Jeongd48f7072021-02-25 18:21:06 -0800350 cpms.removePowerPolicyListener(mPowerPolicyListener);
Ram Periathiruvadiee28c002017-02-07 21:35:01 -0800351 }
Sal Savage703c46f2019-04-15 08:39:25 -0700352 if (mBluetoothBroadcastReceiver != null) {
353 mContext.unregisterReceiver(mBluetoothBroadcastReceiver);
Ram Periathiruvadia048c0a2017-05-09 07:35:03 -0700354 }
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700355 mCarHelper.release();
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800356 }
357
358 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700359 * Tell each Profile device manager that its time to begin auto connecting devices
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800360 */
Sal Savage703c46f2019-04-15 08:39:25 -0700361 public void connectDevices() {
362 logd("Connect devices for each profile");
363 mCarBluetoothService.connectDevices();
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800364 }
365
366 /**
Sal Savageed6b04e2019-03-15 13:27:27 -0700367 * Get the persisted Bluetooth state from Settings
Sal Savage703c46f2019-04-15 08:39:25 -0700368 *
369 * @return True if the persisted Bluetooth state is on, false otherwise
Sal Savageed6b04e2019-03-15 13:27:27 -0700370 */
371 private boolean isBluetoothPersistedOn() {
372 return (Settings.Global.getInt(
373 mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, -1) != 0);
374 }
375
376 /**
377 * Turn on the Bluetooth Adapter.
378 */
Sal Savage703c46f2019-04-15 08:39:25 -0700379 private void enableBluetooth() {
380 logd("Enable bluetooth adapter");
Sal Savageed6b04e2019-03-15 13:27:27 -0700381 if (mBluetoothAdapter == null) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800382 Slog.e(TAG, "Cannot enable Bluetooth adapter. The object is null.");
Sal Savageed6b04e2019-03-15 13:27:27 -0700383 return;
384 }
385 mBluetoothAdapter.enable();
386 }
387
388 /**
389 * Turn off the Bluetooth Adapter.
390 *
391 * Tells BluetoothAdapter to shut down _without_ persisting the off state as the desired state
392 * of the Bluetooth adapter for next start up.
393 */
394 private void disableBluetooth() {
Sal Savage703c46f2019-04-15 08:39:25 -0700395 logd("Disable bluetooth, do not persist state across reboot");
Sal Savageed6b04e2019-03-15 13:27:27 -0700396 if (mBluetoothAdapter == null) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800397 Slog.e(TAG, "Cannot disable Bluetooth adapter. The object is null.");
Sal Savageed6b04e2019-03-15 13:27:27 -0700398 return;
399 }
400 mBluetoothAdapter.disable(false);
401 }
402
403 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700404 * Print the verbose status of the object
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800405 */
Sal Savage6c101292019-11-14 15:30:18 -0800406 public void dump(PrintWriter writer, String indent) {
Sal Savage703c46f2019-04-15 08:39:25 -0700407 writer.println(indent + TAG + ":");
408 writer.println(indent + "\tUserId: " + mUserId);
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700409 }
410
411 /**
Sal Savage703c46f2019-04-15 08:39:25 -0700412 * Print to debug if debug is enabled
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700413 */
Andrew Chengb7eaebe2020-10-02 08:31:55 -0700414 private static void logd(String... msgParts) {
Ram Periathiruvadiee28c002017-02-07 21:35:01 -0800415 if (DBG) {
Eric Jeongbd5fb562020-12-21 13:49:40 -0800416 Slog.d(TAG, String.join(" ", msgParts));
Ram Periathiruvadiee28c002017-02-07 21:35:01 -0800417 }
Ram Periathiruvadi7ed84182017-01-20 15:18:08 -0800418 }
419}