Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.car; |
| 18 | |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 19 | import android.bluetooth.BluetoothAdapter; |
| 20 | import android.bluetooth.BluetoothDevice; |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 21 | import android.car.VehicleAreaSeat; |
| 22 | import android.car.VehicleAreaType; |
| 23 | import android.car.VehiclePropertyIds; |
| 24 | import android.car.VehicleSeatOccupancyState; |
| 25 | import android.car.drivingstate.CarDrivingStateEvent; |
| 26 | import android.car.hardware.CarPropertyValue; |
| 27 | import android.car.hardware.property.CarPropertyEvent; |
| 28 | import android.car.hardware.property.CarPropertyManager; |
| 29 | import android.car.hardware.property.ICarPropertyEventListener; |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 30 | import android.content.BroadcastReceiver; |
| 31 | import android.content.Context; |
| 32 | import android.content.Intent; |
| 33 | import android.content.IntentFilter; |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 34 | import android.os.RemoteException; |
Ram Periathiruvadi | e011a40 | 2018-03-22 18:54:33 -0700 | [diff] [blame] | 35 | import android.os.UserHandle; |
Joseph Pirozzo | 6b5c8dd | 2021-01-22 10:01:17 -0800 | [diff] [blame] | 36 | import android.os.UserManager; |
Ram Periathiruvadi | e011a40 | 2018-03-22 18:54:33 -0700 | [diff] [blame] | 37 | import android.provider.Settings; |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 38 | import android.util.Log; |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 39 | import android.util.Slog; |
Ram Periathiruvadi | 83ee901 | 2017-07-18 19:21:06 -0700 | [diff] [blame] | 40 | |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 41 | import com.android.car.power.SilentModeController; |
| 42 | import com.android.internal.annotations.VisibleForTesting; |
| 43 | |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 44 | import java.io.PrintWriter; |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 45 | import java.util.List; |
Justin Paupore | c813ead | 2018-12-28 20:18:25 -0800 | [diff] [blame] | 46 | import java.util.Objects; |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 47 | |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 48 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 49 | * A Bluetooth Device Connection policy that is specific to the use cases of a Car. Contains policy |
| 50 | * for deciding when to trigger connection and disconnection events. |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 51 | */ |
| 52 | |
| 53 | public class BluetoothDeviceConnectionPolicy { |
Mayank Garg | 72c71d2 | 2021-02-03 23:54:45 -0800 | [diff] [blame^] | 54 | private static final String TAG = CarLog.tagFor(BluetoothDeviceConnectionPolicy.class); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 55 | private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); |
Justin Paupore | 7b17ea6 | 2018-12-28 20:27:33 -0800 | [diff] [blame] | 56 | |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 57 | private final int mUserId; |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 58 | private final Context mContext; |
Ram Periathiruvadi | ee28c00 | 2017-02-07 21:35:01 -0800 | [diff] [blame] | 59 | private final BluetoothAdapter mBluetoothAdapter; |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 60 | private final CarBluetoothService mCarBluetoothService; |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 61 | private final CarServicesHelper mCarHelper; |
Joseph Pirozzo | 6b5c8dd | 2021-01-22 10:01:17 -0800 | [diff] [blame] | 62 | private final UserManager mUserManager; |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 63 | |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 64 | private final SilentModeController.SilentModeListener mSilentModeListener = |
| 65 | new SilentModeController.SilentModeListener() { |
| 66 | @Override |
| 67 | public void onModeChange(boolean isSilent) { |
Joseph Pirozzo | 6b5c8dd | 2021-01-22 10:01:17 -0800 | [diff] [blame] | 68 | if (!mUserManager.isUserUnlocked(mUserId)) { |
| 69 | logd("User " + mUserId + " is locked, ignoring silent mode " + isSilent); |
| 70 | return; |
| 71 | } |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 72 | if (isSilent) { |
| 73 | // we'll turn off Bluetooth to disconnect devices and better the "off" |
| 74 | // illusion |
| 75 | logd("Car is going silent. Disable bluetooth adapter"); |
| 76 | disableBluetooth(); |
| 77 | } else { |
| 78 | if (isBluetoothPersistedOn()) { |
| 79 | enableBluetooth(); |
| 80 | } |
| 81 | // The above isBluetoothPersistedOn() call is always true when the |
| 82 | // adapter is on, but can be true or false if the adapter is off. If we |
| 83 | // turned the adapter back on then this connectDevices() call would fail |
| 84 | // at first here but be caught by the following adapter on broadcast |
| 85 | // below. We'll only do this if the adapter is on. |
| 86 | if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { |
| 87 | connectDevices(); |
| 88 | } |
| 89 | } |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 90 | } |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 91 | }; |
| 92 | |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 93 | @VisibleForTesting |
| 94 | public SilentModeController.SilentModeListener getSilentModeListener() { |
| 95 | return mSilentModeListener; |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 99 | * A BroadcastReceiver that listens specifically for actions related to the profile we're |
| 100 | * tracking and uses them to update the status. |
| 101 | * |
| 102 | * On BluetoothAdapter.ACTION_STATE_CHANGED: |
| 103 | * If the adapter is going into the ON state, then commit trigger auto connection. |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 104 | */ |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 105 | private class BluetoothBroadcastReceiver extends BroadcastReceiver { |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 106 | @Override |
| 107 | public void onReceive(Context context, Intent intent) { |
| 108 | String action = intent.getAction(); |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 109 | BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 110 | if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { |
| 111 | int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 112 | logd("Bluetooth Adapter state changed: ", Utils.getAdapterStateName(state)); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 113 | if (state == BluetoothAdapter.STATE_ON) { |
| 114 | connectDevices(); |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 115 | } |
| 116 | } |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 117 | } |
| 118 | } |
Sal Savage | 6c10129 | 2019-11-14 15:30:18 -0800 | [diff] [blame] | 119 | private final BluetoothBroadcastReceiver mBluetoothBroadcastReceiver; |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 120 | |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 121 | /** |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 122 | * A helper class to interact with the VHAL and the rest of the car. |
| 123 | */ |
| 124 | private final class CarServicesHelper { |
| 125 | private final CarPropertyService mCarPropertyService; |
| 126 | private final CarDrivingStateService mCarDrivingStateService; |
| 127 | |
| 128 | // Location of the driver's seat, e.g., left or right side. |
| 129 | private final int mDriverSeat; |
| 130 | |
| 131 | CarServicesHelper() { |
| 132 | mCarPropertyService = CarLocalServices.getService(CarPropertyService.class); |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 133 | if (mCarPropertyService == null) Slog.w(TAG, "Cannot find CarPropertyService"); |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 134 | mDriverSeat = getDriverSeatLocationFromVhal(); |
| 135 | mCarDrivingStateService = CarLocalServices.getService(CarDrivingStateService.class); |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 136 | if (mCarDrivingStateService == null) Slog.w(TAG, "Cannot find mCarDrivingStateService"); |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | /** |
| 140 | * Set up vehicle event listeners. Remember to call {@link release()} when done. |
| 141 | */ |
| 142 | public void init() { |
| 143 | if (mCarPropertyService != null) { |
| 144 | mCarPropertyService.registerListener(VehiclePropertyIds.SEAT_OCCUPANCY, |
| 145 | CarPropertyManager.SENSOR_RATE_ONCHANGE, mSeatOnOccupiedListener); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | public void release() { |
| 150 | if (mCarPropertyService != null) { |
| 151 | mCarPropertyService.unregisterListener(VehiclePropertyIds.SEAT_OCCUPANCY, |
| 152 | mSeatOnOccupiedListener); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | /** |
| 157 | * A {@code ICarPropertyEventListener} that triggers the auto-connection process when |
| 158 | * {@code SEAT_OCCUPANCY} is {@code OCCUPIED}. |
| 159 | */ |
| 160 | private final ICarPropertyEventListener mSeatOnOccupiedListener = |
| 161 | new ICarPropertyEventListener.Stub() { |
| 162 | @Override |
| 163 | public void onEvent(List<CarPropertyEvent> events) throws RemoteException { |
| 164 | for (CarPropertyEvent event : events) { |
| 165 | onSeatOccupancyCarPropertyEvent(event); |
| 166 | } |
| 167 | } |
| 168 | }; |
| 169 | |
| 170 | /** |
| 171 | * Acts on {@link CarPropertyEvent} events marked with |
| 172 | * {@link CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE} and marked with {@link |
| 173 | * VehiclePropertyIds.SEAT_OCCUPANCY} by calling {@link connectDevices}. |
| 174 | * <p> |
| 175 | * Default implementation filters on driver's seat only, but can change to trigger on |
| 176 | * any front row seat, or any seat in the car. |
| 177 | * <p> |
| 178 | * Default implementation also restricts this trigger to when the car is in the |
| 179 | * parked state, to discourage drivers from exploiting to connect while driving, and to |
| 180 | * also filter out spurious seat sensor signals while driving. |
| 181 | * <p> |
| 182 | * This method does nothing if the event parameter is {@code null}. |
| 183 | * |
| 184 | * @param event - The {@link CarPropertyEvent} to be handled. |
| 185 | */ |
| 186 | private void onSeatOccupancyCarPropertyEvent(CarPropertyEvent event) { |
| 187 | if ((event == null) |
| 188 | || (event.getEventType() != CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE)) { |
| 189 | return; |
| 190 | } |
| 191 | CarPropertyValue value = event.getCarPropertyValue(); |
| 192 | logd("Car property changed: ", value.toString()); |
| 193 | if (mBluetoothAdapter.isEnabled() |
| 194 | && (value.getPropertyId() == VehiclePropertyIds.SEAT_OCCUPANCY) |
| 195 | && ((int) value.getValue() == VehicleSeatOccupancyState.OCCUPIED) |
| 196 | && (value.getAreaId() == mDriverSeat) |
| 197 | && isParked()) { |
| 198 | connectDevices(); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | /** |
| 203 | * Gets the location of the driver's seat (e.g., front-left, front-right) from the VHAL. |
| 204 | * <p> |
| 205 | * Default implementation sets the driver's seat to front-left if mCarPropertyService is |
| 206 | * not found. |
| 207 | * <p> |
| 208 | * Note, comments for {@link CarPropertyManager#getIntProperty(int, int)} indicate it may |
| 209 | * take a couple of seconds to complete, whereas there are no such comments for |
| 210 | * {@link CarPropertyService#getProperty(int, int)}, but we assume there is also similar |
| 211 | * latency in querying VHAL properties. |
| 212 | * |
| 213 | * @return An {@code int} representing driver's seat location. |
| 214 | */ |
| 215 | private int getDriverSeatLocationFromVhal() { |
| 216 | if (mCarPropertyService == null) { |
| 217 | return VehicleAreaSeat.SEAT_ROW_1_LEFT; |
| 218 | } |
| 219 | return (int) mCarPropertyService.getProperty(VehiclePropertyIds.INFO_DRIVER_SEAT, |
| 220 | VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL).getValue(); |
| 221 | } |
| 222 | |
| 223 | public int getDriverSeatLocation() { |
| 224 | return mDriverSeat; |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * Returns {@code true} if the car is in parked gear. |
| 229 | * <p> |
| 230 | * We are being conservative and only want to trigger when car is in parked state. Extending |
| 231 | * this conservative approach, we default return false if {@code mCarDrivingStateService} |
| 232 | * is not found. |
| 233 | */ |
| 234 | public boolean isParked() { |
| 235 | if (mCarDrivingStateService == null) { |
| 236 | return false; |
| 237 | } |
| 238 | return mCarDrivingStateService.getCurrentDrivingState().eventValue |
| 239 | == CarDrivingStateEvent.DRIVING_STATE_PARKED; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 244 | * Create a new BluetoothDeviceConnectionPolicy object, responsible for encapsulating the |
| 245 | * default policy for when to initiate device connections given the list of prioritized devices |
| 246 | * for each profile. |
| 247 | * |
| 248 | * @param context - The context of the creating application |
| 249 | * @param userId - The user ID we're operating as |
| 250 | * @param bluetoothService - A reference to CarBluetoothService so we can connect devices |
| 251 | * @return A new instance of a BluetoothProfileDeviceManager, or null on any error |
| 252 | */ |
| 253 | public static BluetoothDeviceConnectionPolicy create(Context context, int userId, |
| 254 | CarBluetoothService bluetoothService) { |
| 255 | try { |
| 256 | return new BluetoothDeviceConnectionPolicy(context, userId, bluetoothService); |
| 257 | } catch (NullPointerException e) { |
| 258 | return null; |
Ram Periathiruvadi | be7ea0fe | 2017-05-31 23:31:40 -0700 | [diff] [blame] | 259 | } |
| 260 | } |
| 261 | |
| 262 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 263 | * Create a new BluetoothDeviceConnectionPolicy object, responsible for encapsulating the |
| 264 | * default policy for when to initiate device connections given the list of prioritized devices |
| 265 | * for each profile. |
Ram Periathiruvadi | be7ea0fe | 2017-05-31 23:31:40 -0700 | [diff] [blame] | 266 | * |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 267 | * @param context - The context of the creating application |
| 268 | * @param userId - The user ID we're operating as |
| 269 | * @param bluetoothService - A reference to CarBluetoothService so we can connect devices |
| 270 | * @return A new instance of a BluetoothProfileDeviceManager |
Ram Periathiruvadi | be7ea0fe | 2017-05-31 23:31:40 -0700 | [diff] [blame] | 271 | */ |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 272 | private BluetoothDeviceConnectionPolicy(Context context, int userId, |
| 273 | CarBluetoothService bluetoothService) { |
| 274 | mUserId = userId; |
| 275 | mContext = Objects.requireNonNull(context); |
| 276 | mCarBluetoothService = bluetoothService; |
Sal Savage | 6c10129 | 2019-11-14 15:30:18 -0800 | [diff] [blame] | 277 | mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver(); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 278 | mBluetoothAdapter = Objects.requireNonNull(BluetoothAdapter.getDefaultAdapter()); |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 279 | mCarHelper = new CarServicesHelper(); |
Joseph Pirozzo | 6b5c8dd | 2021-01-22 10:01:17 -0800 | [diff] [blame] | 280 | mUserManager = mContext.getSystemService(UserManager.class); |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 281 | } |
| 282 | |
| 283 | /** |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 284 | * Setup the Bluetooth profile service connections and Vehicle Event listeners. |
| 285 | * and start the state machine -{@link BluetoothAutoConnectStateMachine} |
| 286 | */ |
Sal Savage | 6c10129 | 2019-11-14 15:30:18 -0800 | [diff] [blame] | 287 | public void init() { |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 288 | logd("init()"); |
Pavel Maltsev | c9e86e8 | 2017-03-22 11:37:21 -0700 | [diff] [blame] | 289 | IntentFilter profileFilter = new IntentFilter(); |
Pavel Maltsev | c9e86e8 | 2017-03-22 11:37:21 -0700 | [diff] [blame] | 290 | profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 291 | mContext.registerReceiverAsUser(mBluetoothBroadcastReceiver, UserHandle.CURRENT, |
| 292 | profileFilter, null, null); |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 293 | SilentModeController silentModeController = CarLocalServices.getService( |
| 294 | SilentModeController.class); |
| 295 | if (silentModeController != null) { |
| 296 | silentModeController.registerListener(mSilentModeListener); |
Ram Periathiruvadi | e011a40 | 2018-03-22 18:54:33 -0700 | [diff] [blame] | 297 | } else { |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 298 | Slog.w(TAG, "Cannot find SilentModeController"); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 299 | } |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 300 | mCarHelper.init(); |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 301 | |
| 302 | // Since we do this only on start up and on user switch, it's safe to kick off a connect on |
| 303 | // init. If we have a connect in progress, this won't hurt anything. If we already have |
| 304 | // devices connected, this will add on top of it. We _could_ enter this from a crash |
| 305 | // recovery, but that would at worst cause more devices to connect and wouldn't change the |
| 306 | // existing devices. |
| 307 | if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { |
| 308 | // CarPowerManager doesn't provide a getState() or that would go here too. |
| 309 | connectDevices(); |
Ram Periathiruvadi | e011a40 | 2018-03-22 18:54:33 -0700 | [diff] [blame] | 310 | } |
| 311 | } |
| 312 | |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 313 | /** |
| 314 | * Clean up slate. Close the Bluetooth profile service connections and quit the state machine - |
| 315 | * {@link BluetoothAutoConnectStateMachine} |
| 316 | */ |
Sal Savage | 6c10129 | 2019-11-14 15:30:18 -0800 | [diff] [blame] | 317 | public void release() { |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 318 | logd("release()"); |
Jim Kaye | 9c2a155 | 2020-06-04 13:48:54 -0700 | [diff] [blame] | 319 | SilentModeController silentModeController = |
| 320 | CarLocalServices.getService(SilentModeController.class); |
| 321 | if (silentModeController != null) { |
| 322 | silentModeController.unregisterListener(mSilentModeListener); |
Ram Periathiruvadi | ee28c00 | 2017-02-07 21:35:01 -0800 | [diff] [blame] | 323 | } |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 324 | if (mBluetoothBroadcastReceiver != null) { |
| 325 | mContext.unregisterReceiver(mBluetoothBroadcastReceiver); |
Ram Periathiruvadi | a048c0a | 2017-05-09 07:35:03 -0700 | [diff] [blame] | 326 | } |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 327 | mCarHelper.release(); |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 328 | } |
| 329 | |
| 330 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 331 | * Tell each Profile device manager that its time to begin auto connecting devices |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 332 | */ |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 333 | public void connectDevices() { |
| 334 | logd("Connect devices for each profile"); |
| 335 | mCarBluetoothService.connectDevices(); |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 336 | } |
| 337 | |
| 338 | /** |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 339 | * Get the persisted Bluetooth state from Settings |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 340 | * |
| 341 | * @return True if the persisted Bluetooth state is on, false otherwise |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 342 | */ |
| 343 | private boolean isBluetoothPersistedOn() { |
| 344 | return (Settings.Global.getInt( |
| 345 | mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, -1) != 0); |
| 346 | } |
| 347 | |
| 348 | /** |
| 349 | * Turn on the Bluetooth Adapter. |
| 350 | */ |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 351 | private void enableBluetooth() { |
| 352 | logd("Enable bluetooth adapter"); |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 353 | if (mBluetoothAdapter == null) { |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 354 | Slog.e(TAG, "Cannot enable Bluetooth adapter. The object is null."); |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 355 | return; |
| 356 | } |
| 357 | mBluetoothAdapter.enable(); |
| 358 | } |
| 359 | |
| 360 | /** |
| 361 | * Turn off the Bluetooth Adapter. |
| 362 | * |
| 363 | * Tells BluetoothAdapter to shut down _without_ persisting the off state as the desired state |
| 364 | * of the Bluetooth adapter for next start up. |
| 365 | */ |
| 366 | private void disableBluetooth() { |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 367 | logd("Disable bluetooth, do not persist state across reboot"); |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 368 | if (mBluetoothAdapter == null) { |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 369 | Slog.e(TAG, "Cannot disable Bluetooth adapter. The object is null."); |
Sal Savage | ed6b04e | 2019-03-15 13:27:27 -0700 | [diff] [blame] | 370 | return; |
| 371 | } |
| 372 | mBluetoothAdapter.disable(false); |
| 373 | } |
| 374 | |
| 375 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 376 | * Print the verbose status of the object |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 377 | */ |
Sal Savage | 6c10129 | 2019-11-14 15:30:18 -0800 | [diff] [blame] | 378 | public void dump(PrintWriter writer, String indent) { |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 379 | writer.println(indent + TAG + ":"); |
| 380 | writer.println(indent + "\tUserId: " + mUserId); |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 381 | } |
| 382 | |
| 383 | /** |
Sal Savage | 703c46f | 2019-04-15 08:39:25 -0700 | [diff] [blame] | 384 | * Print to debug if debug is enabled |
Ram Periathiruvadi | acb6024 | 2017-04-13 16:19:09 -0700 | [diff] [blame] | 385 | */ |
Andrew Cheng | b7eaebe | 2020-10-02 08:31:55 -0700 | [diff] [blame] | 386 | private static void logd(String... msgParts) { |
Ram Periathiruvadi | ee28c00 | 2017-02-07 21:35:01 -0800 | [diff] [blame] | 387 | if (DBG) { |
Eric Jeong | bd5fb56 | 2020-12-21 13:49:40 -0800 | [diff] [blame] | 388 | Slog.d(TAG, String.join(" ", msgParts)); |
Ram Periathiruvadi | ee28c00 | 2017-02-07 21:35:01 -0800 | [diff] [blame] | 389 | } |
Ram Periathiruvadi | 7ed8418 | 2017-01-20 15:18:08 -0800 | [diff] [blame] | 390 | } |
| 391 | } |