1 /* 2 * Copyright (C) 2020 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 package com.android.car; 17 18 import static android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME; 19 import static android.car.Car.PERMISSION_CAR_POWER; 20 import static android.car.Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG; 21 import static android.car.Car.PERMISSION_USE_CAR_WATCHDOG; 22 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.ASSOCIATE_CURRENT_USER; 23 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_ALL_USERS; 24 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_CURRENT_USER; 25 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_1; 26 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_2; 27 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_3; 28 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_4; 29 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.KEY_FOB; 30 import static android.media.AudioManager.FLAG_SHOW_UI; 31 32 import static com.android.car.power.PolicyReader.POWER_STATE_ON; 33 import static com.android.car.power.PolicyReader.POWER_STATE_WAIT_FOR_VHAL; 34 35 import android.annotation.NonNull; 36 import android.annotation.Nullable; 37 import android.annotation.UserIdInt; 38 import android.app.ActivityManager; 39 import android.app.ActivityOptions; 40 import android.app.UiModeManager; 41 import android.car.Car; 42 import android.car.CarOccupantZoneManager; 43 import android.car.VehiclePropertyIds; 44 import android.car.content.pm.CarPackageManager; 45 import android.car.input.CarInputManager; 46 import android.car.input.CustomInputEvent; 47 import android.car.input.RotaryEvent; 48 import android.car.user.CarUserManager; 49 import android.car.user.UserCreationResult; 50 import android.car.user.UserIdentificationAssociationResponse; 51 import android.car.user.UserRemovalResult; 52 import android.car.user.UserSwitchResult; 53 import android.car.userlib.HalCallback; 54 import android.car.userlib.UserHalHelper; 55 import android.car.util.concurrent.AsyncFuture; 56 import android.car.watchdog.CarWatchdogManager; 57 import android.car.watchdog.IoOveruseConfiguration; 58 import android.car.watchdog.PerStateBytes; 59 import android.car.watchdog.ResourceOveruseConfiguration; 60 import android.content.ComponentName; 61 import android.content.Context; 62 import android.content.Intent; 63 import android.hardware.automotive.vehicle.V2_0.CreateUserRequest; 64 import android.hardware.automotive.vehicle.V2_0.CreateUserStatus; 65 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponse; 66 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction; 67 import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest; 68 import android.hardware.automotive.vehicle.V2_0.SwitchUserMessageType; 69 import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest; 70 import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus; 71 import android.hardware.automotive.vehicle.V2_0.UserFlags; 72 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociation; 73 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue; 74 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType; 75 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue; 76 import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest; 77 import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse; 78 import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation; 79 import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest; 80 import android.hardware.automotive.vehicle.V2_0.UserInfo; 81 import android.hardware.automotive.vehicle.V2_0.UsersInfo; 82 import android.hardware.automotive.vehicle.V2_0.VehicleArea; 83 import android.hardware.automotive.vehicle.V2_0.VehicleDisplay; 84 import android.hardware.automotive.vehicle.V2_0.VehicleGear; 85 import android.os.Binder; 86 import android.os.Build; 87 import android.os.Process; 88 import android.os.RemoteException; 89 import android.os.ShellCommand; 90 import android.os.SystemClock; 91 import android.os.UserHandle; 92 import android.os.UserManager; 93 import android.text.TextUtils; 94 import android.util.ArrayMap; 95 import android.util.IndentingPrintWriter; 96 import android.util.Slog; 97 import android.util.SparseArray; 98 import android.view.KeyEvent; 99 100 import com.android.car.am.FixedActivityService; 101 import com.android.car.audio.CarAudioService; 102 import com.android.car.evs.CarEvsService; 103 import com.android.car.garagemode.GarageModeService; 104 import com.android.car.hal.InputHalService; 105 import com.android.car.hal.UserHalService; 106 import com.android.car.hal.VehicleHal; 107 import com.android.car.pm.CarPackageManagerService; 108 import com.android.car.power.CarPowerManagementService; 109 import com.android.car.systeminterface.SystemInterface; 110 import com.android.car.user.CarUserService; 111 import com.android.car.watchdog.CarWatchdogService; 112 import com.android.internal.util.Preconditions; 113 114 import java.util.ArrayList; 115 import java.util.Arrays; 116 import java.util.Collections; 117 import java.util.List; 118 import java.util.Objects; 119 import java.util.concurrent.CountDownLatch; 120 import java.util.concurrent.ExecutionException; 121 import java.util.concurrent.TimeUnit; 122 import java.util.concurrent.TimeoutException; 123 import java.util.concurrent.atomic.AtomicBoolean; 124 125 final class CarShellCommand extends ShellCommand { 126 127 private static final String NO_INITIAL_USER = "N/A"; 128 129 private static final String TAG = CarLog.tagFor(CarShellCommand.class); 130 private static final boolean VERBOSE = false; 131 132 private static final String COMMAND_HELP = "-h"; 133 private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode"; 134 private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event"; 135 private static final String COMMAND_INJECT_ERROR_EVENT = "inject-error-event"; 136 private static final String COMMAND_INJECT_CONTINUOUS_EVENT = "inject-continuous-events"; 137 private static final String COMMAND_ENABLE_UXR = "enable-uxr"; 138 private static final String COMMAND_GARAGE_MODE = "garage-mode"; 139 private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities"; 140 private static final String COMMAND_GET_CARPROPERTYCONFIG = "get-carpropertyconfig"; 141 private static final String COMMAND_GET_PROPERTY_VALUE = "get-property-value"; 142 private static final String COMMAND_PROJECTION_AP_TETHERING = "projection-tethering"; 143 private static final String COMMAND_PROJECTION_UI_MODE = "projection-ui-mode"; 144 private static final String COMMAND_RESUME = "resume"; 145 private static final String COMMAND_SUSPEND = "suspend"; 146 private static final String COMMAND_SET_UID_TO_ZONE = "set-audio-zone-for-uid"; 147 private static final String COMMAND_RESET_VOLUME_CONTEXT = "reset-selected-volume-context"; 148 private static final String COMMAND_SET_MUTE_CAR_VOLUME_GROUP = "set-mute-car-volume-group"; 149 private static final String COMMAND_SET_GROUP_VOLUME = "set-group-volume"; 150 private static final String COMMAND_START_FIXED_ACTIVITY_MODE = "start-fixed-activity-mode"; 151 private static final String COMMAND_STOP_FIXED_ACTIVITY_MODE = "stop-fixed-activity-mode"; 152 private static final String COMMAND_ENABLE_FEATURE = "enable-feature"; 153 private static final String COMMAND_DISABLE_FEATURE = "disable-feature"; 154 private static final String COMMAND_INJECT_KEY = "inject-key"; 155 private static final String COMMAND_INJECT_ROTARY = "inject-rotary"; 156 private static final String COMMAND_INJECT_CUSTOM_INPUT = "inject-custom-input"; 157 private static final String COMMAND_GET_INITIAL_USER_INFO = "get-initial-user-info"; 158 private static final String COMMAND_SWITCH_USER = "switch-user"; 159 private static final String COMMAND_REMOVE_USER = "remove-user"; 160 private static final String COMMAND_CREATE_USER = "create-user"; 161 private static final String COMMAND_GET_INITIAL_USER = "get-initial-user"; 162 private static final String COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE = 163 "set-occupant-zone-for-user"; 164 private static final String COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE = 165 "reset-user-in-occupant-zone"; 166 private static final String COMMAND_GET_USER_AUTH_ASSOCIATION = 167 "get-user-auth-association"; 168 private static final String COMMAND_SET_USER_AUTH_ASSOCIATION = 169 "set-user-auth-association"; 170 private static final String COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE = 171 "set-start-bg-users-on-garage-mode"; 172 private static final String COMMAND_DEFINE_POWER_POLICY = "define-power-policy"; 173 private static final String COMMAND_APPLY_POWER_POLICY = "apply-power-policy"; 174 private static final String COMMAND_DEFINE_POWER_POLICY_GROUP = "define-power-policy-group"; 175 private static final String COMMAND_SET_POWER_POLICY_GROUP = "set-power-policy-group"; 176 private static final String COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY = 177 "apply-cts-verifier-power-off-policy"; 178 private static final String COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY = 179 "apply-cts-verifier-power-on-policy"; 180 private static final String COMMAND_POWER_OFF = "power-off"; 181 private static final String POWER_OFF_SKIP_GARAGEMODE = "--skip-garagemode"; 182 private static final String POWER_OFF_SHUTDOWN = "--shutdown"; 183 private static final String COMMAND_SILENT_MODE = "silent-mode"; 184 // Used with COMMAND_SILENT_MODE for forced silent: "forced-silent" 185 private static final String SILENT_MODE_FORCED_SILENT = 186 CarPowerManagementService.SILENT_MODE_FORCED_SILENT; 187 // Used with COMMAND_SILENT_MODE for forced non silent: "forced-non-silent" 188 private static final String SILENT_MODE_FORCED_NON_SILENT = 189 CarPowerManagementService.SILENT_MODE_FORCED_NON_SILENT; 190 // Used with COMMAND_SILENT_MODE for non forced silent mode: "non-forced-silent-mode" 191 private static final String SILENT_MODE_NON_FORCED = 192 CarPowerManagementService.SILENT_MODE_NON_FORCED; 193 194 private static final String COMMAND_EMULATE_DRIVING_STATE = "emulate-driving-state"; 195 private static final String DRIVING_STATE_DRIVE = "drive"; 196 private static final String DRIVING_STATE_PARK = "park"; 197 private static final String DRIVING_STATE_REVERSE = "reverse"; 198 199 private static final String COMMAND_SET_REARVIEW_CAMERA_ID = "set-rearview-camera-id"; 200 private static final String COMMAND_GET_REARVIEW_CAMERA_ID = "get-rearview-camera-id"; 201 202 private static final String COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE = 203 "watchdog-control-package-killable-state"; 204 private static final String COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES = 205 "watchdog-io-set-3p-foreground-bytes"; 206 private static final String COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES = 207 "watchdog-io-get-3p-foreground-bytes"; 208 private static final String COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK = 209 "watchdog-control-health-check"; 210 211 private static final String COMMAND_DRIVING_SAFETY_SET_REGION = 212 "set-drivingsafety-region"; 213 214 private static final String[] CREATE_OR_MANAGE_USERS_PERMISSIONS = new String[] { 215 android.Manifest.permission.CREATE_USERS, 216 android.Manifest.permission.MANAGE_USERS 217 }; 218 219 // List of commands allowed in user build. All these command should be protected with 220 // a permission. K: command, V: required permissions (must have at least 1). 221 // Only commands with permission already granted to shell user should be allowed. 222 // Commands that can affect safety should be never allowed in user build. 223 // 224 // This map is looked up first, then USER_BUILD_COMMAND_TO_PERMISSION_MAP 225 private static final ArrayMap<String, String[]> USER_BUILD_COMMAND_TO_PERMISSIONS_MAP; 226 static { 227 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP = new ArrayMap<>(7); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_INITIAL_USER_INFO, CREATE_OR_MANAGE_USERS_PERMISSIONS)228 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_INITIAL_USER_INFO, 229 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SWITCH_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)230 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SWITCH_USER, 231 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_REMOVE_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)232 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_REMOVE_USER, 233 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_CREATE_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)234 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_CREATE_USER, 235 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_AUTH_ASSOCIATION, CREATE_OR_MANAGE_USERS_PERMISSIONS)236 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_AUTH_ASSOCIATION, 237 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_USER_AUTH_ASSOCIATION, CREATE_OR_MANAGE_USERS_PERMISSIONS)238 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_USER_AUTH_ASSOCIATION, 239 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE, CREATE_OR_MANAGE_USERS_PERMISSIONS)240 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE, 241 CREATE_OR_MANAGE_USERS_PERMISSIONS); 242 } 243 244 // List of commands allowed in user build. All these command should be protected with 245 // a permission. K: command, V: required permission. 246 // Only commands with permission already granted to shell user should be allowed. 247 // Commands that can affect safety should be never allowed in user build. 248 private static final ArrayMap<String, String> USER_BUILD_COMMAND_TO_PERMISSION_MAP; 249 static { 250 USER_BUILD_COMMAND_TO_PERMISSION_MAP = new ArrayMap<>(8); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GARAGE_MODE, android.Manifest.permission.DEVICE_POWER)251 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GARAGE_MODE, 252 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESUME, android.Manifest.permission.DEVICE_POWER)253 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESUME, 254 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SUSPEND, android.Manifest.permission.DEVICE_POWER)255 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SUSPEND, 256 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY, android.Manifest.permission.DEVICE_POWER)257 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY, 258 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_POWER_POLICY, android.Manifest.permission.DEVICE_POWER)259 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_POWER_POLICY, 260 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY_GROUP, android.Manifest.permission.DEVICE_POWER)261 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY_GROUP, 262 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_POWER_POLICY_GROUP, android.Manifest.permission.DEVICE_POWER)263 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_POWER_POLICY_GROUP, 264 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, android.Manifest.permission.DEVICE_POWER)265 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, 266 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, android.Manifest.permission.DEVICE_POWER)267 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, 268 android.Manifest.permission.DEVICE_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SILENT_MODE, PERMISSION_CAR_POWER)269 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SILENT_MODE, 270 PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_INITIAL_USER, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)271 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_INITIAL_USER, 272 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DAY_NIGHT_MODE, android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)273 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DAY_NIGHT_MODE, 274 android.Manifest.permission.MODIFY_DAY_NIGHT_MODE); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESET_VOLUME_CONTEXT, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)275 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESET_VOLUME_CONTEXT, 276 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_MUTE_CAR_VOLUME_GROUP, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)277 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_MUTE_CAR_VOLUME_GROUP, 278 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_GROUP_VOLUME, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)279 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_GROUP_VOLUME, 280 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_KEY, android.Manifest.permission.INJECT_EVENTS)281 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_KEY, 282 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_ROTARY, android.Manifest.permission.INJECT_EVENTS)283 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_ROTARY, 284 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)285 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE, 286 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)287 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES, 288 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)289 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES, 290 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK, PERMISSION_USE_CAR_WATCHDOG)291 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK, 292 PERMISSION_USE_CAR_WATCHDOG); 293 } 294 295 private static final String PARAM_DAY_MODE = "day"; 296 private static final String PARAM_NIGHT_MODE = "night"; 297 private static final String PARAM_SENSOR_MODE = "sensor"; 298 private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0"; 299 private static final String PARAM_INJECT_EVENT_DEFAULT_RATE = "10"; 300 private static final String PARAM_INJECT_EVENT_DEFAULT_DURATION = "60"; 301 private static final String PARAM_ALL_PROPERTIES_OR_AREA = "-1"; 302 private static final String PARAM_ON_MODE = "on"; 303 private static final String PARAM_OFF_MODE = "off"; 304 private static final String PARAM_QUERY_MODE = "query"; 305 private static final String PARAM_REBOOT = "reboot"; 306 private static final String PARAM_MUTE = "mute"; 307 private static final String PARAM_UNMUTE = "unmute"; 308 309 310 private static final int RESULT_OK = 0; 311 private static final int RESULT_ERROR = -1; // Arbitrary value, any non-0 is fine 312 313 private static final int DEFAULT_HAL_TIMEOUT_MS = 1_000; 314 315 private static final int DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS = 60_000; 316 317 private static final int INVALID_USER_AUTH_TYPE_OR_VALUE = -1; 318 319 private static final SparseArray<String> VALID_USER_AUTH_TYPES; 320 private static final String VALID_USER_AUTH_TYPES_HELP; 321 322 private static final SparseArray<String> VALID_USER_AUTH_SET_VALUES; 323 private static final String VALID_USER_AUTH_SET_VALUES_HELP; 324 325 private static final ArrayMap<String, Integer> CUSTOM_INPUT_FUNCTION_ARGS; 326 327 static { 328 VALID_USER_AUTH_TYPES = new SparseArray<>(5); VALID_USER_AUTH_TYPES.put(KEY_FOB, UserIdentificationAssociationType.toString(KEY_FOB))329 VALID_USER_AUTH_TYPES.put(KEY_FOB, UserIdentificationAssociationType.toString(KEY_FOB)); VALID_USER_AUTH_TYPES.put(CUSTOM_1, UserIdentificationAssociationType.toString(CUSTOM_1))330 VALID_USER_AUTH_TYPES.put(CUSTOM_1, UserIdentificationAssociationType.toString(CUSTOM_1)); VALID_USER_AUTH_TYPES.put(CUSTOM_2, UserIdentificationAssociationType.toString(CUSTOM_2))331 VALID_USER_AUTH_TYPES.put(CUSTOM_2, UserIdentificationAssociationType.toString(CUSTOM_2)); VALID_USER_AUTH_TYPES.put(CUSTOM_3, UserIdentificationAssociationType.toString(CUSTOM_3))332 VALID_USER_AUTH_TYPES.put(CUSTOM_3, UserIdentificationAssociationType.toString(CUSTOM_3)); VALID_USER_AUTH_TYPES.put(CUSTOM_4, UserIdentificationAssociationType.toString(CUSTOM_4))333 VALID_USER_AUTH_TYPES.put(CUSTOM_4, UserIdentificationAssociationType.toString(CUSTOM_4)); 334 VALID_USER_AUTH_TYPES_HELP = getHelpString("types", VALID_USER_AUTH_TYPES); 335 336 VALID_USER_AUTH_SET_VALUES = new SparseArray<>(3); VALID_USER_AUTH_SET_VALUES.put(ASSOCIATE_CURRENT_USER, UserIdentificationAssociationSetValue.toString(ASSOCIATE_CURRENT_USER))337 VALID_USER_AUTH_SET_VALUES.put(ASSOCIATE_CURRENT_USER, 338 UserIdentificationAssociationSetValue.toString(ASSOCIATE_CURRENT_USER)); VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_CURRENT_USER, UserIdentificationAssociationSetValue.toString(DISASSOCIATE_CURRENT_USER))339 VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_CURRENT_USER, 340 UserIdentificationAssociationSetValue.toString(DISASSOCIATE_CURRENT_USER)); VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_ALL_USERS, UserIdentificationAssociationSetValue.toString(DISASSOCIATE_ALL_USERS))341 VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_ALL_USERS, 342 UserIdentificationAssociationSetValue.toString(DISASSOCIATE_ALL_USERS)); 343 VALID_USER_AUTH_SET_VALUES_HELP = getHelpString("values", VALID_USER_AUTH_SET_VALUES); 344 345 CUSTOM_INPUT_FUNCTION_ARGS = new ArrayMap<>(10); 346 CUSTOM_INPUT_FUNCTION_ARGS.put("f1", CustomInputEvent.INPUT_CODE_F1); 347 CUSTOM_INPUT_FUNCTION_ARGS.put("f2", CustomInputEvent.INPUT_CODE_F2); 348 CUSTOM_INPUT_FUNCTION_ARGS.put("f3", CustomInputEvent.INPUT_CODE_F3); 349 CUSTOM_INPUT_FUNCTION_ARGS.put("f4", CustomInputEvent.INPUT_CODE_F4); 350 CUSTOM_INPUT_FUNCTION_ARGS.put("f5", CustomInputEvent.INPUT_CODE_F5); 351 CUSTOM_INPUT_FUNCTION_ARGS.put("f6", CustomInputEvent.INPUT_CODE_F6); 352 CUSTOM_INPUT_FUNCTION_ARGS.put("f7", CustomInputEvent.INPUT_CODE_F7); 353 CUSTOM_INPUT_FUNCTION_ARGS.put("f8", CustomInputEvent.INPUT_CODE_F8); 354 CUSTOM_INPUT_FUNCTION_ARGS.put("f9", CustomInputEvent.INPUT_CODE_F9); 355 CUSTOM_INPUT_FUNCTION_ARGS.put("f10", CustomInputEvent.INPUT_CODE_F10); 356 } 357 358 @NonNull getHelpString(@onNull String name, @NonNull SparseArray<String> values)359 private static String getHelpString(@NonNull String name, @NonNull SparseArray<String> values) { 360 StringBuilder help = new StringBuilder("Valid ").append(name).append(" are: "); 361 int size = values.size(); 362 for (int i = 0; i < size; i++) { 363 help.append(values.valueAt(i)); 364 if (i != size - 1) { 365 help.append(", "); 366 } 367 } 368 return help.append('.').toString(); 369 } 370 371 private final Context mContext; 372 private final VehicleHal mHal; 373 private final CarAudioService mCarAudioService; 374 private final CarPackageManagerService mCarPackageManagerService; 375 private final CarProjectionService mCarProjectionService; 376 private final CarPowerManagementService mCarPowerManagementService; 377 private final FixedActivityService mFixedActivityService; 378 private final CarFeatureController mFeatureController; 379 private final CarInputService mCarInputService; 380 private final CarNightService mCarNightService; 381 private final SystemInterface mSystemInterface; 382 private final GarageModeService mGarageModeService; 383 private final CarUserService mCarUserService; 384 private final CarOccupantZoneService mCarOccupantZoneService; 385 private final CarEvsService mCarEvsService; 386 private final CarWatchdogService mCarWatchdogService; 387 private long mKeyDownTime; 388 CarShellCommand(Context context, VehicleHal hal, CarAudioService carAudioService, CarPackageManagerService carPackageManagerService, CarProjectionService carProjectionService, CarPowerManagementService carPowerManagementService, FixedActivityService fixedActivityService, CarFeatureController featureController, CarInputService carInputService, CarNightService carNightService, SystemInterface systemInterface, GarageModeService garageModeService, CarUserService carUserService, CarOccupantZoneService carOccupantZoneService, CarEvsService carEvsService, CarWatchdogService carWatchdogService)389 CarShellCommand(Context context, 390 VehicleHal hal, 391 CarAudioService carAudioService, 392 CarPackageManagerService carPackageManagerService, 393 CarProjectionService carProjectionService, 394 CarPowerManagementService carPowerManagementService, 395 FixedActivityService fixedActivityService, 396 CarFeatureController featureController, 397 CarInputService carInputService, 398 CarNightService carNightService, 399 SystemInterface systemInterface, 400 GarageModeService garageModeService, 401 CarUserService carUserService, 402 CarOccupantZoneService carOccupantZoneService, 403 CarEvsService carEvsService, 404 CarWatchdogService carWatchdogService) { 405 mContext = context; 406 mHal = hal; 407 mCarAudioService = carAudioService; 408 mCarPackageManagerService = carPackageManagerService; 409 mCarProjectionService = carProjectionService; 410 mCarPowerManagementService = carPowerManagementService; 411 mFixedActivityService = fixedActivityService; 412 mFeatureController = featureController; 413 mCarInputService = carInputService; 414 mCarNightService = carNightService; 415 mSystemInterface = systemInterface; 416 mGarageModeService = garageModeService; 417 mCarUserService = carUserService; 418 mCarOccupantZoneService = carOccupantZoneService; 419 mCarEvsService = carEvsService; 420 mCarWatchdogService = carWatchdogService; 421 } 422 423 @Override onCommand(String cmd)424 public int onCommand(String cmd) { 425 if (cmd == null) { 426 onHelp(); 427 return RESULT_ERROR; 428 } 429 ArrayList<String> argsList = new ArrayList<>(); 430 argsList.add(cmd); 431 String arg = null; 432 do { 433 arg = getNextArg(); 434 if (arg != null) { 435 argsList.add(arg); 436 } 437 } while (arg != null); 438 String[] args = new String[argsList.size()]; 439 argsList.toArray(args); 440 try (IndentingPrintWriter pw = new IndentingPrintWriter(getOutPrintWriter())) { 441 return exec(args, pw); 442 } 443 } 444 445 @Override onHelp()446 public void onHelp() { 447 try (IndentingPrintWriter pw = new IndentingPrintWriter(getOutPrintWriter())) { 448 showHelp(pw); 449 } 450 } 451 showHelp(IndentingPrintWriter pw)452 private static void showHelp(IndentingPrintWriter pw) { 453 pw.println("Car service commands:"); 454 pw.println("\t-h"); 455 pw.println("\t Print this help text."); 456 pw.println("\tday-night-mode [day|night|sensor]"); 457 pw.println("\t Force into day/night mode or restore to auto."); 458 pw.println("\tinject-vhal-event <PROPERTY_ID in Hex or Decimal> [zone] " 459 + "data(can be comma separated list) " 460 + "[-t delay_time_seconds]"); 461 pw.println("\t Inject a vehicle property for testing."); 462 pw.println("\t delay_time_seconds: the event timestamp is increased by certain second."); 463 pw.println("\t If not specified, it will be 0."); 464 pw.println("\tinject-error-event <PROPERTY_ID in Hex or Decimal> zone <errorCode>"); 465 pw.println("\t Inject an error event from VHAL for testing."); 466 pw.println("\tinject-continuous-events <PROPERTY_ID in Hex or Decimal> " 467 + "data(can be comma separated list) " 468 + "[-z zone] [-s SampleRate in Hz] [-d time duration in seconds]"); 469 pw.println("\t Inject continuous vehicle events for testing."); 470 pw.printf("\t If not specified, CarService will inject fake events with areaId:%s " 471 + "at sample rate %s for %s seconds.", PARAM_VEHICLE_PROPERTY_AREA_GLOBAL, 472 PARAM_INJECT_EVENT_DEFAULT_RATE, PARAM_INJECT_EVENT_DEFAULT_DURATION); 473 pw.println("\tenable-uxr true|false"); 474 pw.println("\t Enable/Disable UX restrictions and App blocking."); 475 pw.println("\tgarage-mode [on|off|query|reboot]"); 476 pw.println("\t Force into or out of garage mode, or check status."); 477 pw.println("\t With 'reboot', enter garage mode, then reboot when it completes."); 478 pw.println("\tget-do-activities pkgname"); 479 pw.println("\t Get Distraction Optimized activities in given package."); 480 pw.println("\tget-carpropertyconfig [PROPERTY_ID in Hex or Decimal]"); 481 pw.println("\t Get a CarPropertyConfig by Id or list all CarPropertyConfigs"); 482 pw.println("\tget-property-value [PROPERTY_ID in Hex or Decimal] [areaId]"); 483 pw.println("\t Get a vehicle property value by property id and areaId"); 484 pw.println("\t or list all property values for all areaId"); 485 pw.println("\tsuspend"); 486 pw.println("\t Suspend the system to Deep Sleep."); 487 pw.println("\tresume"); 488 pw.println("\t Wake the system up after a 'suspend.'"); 489 pw.println("\tprojection-tethering [true|false]"); 490 pw.println("\t Whether tethering should be used when creating access point for" 491 + " wireless projection"); 492 pw.println("\t--metrics"); 493 pw.println("\t When used with dumpsys, only metrics will be in the dumpsys output."); 494 pw.printf("\t%s [zoneid] [uid]\n", COMMAND_SET_UID_TO_ZONE); 495 pw.println("\t Maps the audio zoneid to uid."); 496 pw.printf("\t%s\n", COMMAND_RESET_VOLUME_CONTEXT); 497 pw.println("\t Resets the last selected volume context for volume changes."); 498 pw.printf("\t%s [zoneId] [groupId] [%s\\%s]\n", COMMAND_SET_MUTE_CAR_VOLUME_GROUP, 499 PARAM_MUTE, PARAM_UNMUTE); 500 pw.printf("\t %s\\%s groupId in zoneId\n", PARAM_MUTE, PARAM_UNMUTE); 501 pw.printf("\t%s [zoneId] [groupId] [volume]\n", COMMAND_SET_GROUP_VOLUME); 502 pw.println("\t sets the group volume for [groupId] in [zoneId] to %volume,"); 503 pw.println("\t [volume] must be an integer between 0 to 100"); 504 pw.println("\tstart-fixed-activity displayId packageName activityName"); 505 pw.println("\t Start an Activity the specified display as fixed mode"); 506 pw.println("\tstop-fixed-mode displayId"); 507 pw.println("\t Stop fixed Activity mode for the given display. " 508 + "The Activity will not be restarted upon crash."); 509 pw.println("\tenable-feature featureName"); 510 pw.println("\t Enable the requested feature. Change will happen after reboot."); 511 pw.println("\t This requires root/su."); 512 pw.println("\tdisable-feature featureName"); 513 pw.println("\t Disable the requested feature. Change will happen after reboot"); 514 pw.println("\t This requires root/su."); 515 pw.println("\tinject-key [-d display] [-t down_delay_ms | -a down|up] key_code"); 516 pw.println("\t inject key down and/or up event to car service"); 517 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 518 pw.println("\t down_delay_ms: delay from down to up key event. If not specified,"); 519 pw.println("\t it will be 0"); 520 pw.println("\t key_code: int key code defined in android KeyEvent"); 521 pw.println("\t If -a isn't specified, both down and up will be injected."); 522 pw.println("\tinject-rotary [-d display] [-i input_type] [-c clockwise]"); 523 pw.println("\t [-dt delta_times_ms]"); 524 pw.println("\t inject rotary input event to car service."); 525 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 526 pw.println("\t input_type: 10 for navigation controller input, 11 for volume"); 527 pw.println("\t controller input. If not specified, it will be 10."); 528 pw.println("\t clockwise: true if the event is clockwise, false if the event is"); 529 pw.println("\t counter-clockwise. If not specified, it will be false."); 530 pw.println("\t delta_times_ms: a list of delta time (current time minus event time)"); 531 pw.println("\t in descending order. If not specified, it will be 0."); 532 pw.println("\tinject-custom-input [-d display] [-r repeatCounter] EVENT"); 533 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 534 pw.println("\t repeatCounter: number of times the button was hit (default value is 1)"); 535 pw.println("\t EVENT: mandatory last argument. Possible values for for this flag are "); 536 pw.println("\t F1, F2, up to F10 (functions to defined by OEM partners)"); 537 pw.printf("\t%s <REQ_TYPE> [--timeout TIMEOUT_MS]\n", COMMAND_GET_INITIAL_USER_INFO); 538 pw.println("\t Calls the Vehicle HAL to get the initial boot info, passing the given"); 539 pw.println("\t REQ_TYPE (which could be either FIRST_BOOT, FIRST_BOOT_AFTER_OTA, "); 540 pw.println("\t COLD_BOOT, RESUME, or any numeric value that would be passed 'as-is')"); 541 pw.println("\t and an optional TIMEOUT_MS to wait for the HAL response (if not set,"); 542 pw.println("\t it will use a default value)."); 543 pw.println("\t The --hal-only option only calls HAL, without using CarUserService."); 544 545 pw.printf("\t%s <USER_ID> [--hal-only] [--timeout TIMEOUT_MS]\n", COMMAND_SWITCH_USER); 546 pw.println("\t Switches to user USER_ID using the HAL integration."); 547 pw.println("\t The --hal-only option only calls HAL, without switching the user,"); 548 pw.println("\t while the --timeout defines how long to wait for the response."); 549 550 pw.printf("\t%s <USER_ID> [--hal-only]\n", COMMAND_REMOVE_USER); 551 pw.println("\t Removes user with USER_ID using the HAL integration."); 552 pw.println("\t The --hal-only option only calls HAL, without removing the user,"); 553 554 pw.printf("\t%s [--hal-only] [--timeout TIMEOUT_MS] [--type TYPE] [--flags FLAGS] [NAME]\n", 555 COMMAND_CREATE_USER); 556 pw.println("\t Creates a new user using the HAL integration."); 557 pw.println("\t The --hal-only uses UserManager to create the user,"); 558 pw.println("\t while the --timeout defines how long to wait for the response."); 559 560 pw.printf("\t%s\n", COMMAND_GET_INITIAL_USER); 561 pw.printf("\t Gets the id of the initial user (or %s when it's not available)\n", 562 NO_INITIAL_USER); 563 564 pw.printf("\t%s [occupantZoneId] [userId]\n", COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE); 565 pw.println("\t Maps the occupant zone id to user id."); 566 pw.printf("\t%s [occupantZoneId]\n", COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE); 567 pw.println("\t Unmaps the user assigned to occupant zone id."); 568 569 pw.printf("\t%s [--hal-only] [--user USER_ID] TYPE1 [..TYPE_N]\n", 570 COMMAND_GET_USER_AUTH_ASSOCIATION); 571 pw.println("\t Gets the N user authentication values for the N types for the given user"); 572 pw.println("\t (or current user when not specified)."); 573 pw.println("\t By defautt it calls CarUserManager, but using --hal-only will call just " 574 + "UserHalService."); 575 576 pw.printf("\t%s [--hal-only] [--user USER_ID] TYPE1 VALUE1 [..TYPE_N VALUE_N]\n", 577 COMMAND_SET_USER_AUTH_ASSOCIATION); 578 pw.println("\t Sets the N user authentication types with the N values for the given user"); 579 pw.println("\t (or current user when not specified)."); 580 pw.println("\t By default it calls CarUserManager, but using --hal-only will call just " 581 + "UserHalService."); 582 pw.printf("\t %s\n", VALID_USER_AUTH_TYPES_HELP); 583 pw.printf("\t %s\n", VALID_USER_AUTH_SET_VALUES_HELP); 584 585 pw.printf("\t%s [true|false]\n", COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE); 586 pw.println("\t Controls backgroud user start and stop during garage mode."); 587 pw.println("\t If false, garage mode operations (background users start at garage mode" 588 + " entry and background users stop at garage mode exit) will be skipped."); 589 590 pw.printf("\t %s [%s|%s|%s|%s]\n", COMMAND_SILENT_MODE, SILENT_MODE_FORCED_SILENT, 591 SILENT_MODE_FORCED_NON_SILENT, SILENT_MODE_NON_FORCED, PARAM_QUERY_MODE); 592 pw.println("\t Forces silent mode silent or non-silent. With query (or no command) " 593 + "displays the silent state"); 594 pw.println("\t and shows how many listeners are monitoring the state."); 595 596 pw.printf("\t%s [%s|%s|%s]\n", COMMAND_EMULATE_DRIVING_STATE, DRIVING_STATE_DRIVE, 597 DRIVING_STATE_PARK, DRIVING_STATE_REVERSE); 598 pw.println("\t Emulates the giving driving state."); 599 600 pw.printf("\t%s <POLICY_ID> [--enable COMP1,COMP2,...] [--disable COMP1,COMP2,...]\n", 601 COMMAND_DEFINE_POWER_POLICY); 602 pw.println("\t Defines a power policy. Components not specified in --enable or --disable"); 603 pw.println("\t are unchanged when the policy is applied."); 604 pw.println("\t Components should be comma-separated without space."); 605 606 pw.printf("\t%s <POLICY_ID>\n", COMMAND_APPLY_POWER_POLICY); 607 pw.println("\t Applies power policy which is defined in /vendor/etc/power_policy.xml or"); 608 pw.printf("\t by %s command\n", COMMAND_DEFINE_POWER_POLICY); 609 610 pw.printf("\t%s <POLICY_GROUP_ID> [%s:<POLICY_ID>] [%s:<POLICY_ID>]\n", 611 COMMAND_DEFINE_POWER_POLICY_GROUP, POWER_STATE_WAIT_FOR_VHAL, POWER_STATE_ON); 612 pw.println("\t Defines a power policy group. The policy ID must be defined in advance."); 613 614 pw.printf("\t%s <POLICY_GROUP_ID>\n", COMMAND_SET_POWER_POLICY_GROUP); 615 pw.println("\t Sets power policy group which is defined in /vendor/etc/power_policy.xml "); 616 pw.printf("\t or by %s command\n", COMMAND_DEFINE_POWER_POLICY_GROUP); 617 618 pw.printf("\t%s\n", COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY); 619 pw.println("\t Define and apply the cts_verifier_off power policy with " 620 + "--disable WIFI,LOCATION,BLUETOOTH"); 621 622 pw.printf("\t%s\n", COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY); 623 pw.println("\t Define and apply the cts_verifier_on power policy with " 624 + "--enable WIFI,LOCATION,BLUETOOTH"); 625 626 pw.printf("\t%s [%s] [%s]\n", COMMAND_POWER_OFF, POWER_OFF_SKIP_GARAGEMODE, 627 POWER_OFF_SHUTDOWN); 628 pw.println("\t Powers off the car."); 629 630 pw.printf("\t%s <CAMERA_ID>\n", COMMAND_SET_REARVIEW_CAMERA_ID); 631 pw.println("\t Configures a target camera device CarEvsService to use."); 632 pw.println("\t If CAMEAR_ID is \"default\", this command will configure CarEvsService "); 633 pw.println("\t to use its default camera device."); 634 635 pw.printf("\t%s\n", COMMAND_GET_REARVIEW_CAMERA_ID); 636 pw.println("\t Gets the name of the camera device CarEvsService is using for " + 637 "the rearview."); 638 639 pw.printf("\t%s true|false <PACKAGE_NAME>\n", 640 COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE); 641 pw.println("\t Marks PACKAGE_NAME as killable or not killable on resource overuse "); 642 643 pw.printf("\t%s <FOREGROUND_MODE_BYTES>\n", COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES); 644 pw.println("\t Sets third-party apps foreground I/O overuse threshold"); 645 646 pw.printf("\t%s\n", COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES); 647 pw.println("\t Gets third-party apps foreground I/O overuse threshold"); 648 649 pw.printf("\t%s enable|disable\n", COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK); 650 pw.println("\t Enables/disables car watchdog process health check."); 651 652 pw.printf("\t%s [REGION_STRING]", COMMAND_DRIVING_SAFETY_SET_REGION); 653 pw.println("\t Set driving safety region."); 654 pw.println("\t Skipping REGION_STRING leads into resetting to all regions"); 655 } 656 showInvalidArguments(IndentingPrintWriter pw)657 private static int showInvalidArguments(IndentingPrintWriter pw) { 658 pw.println("Incorrect number of arguments."); 659 showHelp(pw); 660 return RESULT_ERROR; 661 } 662 runSetZoneIdForUid(String zoneString, String uidString)663 private void runSetZoneIdForUid(String zoneString, String uidString) { 664 int uid = Integer.parseInt(uidString); 665 int zoneId = Integer.parseInt(zoneString); 666 mCarAudioService.setZoneIdForUid(zoneId, uid); 667 } 668 runSetMuteCarVolumeGroup(String zoneString, String groupIdString, String muteString)669 private void runSetMuteCarVolumeGroup(String zoneString, String groupIdString, 670 String muteString) { 671 int groupId = Integer.parseInt(groupIdString); 672 int zoneId = Integer.parseInt(zoneString); 673 if (!PARAM_MUTE.equalsIgnoreCase(muteString) 674 && !PARAM_UNMUTE.equalsIgnoreCase(muteString)) { 675 throw new IllegalArgumentException("Failed to set volume group mute for " 676 + groupIdString + " in zone " + zoneString 677 + ", bad mute argument: " + muteString); 678 } 679 boolean muteState = PARAM_MUTE.equalsIgnoreCase(muteString); 680 mCarAudioService.setVolumeGroupMute(zoneId, groupId, muteState, FLAG_SHOW_UI); 681 } 682 683 runSetGroupVolume(String zoneIdString, String groupIdString, String volumeString)684 private void runSetGroupVolume(String zoneIdString, String groupIdString, String volumeString) { 685 int groupId = Integer.parseInt(groupIdString); 686 int zoneId = Integer.parseInt(zoneIdString); 687 int percentVolume = Integer.parseInt(volumeString); 688 Preconditions.checkArgumentInRange(percentVolume, 0, 100, 689 "%volume for group " + groupIdString + " in zone " + zoneIdString); 690 int minIndex = mCarAudioService.getGroupMinVolume(zoneId, groupId); 691 int maxIndex = mCarAudioService.getGroupMaxVolume(zoneId, groupId); 692 int index = minIndex 693 + (int) ((float) (maxIndex - minIndex) * ((float) percentVolume / 100.0f)); 694 mCarAudioService.setGroupVolume(zoneId, groupId, index, FLAG_SHOW_UI); 695 } 696 runResetSelectedVolumeContext()697 private void runResetSelectedVolumeContext() { 698 mCarAudioService.resetSelectedVolumeContext(); 699 } 700 runSetOccupantZoneIdForUserId(String occupantZoneIdString, String userIdString)701 private void runSetOccupantZoneIdForUserId(String occupantZoneIdString, 702 String userIdString) { 703 int userId = Integer.parseInt(userIdString); 704 int occupantZoneId = Integer.parseInt(occupantZoneIdString); 705 if (!mCarOccupantZoneService.assignProfileUserToOccupantZone(occupantZoneId, userId)) { 706 throw new IllegalStateException("Failed to set userId " + userId + " to occupantZoneId " 707 + occupantZoneIdString); 708 } 709 } 710 runResetOccupantZoneId(String occupantZoneIdString)711 private void runResetOccupantZoneId(String occupantZoneIdString) { 712 int occupantZoneId = Integer.parseInt(occupantZoneIdString); 713 if (!mCarOccupantZoneService 714 .assignProfileUserToOccupantZone(occupantZoneId, UserHandle.USER_NULL)) { 715 throw new IllegalStateException("Failed to reset occupantZoneId " 716 + occupantZoneIdString); 717 } 718 } 719 assertHasAtLeastOnePermission(String cmd, String[] requiredPermissions)720 private void assertHasAtLeastOnePermission(String cmd, String[] requiredPermissions) { 721 for (String requiredPermission : requiredPermissions) { 722 if (ICarImpl.hasPermission(mContext, requiredPermission)) return; 723 } 724 if (requiredPermissions.length == 1) { 725 throw new SecurityException("The command '" + cmd + "' requires permission:" 726 + requiredPermissions[0]); 727 } 728 throw new SecurityException( 729 "The command " + cmd + " requires one of the following permissions:" 730 + Arrays.toString(requiredPermissions)); 731 } 732 exec(String[] args, IndentingPrintWriter writer)733 int exec(String[] args, IndentingPrintWriter writer) { 734 String cmd = args[0]; 735 String[] requiredPermissions = USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.get(cmd); 736 if (requiredPermissions == null) { 737 String requiredPermission = USER_BUILD_COMMAND_TO_PERMISSION_MAP.get(cmd); 738 if (requiredPermission != null) { 739 requiredPermissions = new String[] { requiredPermission }; 740 } 741 742 } 743 if (VERBOSE) { 744 Slog.v(TAG, "cmd: " + cmd + ", requiredPermissions: " 745 + Arrays.toString(requiredPermissions)); 746 } 747 if (Build.IS_USER && requiredPermissions == null) { 748 throw new SecurityException("The command '" + cmd + "' requires non-user build"); 749 } 750 if (requiredPermissions != null) { 751 assertHasAtLeastOnePermission(cmd, requiredPermissions); 752 } 753 754 switch (cmd) { 755 case COMMAND_HELP: 756 showHelp(writer); 757 break; 758 case COMMAND_DAY_NIGHT_MODE: { 759 String value = args.length < 2 ? "" : args[1]; 760 forceDayNightMode(value, writer); 761 break; 762 } 763 case COMMAND_GARAGE_MODE: { 764 String value = args.length < 2 ? "" : args[1]; 765 forceGarageMode(value, writer); 766 break; 767 } 768 case COMMAND_INJECT_VHAL_EVENT: 769 String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL; 770 String data; 771 int argNum = args.length; 772 if (argNum < 3 || argNum > 6) { 773 return showInvalidArguments(writer); 774 } 775 String delayTime = args[argNum - 2].equals("-t") ? args[argNum - 1] : "0"; 776 if (argNum == 4 || argNum == 6) { 777 // Zoned 778 zone = args[2]; 779 data = args[3]; 780 } else { 781 // Global 782 data = args[2]; 783 } 784 injectVhalEvent(args[1], zone, data, false, delayTime, writer); 785 break; 786 case COMMAND_INJECT_CONTINUOUS_EVENT: 787 injectContinuousEvents(args, writer); 788 break; 789 case COMMAND_INJECT_ERROR_EVENT: 790 if (args.length != 4) { 791 return showInvalidArguments(writer); 792 } 793 String errorAreaId = args[2]; 794 String errorCode = args[3]; 795 injectVhalEvent(args[1], errorAreaId, errorCode, true, "0", writer); 796 break; 797 case COMMAND_ENABLE_UXR: 798 if (args.length != 2) { 799 return showInvalidArguments(writer); 800 } 801 boolean enableBlocking = Boolean.valueOf(args[1]); 802 if (mCarPackageManagerService != null) { 803 mCarPackageManagerService.setEnableActivityBlocking(enableBlocking); 804 } 805 break; 806 case COMMAND_GET_DO_ACTIVITIES: 807 if (args.length != 2) { 808 return showInvalidArguments(writer); 809 } 810 String pkgName = args[1].toLowerCase(); 811 if (mCarPackageManagerService != null) { 812 String[] doActivities = 813 mCarPackageManagerService.getDistractionOptimizedActivities( 814 pkgName); 815 if (doActivities != null) { 816 writer.println("DO Activities for " + pkgName); 817 for (String a : doActivities) { 818 writer.println(a); 819 } 820 } else { 821 writer.println("No DO Activities for " + pkgName); 822 } 823 } 824 break; 825 case COMMAND_GET_CARPROPERTYCONFIG: 826 String propertyId = args.length < 2 ? PARAM_ALL_PROPERTIES_OR_AREA : args[1]; 827 mHal.dumpPropertyConfigs(writer, Integer.decode(propertyId)); 828 break; 829 case COMMAND_GET_PROPERTY_VALUE: 830 String propId = args.length < 2 ? PARAM_ALL_PROPERTIES_OR_AREA : args[1]; 831 String areaId = args.length < 3 ? PARAM_ALL_PROPERTIES_OR_AREA : args[2]; 832 mHal.dumpPropertyValueByCommend(writer, Integer.decode(propId), 833 Integer.decode(areaId)); 834 break; 835 case COMMAND_PROJECTION_UI_MODE: 836 if (args.length != 2) { 837 return showInvalidArguments(writer); 838 } 839 mCarProjectionService.setUiMode(Integer.valueOf(args[1])); 840 break; 841 case COMMAND_PROJECTION_AP_TETHERING: 842 if (args.length != 2) { 843 return showInvalidArguments(writer); 844 } 845 mCarProjectionService.setAccessPointTethering(Boolean.valueOf(args[1])); 846 break; 847 case COMMAND_RESUME: 848 mCarPowerManagementService.forceSimulatedResume(); 849 writer.println("Resume: Simulating resuming from Deep Sleep"); 850 break; 851 case COMMAND_SUSPEND: 852 mCarPowerManagementService.forceSuspendAndMaybeReboot(false); 853 writer.println("Suspend: Simulating powering down to Deep Sleep"); 854 break; 855 case COMMAND_SET_UID_TO_ZONE: 856 if (args.length != 3) { 857 return showInvalidArguments(writer); 858 } 859 runSetZoneIdForUid(args[1], args[2]); 860 break; 861 case COMMAND_RESET_VOLUME_CONTEXT: 862 if (args.length > 1) { 863 return showInvalidArguments(writer); 864 } 865 runResetSelectedVolumeContext(); 866 break; 867 case COMMAND_SET_MUTE_CAR_VOLUME_GROUP: 868 if (args.length != 4) { 869 return showInvalidArguments(writer); 870 } 871 runSetMuteCarVolumeGroup(args[1], args[2], args[3]); 872 break; 873 case COMMAND_SET_GROUP_VOLUME: 874 if (args.length != 4) { 875 return showInvalidArguments(writer); 876 } 877 runSetGroupVolume(args[1], args[2], args[3]); 878 break; 879 case COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE: 880 if (args.length != 3) { 881 return showInvalidArguments(writer); 882 } 883 runSetOccupantZoneIdForUserId(args[1], args[2]); 884 break; 885 case COMMAND_SILENT_MODE: { 886 String value = args.length < 2 ? "" 887 : args.length == 2 ? args[1] : "too many arguments"; 888 runSilentCommand(value, writer); 889 break; 890 } 891 case COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE: 892 if (args.length != 2) { 893 return showInvalidArguments(writer); 894 } 895 runResetOccupantZoneId(args[1]); 896 break; 897 case COMMAND_START_FIXED_ACTIVITY_MODE: 898 startFixedActivity(args, writer); 899 break; 900 case COMMAND_STOP_FIXED_ACTIVITY_MODE: 901 stopFixedMode(args, writer); 902 break; 903 case COMMAND_ENABLE_FEATURE: 904 if (args.length != 2) { 905 return showInvalidArguments(writer); 906 } 907 enableDisableFeature(args, writer, /* enable= */ true); 908 break; 909 case COMMAND_DISABLE_FEATURE: 910 if (args.length != 2) { 911 return showInvalidArguments(writer); 912 } 913 enableDisableFeature(args, writer, /* enable= */ false); 914 break; 915 case COMMAND_INJECT_KEY: 916 if (args.length < 2) { 917 return showInvalidArguments(writer); 918 } 919 injectKey(args, writer); 920 break; 921 case COMMAND_INJECT_ROTARY: 922 if (args.length < 1) { 923 return showInvalidArguments(writer); 924 } 925 injectRotary(args, writer); 926 break; 927 case COMMAND_INJECT_CUSTOM_INPUT: 928 if (args.length < 2) { 929 return showInvalidArguments(writer); 930 } 931 injectCustomInputEvent(args, writer); 932 break; 933 case COMMAND_GET_INITIAL_USER_INFO: 934 getInitialUserInfo(args, writer); 935 break; 936 case COMMAND_SWITCH_USER: 937 switchUser(args, writer); 938 break; 939 case COMMAND_REMOVE_USER: 940 removeUser(args, writer); 941 break; 942 case COMMAND_CREATE_USER: 943 createUser(args, writer); 944 break; 945 case COMMAND_GET_INITIAL_USER: 946 getInitialUser(writer); 947 break; 948 case COMMAND_GET_USER_AUTH_ASSOCIATION: 949 getUserAuthAssociation(args, writer); 950 break; 951 case COMMAND_SET_USER_AUTH_ASSOCIATION: 952 setUserAuthAssociation(args, writer); 953 break; 954 case COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE: 955 setStartBackgroundUsersOnGarageMode(args, writer); 956 break; 957 case COMMAND_EMULATE_DRIVING_STATE: 958 emulateDrivingState(args, writer); 959 break; 960 case COMMAND_DEFINE_POWER_POLICY: 961 return definePowerPolicy(args, writer); 962 case COMMAND_APPLY_POWER_POLICY: 963 return applyPowerPolicy(args, writer); 964 case COMMAND_DEFINE_POWER_POLICY_GROUP: 965 return definePowerPolicyGroup(args, writer); 966 case COMMAND_SET_POWER_POLICY_GROUP: 967 return setPowerPolicyGroup(args, writer); 968 case COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY: 969 return applyCtsVerifierPowerOffPolicy(args, writer); 970 case COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY: 971 return applyCtsVerifierPowerOnPolicy(args, writer); 972 case COMMAND_POWER_OFF: 973 powerOff(args, writer); 974 break; 975 case COMMAND_SET_REARVIEW_CAMERA_ID: 976 setRearviewCameraId(args, writer); 977 break; 978 case COMMAND_GET_REARVIEW_CAMERA_ID: 979 getRearviewCameraId(writer); 980 break; 981 case COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE: 982 controlWatchdogPackageKillableState(args, writer); 983 break; 984 case COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES: 985 setWatchdogIoThirdPartyForegroundBytes(args, writer); 986 break; 987 case COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES: 988 getWatchdogIoThirdPartyForegroundBytes(writer); 989 break; 990 case COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK: 991 controlWatchdogProcessHealthCheck(args, writer); 992 break; 993 case COMMAND_DRIVING_SAFETY_SET_REGION: 994 setDrivingSafetyRegion(args, writer); 995 break; 996 default: 997 writer.println("Unknown command: \"" + cmd + "\""); 998 showHelp(writer); 999 return RESULT_ERROR; 1000 } 1001 return RESULT_OK; 1002 } 1003 1004 private void setStartBackgroundUsersOnGarageMode(String[] args, IndentingPrintWriter writer) { 1005 if (args.length < 2) { 1006 writer.println("Insufficient number of args"); 1007 return; 1008 } 1009 1010 boolean enabled = Boolean.parseBoolean(args[1]); 1011 Slog.d(TAG, "setStartBackgroundUsersOnGarageMode(): " + (enabled ? "enabled" : "disabled")); 1012 mCarUserService.setStartBackgroundUsersOnGarageMode(enabled); 1013 writer.printf("StartBackgroundUsersOnGarageMode set to %b\n", enabled); 1014 } 1015 1016 private void startFixedActivity(String[] args, IndentingPrintWriter writer) { 1017 if (args.length != 4) { 1018 writer.println("Incorrect number of arguments"); 1019 showHelp(writer); 1020 return; 1021 } 1022 int displayId; 1023 try { 1024 displayId = Integer.parseInt(args[1]); 1025 } catch (NumberFormatException e) { 1026 writer.println("Wrong display id:" + args[1]); 1027 return; 1028 } 1029 String packageName = args[2]; 1030 String activityName = args[3]; 1031 Intent intent = new Intent(); 1032 intent.setComponent(new ComponentName(packageName, activityName)); 1033 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1034 ActivityOptions options = ActivityOptions.makeBasic(); 1035 options.setLaunchDisplayId(displayId); 1036 if (!mFixedActivityService.startFixedActivityModeForDisplayAndUser(intent, options, 1037 displayId, ActivityManager.getCurrentUser())) { 1038 writer.println("Failed to start"); 1039 return; 1040 } 1041 writer.println("Succeeded"); 1042 } 1043 1044 private void stopFixedMode(String[] args, IndentingPrintWriter writer) { 1045 if (args.length != 2) { 1046 writer.println("Incorrect number of arguments"); 1047 showHelp(writer); 1048 return; 1049 } 1050 int displayId; 1051 try { 1052 displayId = Integer.parseInt(args[1]); 1053 } catch (NumberFormatException e) { 1054 writer.println("Wrong display id:" + args[1]); 1055 return; 1056 } 1057 mFixedActivityService.stopFixedActivityMode(displayId); 1058 } 1059 1060 private void enableDisableFeature(String[] args, IndentingPrintWriter writer, boolean enable) { 1061 if (Binder.getCallingUid() != Process.ROOT_UID) { 1062 writer.println("Only allowed to root/su"); 1063 return; 1064 } 1065 String featureName = args[1]; 1066 long id = Binder.clearCallingIdentity(); 1067 // no permission check here 1068 int r; 1069 if (enable) { 1070 r = mFeatureController.enableFeature(featureName); 1071 } else { 1072 r = mFeatureController.disableFeature(featureName); 1073 } 1074 switch (r) { 1075 case Car.FEATURE_REQUEST_SUCCESS: 1076 if (enable) { 1077 writer.println("Enabled feature:" + featureName); 1078 } else { 1079 writer.println("Disabled feature:" + featureName); 1080 } 1081 break; 1082 case Car.FEATURE_REQUEST_ALREADY_IN_THE_STATE: 1083 if (enable) { 1084 writer.println("Already enabled:" + featureName); 1085 } else { 1086 writer.println("Already disabled:" + featureName); 1087 } 1088 break; 1089 case Car.FEATURE_REQUEST_MANDATORY: 1090 writer.println("Cannot change mandatory feature:" + featureName); 1091 break; 1092 case Car.FEATURE_REQUEST_NOT_EXISTING: 1093 writer.println("Non-existing feature:" + featureName); 1094 break; 1095 default: 1096 writer.println("Unknown error:" + r); 1097 break; 1098 } 1099 Binder.restoreCallingIdentity(id); 1100 } 1101 1102 private void injectKey(String[] args, IndentingPrintWriter writer) { 1103 int i = 1; // 0 is command itself 1104 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 1105 int delayMs = 0; 1106 int keyCode = KeyEvent.KEYCODE_UNKNOWN; 1107 int action = -1; 1108 try { 1109 while (i < args.length) { 1110 switch (args[i]) { 1111 case "-d": 1112 i++; 1113 int vehicleDisplay = Integer.parseInt(args[i]); 1114 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 1115 return; 1116 } 1117 display = InputHalService.convertDisplayType(vehicleDisplay); 1118 break; 1119 case "-t": 1120 i++; 1121 delayMs = Integer.parseInt(args[i]); 1122 break; 1123 case "-a": 1124 i++; 1125 if (args[i].equalsIgnoreCase("down")) { 1126 action = KeyEvent.ACTION_DOWN; 1127 } else if (args[i].equalsIgnoreCase("up")) { 1128 action = KeyEvent.ACTION_UP; 1129 } else { 1130 throw new IllegalArgumentException("Invalid action: " + args[i]); 1131 } 1132 break; 1133 default: 1134 if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { 1135 throw new IllegalArgumentException("key_code already set:" 1136 + keyCode); 1137 } 1138 keyCode = Integer.parseInt(args[i]); 1139 } 1140 i++; 1141 } 1142 } catch (NumberFormatException e) { 1143 writer.println("Invalid args:" + e); 1144 showHelp(writer); 1145 return; 1146 } 1147 if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { 1148 writer.println("Missing key code or invalid keycode"); 1149 showHelp(writer); 1150 return; 1151 } 1152 if (delayMs < 0) { 1153 writer.println("Invalid delay:" + delayMs); 1154 showHelp(writer); 1155 1156 return; 1157 } 1158 if (action == -1) { 1159 injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, display); 1160 SystemClock.sleep(delayMs); 1161 injectKeyEvent(KeyEvent.ACTION_UP, keyCode, display); 1162 } else { 1163 injectKeyEvent(action, keyCode, display); 1164 } 1165 writer.println("Succeeded"); 1166 } 1167 1168 private void injectKeyEvent(int action, int keyCode, int display) { 1169 long currentTime = SystemClock.uptimeMillis(); 1170 if (action == KeyEvent.ACTION_DOWN) mKeyDownTime = currentTime; 1171 long token = Binder.clearCallingIdentity(); 1172 try { 1173 mCarInputService.injectKeyEvent( 1174 new KeyEvent(/* downTime= */ mKeyDownTime, /* eventTime= */ currentTime, 1175 action, keyCode, /* repeat= */ 0), display); 1176 } finally { 1177 Binder.restoreCallingIdentity(token); 1178 } 1179 } 1180 1181 private void injectRotary(String[] args, IndentingPrintWriter writer) { 1182 int i = 1; // 0 is command itself 1183 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 1184 int inputType = CarInputManager.INPUT_TYPE_ROTARY_NAVIGATION; 1185 boolean clockwise = false; 1186 List<Long> deltaTimeMs = new ArrayList<>(); 1187 try { 1188 while (i < args.length) { 1189 switch (args[i]) { 1190 case "-d": 1191 i++; 1192 int vehicleDisplay = Integer.parseInt(args[i]); 1193 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 1194 return; 1195 } 1196 display = InputHalService.convertDisplayType(vehicleDisplay); 1197 break; 1198 case "-i": 1199 i++; 1200 inputType = Integer.parseInt(args[i]); 1201 break; 1202 case "-c": 1203 i++; 1204 clockwise = Boolean.parseBoolean(args[i]); 1205 break; 1206 case "-dt": 1207 i++; 1208 while (i < args.length) { 1209 deltaTimeMs.add(Long.parseLong(args[i])); 1210 i++; 1211 } 1212 break; 1213 default: 1214 writer.println("Invalid option at index " + i + ": " + args[i]); 1215 return; 1216 } 1217 i++; 1218 } 1219 } catch (NumberFormatException e) { 1220 writer.println("Invalid args:" + e); 1221 showHelp(writer); 1222 return; 1223 } 1224 if (deltaTimeMs.isEmpty()) { 1225 deltaTimeMs.add(0L); 1226 } 1227 for (int j = 0; j < deltaTimeMs.size(); j++) { 1228 if (deltaTimeMs.get(j) < 0) { 1229 writer.println("Delta time shouldn't be negative: " + deltaTimeMs.get(j)); 1230 showHelp(writer); 1231 return; 1232 } 1233 if (j > 0 && deltaTimeMs.get(j) > deltaTimeMs.get(j - 1)) { 1234 writer.println("Delta times should be in descending order"); 1235 showHelp(writer); 1236 return; 1237 } 1238 } 1239 long[] uptimeMs = new long[deltaTimeMs.size()]; 1240 long currentUptime = SystemClock.uptimeMillis(); 1241 for (int j = 0; j < deltaTimeMs.size(); j++) { 1242 uptimeMs[j] = currentUptime - deltaTimeMs.get(j); 1243 } 1244 RotaryEvent rotaryEvent = new RotaryEvent(inputType, clockwise, uptimeMs); 1245 mCarInputService.onRotaryEvent(rotaryEvent, display); 1246 writer.println("Succeeded in injecting: " + rotaryEvent); 1247 } 1248 1249 private void injectCustomInputEvent(String[] args, IndentingPrintWriter writer) { 1250 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 1251 int repeatCounter = 1; 1252 1253 int argIdx = 1; 1254 for (; argIdx < args.length - 1; argIdx++) { 1255 switch (args[argIdx]) { 1256 case "-d": 1257 int vehicleDisplay = Integer.parseInt(args[++argIdx]); 1258 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 1259 return; 1260 } 1261 display = InputHalService.convertDisplayType(vehicleDisplay); 1262 break; 1263 case "-r": 1264 repeatCounter = Integer.parseInt(args[++argIdx]); 1265 break; 1266 default: 1267 writer.printf("Unrecognized argument: {%s}\n", args[argIdx]); 1268 writer.println("Pass -help to see the full list of options"); 1269 return; 1270 } 1271 } 1272 1273 if (argIdx == args.length) { 1274 writer.println("Last mandatory argument (fn) not passed."); 1275 writer.println("Pass -help to see the full list of options"); 1276 return; 1277 } 1278 1279 // Processing the last remaining argument (expected to be 'f1', 'f2', ..., 'f10'). 1280 String eventValue = args[argIdx].toLowerCase(); 1281 Integer inputCode = CUSTOM_INPUT_FUNCTION_ARGS.get(eventValue); 1282 if (inputCode == null) { 1283 writer.printf("Invalid input event value {%s}, valid values are f1, f2, ..., f10\n", 1284 eventValue); 1285 writer.println("Pass -help to see the full list of options"); 1286 return; 1287 } 1288 1289 CustomInputEvent event = new CustomInputEvent(inputCode, display, repeatCounter); 1290 mCarInputService.onCustomInputEvent(event); 1291 writer.printf("Succeeded in injecting {%s}\n", event); 1292 } 1293 1294 private boolean checkVehicleDisplay(int vehicleDisplay, IndentingPrintWriter writer) { 1295 if (vehicleDisplay != VehicleDisplay.MAIN 1296 && vehicleDisplay != VehicleDisplay.INSTRUMENT_CLUSTER) { 1297 writer.println("Invalid display:" + vehicleDisplay); 1298 showHelp(writer); 1299 return false; 1300 } 1301 return true; 1302 } 1303 1304 private void getInitialUserInfo(String[] args, IndentingPrintWriter writer) { 1305 if (args.length < 2) { 1306 writer.println("Insufficient number of args"); 1307 return; 1308 } 1309 1310 // Gets the request type 1311 String typeArg = args[1]; 1312 int requestType = UserHalHelper.parseInitialUserInfoRequestType(typeArg); 1313 1314 int timeout = DEFAULT_HAL_TIMEOUT_MS; 1315 for (int i = 2; i < args.length; i++) { 1316 String arg = args[i]; 1317 switch (arg) { 1318 case "--timeout": 1319 timeout = Integer.parseInt(args[++i]); 1320 break; 1321 default: 1322 writer.println("Invalid option at index " + i + ": " + arg); 1323 return; 1324 1325 } 1326 } 1327 1328 Slog.d(TAG, "handleGetInitialUserInfo(): type=" + requestType + " (" + typeArg 1329 + "), timeout=" + timeout); 1330 1331 CountDownLatch latch = new CountDownLatch(1); 1332 HalCallback<InitialUserInfoResponse> callback = (status, resp) -> { 1333 try { 1334 Slog.d(TAG, "GetUserInfoResponse: status=" + status + ", resp=" + resp); 1335 writer.printf("Call status: %s\n", 1336 UserHalHelper.halCallbackStatusToString(status)); 1337 if (status != HalCallback.STATUS_OK) { 1338 return; 1339 } 1340 writer.printf("Request id: %d\n", resp.requestId); 1341 writer.printf("Action: %s\n", 1342 InitialUserInfoResponseAction.toString(resp.action)); 1343 if (!TextUtils.isEmpty(resp.userNameToCreate)) { 1344 writer.printf("User name: %s\n", resp.userNameToCreate); 1345 } 1346 if (resp.userToSwitchOrCreate.userId != UserHandle.USER_NULL) { 1347 writer.printf("User id: %d\n", resp.userToSwitchOrCreate.userId); 1348 } 1349 if (resp.userToSwitchOrCreate.flags != UserFlags.NONE) { 1350 writer.printf("User flags: %s\n", 1351 UserHalHelper.userFlagsToString(resp.userToSwitchOrCreate.flags)); 1352 } 1353 if (!TextUtils.isEmpty(resp.userLocales)) { 1354 writer.printf("User locales: %s\n", resp.userLocales); 1355 } 1356 } finally { 1357 latch.countDown(); 1358 } 1359 }; 1360 UsersInfo usersInfo = generateUsersInfo(); 1361 mHal.getUserHal().getInitialUserInfo(requestType, timeout, usersInfo, callback); 1362 waitForHal(writer, latch, timeout); 1363 } 1364 1365 private UsersInfo generateUsersInfo() { 1366 return UserHalHelper.newUsersInfo(UserManager.get(mContext)); 1367 } 1368 1369 private int getUserHalFlags(@UserIdInt int userId) { 1370 return UserHalHelper.getFlags(UserManager.get(mContext), userId); 1371 } 1372 1373 private static void waitForHal(IndentingPrintWriter writer, CountDownLatch latch, 1374 int timeoutMs) { 1375 try { 1376 if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { 1377 writer.printf("HAL didn't respond in %dms\n", timeoutMs); 1378 } 1379 } catch (InterruptedException e) { 1380 Thread.currentThread().interrupt(); 1381 writer.println("Interrupted waiting for HAL"); 1382 } 1383 return; 1384 } 1385 1386 private void switchUser(String[] args, IndentingPrintWriter writer) { 1387 if (args.length < 2) { 1388 writer.println("Insufficient number of args"); 1389 return; 1390 } 1391 1392 int targetUserId = Integer.parseInt(args[1]); 1393 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 1394 boolean halOnly = false; 1395 1396 for (int i = 2; i < args.length; i++) { 1397 String arg = args[i]; 1398 switch (arg) { 1399 case "--timeout": 1400 timeout = Integer.parseInt(args[++i]); 1401 break; 1402 case "--hal-only": 1403 halOnly = true; 1404 break; 1405 default: 1406 writer.println("Invalid option at index " + i + ": " + arg); 1407 return; 1408 } 1409 } 1410 1411 Slog.d(TAG, "switchUser(): target=" + targetUserId + ", halOnly=" + halOnly 1412 + ", timeout=" + timeout); 1413 1414 if (halOnly) { 1415 CountDownLatch latch = new CountDownLatch(1); 1416 UserHalService userHal = mHal.getUserHal(); 1417 UserInfo targetUserInfo = new UserInfo(); 1418 targetUserInfo.userId = targetUserId; 1419 targetUserInfo.flags = getUserHalFlags(targetUserId); 1420 1421 SwitchUserRequest request = new SwitchUserRequest(); 1422 request.targetUser = targetUserInfo; 1423 request.usersInfo = generateUsersInfo(); 1424 1425 userHal.switchUser(request, timeout, (status, resp) -> { 1426 try { 1427 Slog.d(TAG, "SwitchUserResponse: status=" + status + ", resp=" + resp); 1428 writer.printf("Call Status: %s\n", 1429 UserHalHelper.halCallbackStatusToString(status)); 1430 if (status != HalCallback.STATUS_OK) { 1431 return; 1432 } 1433 writer.printf("Request id: %d\n", resp.requestId); 1434 writer.printf("Message type: %s\n", 1435 SwitchUserMessageType.toString(resp.messageType)); 1436 writer.printf("Switch Status: %s\n", SwitchUserStatus.toString(resp.status)); 1437 String errorMessage = resp.errorMessage; 1438 if (!TextUtils.isEmpty(errorMessage)) { 1439 writer.printf("Error message: %s", errorMessage); 1440 } 1441 // If HAL returned OK, make a "post-switch" call to the HAL indicating an 1442 // Android error. This is to "rollback" the HAL switch. 1443 if (status == HalCallback.STATUS_OK 1444 && resp.status == SwitchUserStatus.SUCCESS) { 1445 userHal.postSwitchResponse(request); 1446 } 1447 } finally { 1448 latch.countDown(); 1449 } 1450 }); 1451 waitForHal(writer, latch, timeout); 1452 return; 1453 } 1454 CarUserManager carUserManager = getCarUserManager(mContext); 1455 AsyncFuture<UserSwitchResult> future = carUserManager.switchUser(targetUserId); 1456 UserSwitchResult result = waitForFuture(writer, future, timeout); 1457 if (result == null) return; 1458 writer.printf("UserSwitchResult: status=%s", 1459 UserSwitchResult.statusToString(result.getStatus())); 1460 String msg = result.getErrorMessage(); 1461 if (!TextUtils.isEmpty(msg)) { 1462 writer.printf(", errorMessage=%s", msg); 1463 } 1464 writer.println(); 1465 } 1466 1467 private void createUser(String[] args, IndentingPrintWriter writer) { 1468 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 1469 int flags = 0; 1470 boolean halOnly = false; 1471 String name = null; 1472 String userType = null; 1473 1474 for (int i = 1; i < args.length; i++) { 1475 String arg = args[i]; 1476 switch (arg) { 1477 case "--timeout": 1478 timeout = Integer.parseInt(args[++i]); 1479 break; 1480 case "--hal-only": 1481 halOnly = true; 1482 break; 1483 case "--flags": 1484 flags = Integer.parseInt(args[++i]); 1485 break; 1486 case "--type": 1487 userType = args[++i]; 1488 break; 1489 default: 1490 if (name != null) { 1491 writer.println("Invalid option at index " + i + ": " + arg); 1492 return; 1493 } 1494 name = arg; 1495 } 1496 } 1497 1498 if (userType == null) { 1499 userType = android.content.pm.UserInfo.getDefaultUserType(flags); 1500 } 1501 1502 Slog.d(TAG, "createUser(): name=" + name + ", userType=" + userType 1503 + ", flags=" + android.content.pm.UserInfo.flagsToString(flags) 1504 + ", halOnly=" + halOnly + ", timeout=" + timeout); 1505 1506 if (!halOnly) { 1507 CarUserManager carUserManager = getCarUserManager(mContext); 1508 AsyncFuture<UserCreationResult> future = carUserManager 1509 .createUser(name, userType, flags); 1510 1511 UserCreationResult result = waitForFuture(writer, future, timeout); 1512 if (result == null) return; 1513 1514 android.content.pm.UserInfo user = result.getUser(); 1515 writer.printf("UserCreationResult: status=%s, user=%s", 1516 UserCreationResult.statusToString(result.getStatus()), 1517 user == null ? "N/A" : user.toFullString()); 1518 String msg = result.getErrorMessage(); 1519 if (!TextUtils.isEmpty(msg)) { 1520 writer.printf(", errorMessage=%s", msg); 1521 } 1522 writer.println(); 1523 return; 1524 } 1525 1526 CountDownLatch latch = new CountDownLatch(1); 1527 UserHalService userHal = mHal.getUserHal(); 1528 1529 CreateUserRequest request = new CreateUserRequest(); 1530 1531 UserManager um = UserManager.get(mContext); 1532 android.content.pm.UserInfo newUser = um.createUser(name, userType, flags); 1533 if (newUser == null) { 1534 writer.printf("Failed to create user"); 1535 return; 1536 } 1537 writer.printf("New user: %s\n", newUser.toFullString()); 1538 Slog.i(TAG, "Created new user: " + newUser.toFullString()); 1539 1540 request.newUserInfo.userId = newUser.id; 1541 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser); 1542 1543 request.usersInfo = generateUsersInfo(); 1544 1545 AtomicBoolean halOk = new AtomicBoolean(false); 1546 try { 1547 userHal.createUser(request, timeout, (status, resp) -> { 1548 Slog.d(TAG, "CreateUserResponse: status=" + status + ", resp=" + resp); 1549 writer.printf("Call Status: %s\n", 1550 UserHalHelper.halCallbackStatusToString(status)); 1551 if (status == HalCallback.STATUS_OK) { 1552 halOk.set(resp.status == CreateUserStatus.SUCCESS); 1553 writer.printf("Request id: %d\n", resp.requestId); 1554 writer.printf("Create Status: %s\n", CreateUserStatus.toString(resp.status)); 1555 String errorMessage = resp.errorMessage; 1556 if (!TextUtils.isEmpty(errorMessage)) { 1557 writer.printf("Error message: %s", errorMessage); 1558 } 1559 } 1560 latch.countDown(); 1561 }); 1562 waitForHal(writer, latch, timeout); 1563 } catch (RuntimeException e) { 1564 writer.printf("HAL failed: %s\n", e); 1565 } finally { 1566 if (!halOk.get()) { 1567 writer.printf("Removing user %d due to HAL failure\n", newUser.id); 1568 boolean removed = um.removeUser(newUser.id); 1569 writer.printf("User removed: %b\n", removed); 1570 } 1571 } 1572 } 1573 1574 private void removeUser(String[] args, IndentingPrintWriter writer) { 1575 if (args.length < 2) { 1576 writer.println("Insufficient number of args"); 1577 return; 1578 } 1579 1580 int userId = Integer.parseInt(args[1]); 1581 boolean halOnly = false; 1582 1583 for (int i = 2; i < args.length; i++) { 1584 String arg = args[i]; 1585 switch (arg) { 1586 case "--hal-only": 1587 halOnly = true; 1588 break; 1589 default: 1590 writer.println("Invalid option at index " + i + ": " + arg); 1591 return; 1592 } 1593 } 1594 1595 Slog.d(TAG, "handleRemoveUser(): User to remove=" + userId + ", halOnly=" + halOnly); 1596 1597 if (halOnly) { 1598 UserHalService userHal = mHal.getUserHal(); 1599 UsersInfo usersInfo = generateUsersInfo(); 1600 UserInfo userInfo = new UserInfo(); 1601 userInfo.userId = userId; 1602 userInfo.flags = getUserHalFlags(userId); 1603 1604 RemoveUserRequest request = new RemoveUserRequest(); 1605 request.removedUserInfo = userInfo; 1606 request.usersInfo = usersInfo; 1607 1608 userHal.removeUser(request); 1609 writer.printf("User removal sent for HAL only.\n"); 1610 return; 1611 } 1612 1613 CarUserManager carUserManager = getCarUserManager(mContext); 1614 UserRemovalResult result = carUserManager.removeUser(userId); 1615 writer.printf("UserRemovalResult: status = %s\n", 1616 UserRemovalResult.statusToString(result.getStatus())); 1617 } 1618 1619 private static <T> T waitForFuture(@NonNull IndentingPrintWriter writer, 1620 @NonNull AsyncFuture<T> future, int timeoutMs) { 1621 T result = null; 1622 try { 1623 result = future.get(timeoutMs, TimeUnit.MILLISECONDS); 1624 if (result == null) { 1625 writer.printf("Service didn't respond in %d ms", timeoutMs); 1626 } 1627 } catch (InterruptedException e) { 1628 Thread.currentThread().interrupt(); 1629 } catch (ExecutionException | TimeoutException e) { 1630 writer.printf("Exception getting future: %s", e); 1631 } 1632 return result; 1633 } 1634 1635 private void getInitialUser(IndentingPrintWriter writer) { 1636 UserHandle user = mCarUserService.getInitialUser(); 1637 writer.println(user == null ? NO_INITIAL_USER : user.getIdentifier()); 1638 } 1639 1640 private void getUserAuthAssociation(String[] args, IndentingPrintWriter writer) { 1641 if (args.length < 2) { 1642 writer.println("invalid usage, must pass at least 1 argument"); 1643 return; 1644 } 1645 1646 boolean halOnly = false; 1647 int userId = UserHandle.USER_CURRENT; 1648 1649 UserIdentificationGetRequest request = new UserIdentificationGetRequest(); 1650 for (int i = 1; i < args.length; i++) { 1651 String arg = args[i]; 1652 switch (arg) { 1653 case "--user": 1654 try { 1655 userId = Integer.parseInt(args[++i]); 1656 } catch (NumberFormatException e) { 1657 writer.printf("Invalid user id at index %d (from %s): %s\n", i + 1, 1658 Arrays.toString(args), arg); 1659 } 1660 break; 1661 case "--hal-only": 1662 halOnly = true; 1663 break; 1664 default: 1665 int type = parseAuthArg(VALID_USER_AUTH_TYPES, arg); 1666 if (type == INVALID_USER_AUTH_TYPE_OR_VALUE) { 1667 writer.printf("Invalid type at index %d (from %s): %s. %s\n", i + 1, 1668 Arrays.toString(args), arg, VALID_USER_AUTH_TYPES_HELP); 1669 return; 1670 } 1671 request.associationTypes.add(type); 1672 } 1673 1674 } 1675 if (userId == UserHandle.USER_CURRENT) { 1676 userId = ActivityManager.getCurrentUser(); 1677 } 1678 int requestSize = request.associationTypes.size(); 1679 if (halOnly) { 1680 request.numberAssociationTypes = requestSize; 1681 request.userInfo.userId = userId; 1682 request.userInfo.flags = getUserHalFlags(userId); 1683 1684 Slog.d(TAG, "getUserAuthAssociation(): user=" + userId + ", halOnly=" + halOnly 1685 + ", request=" + request); 1686 UserIdentificationResponse response = mHal.getUserHal().getUserAssociation(request); 1687 Slog.d(TAG, "getUserAuthAssociation(): response=" + response); 1688 showResponse(writer, response); 1689 return; 1690 } 1691 1692 CarUserManager carUserManager = getCarUserManager(writer, userId); 1693 int[] types = new int[requestSize]; 1694 for (int i = 0; i < requestSize; i++) { 1695 types[i] = request.associationTypes.get(i); 1696 } 1697 UserIdentificationAssociationResponse response = carUserManager 1698 .getUserIdentificationAssociation(types); 1699 showResponse(writer, response); 1700 } 1701 1702 private CarUserManager getCarUserManager(@NonNull IndentingPrintWriter writer, 1703 @UserIdInt int userId) { 1704 Context context; 1705 if (userId == mContext.getUserId()) { 1706 context = mContext; 1707 } else { 1708 context = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0); 1709 } 1710 int actualUserId = Binder.getCallingUid(); 1711 if (actualUserId != userId) { 1712 writer.printf("Emulating call for user id %d, but caller's user id is %d, so that's " 1713 + "what CarUserService will use when calling HAL.\n", userId, actualUserId); 1714 } 1715 1716 return getCarUserManager(context); 1717 } 1718 1719 private CarUserManager getCarUserManager(@NonNull Context context) { 1720 Car car = Car.createCar(context); 1721 CarUserManager carUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE); 1722 return carUserManager; 1723 } 1724 1725 private void showResponse(@NonNull IndentingPrintWriter writer, 1726 @NonNull UserIdentificationResponse response) { 1727 if (response == null) { 1728 writer.println("null response"); 1729 return; 1730 } 1731 1732 if (!TextUtils.isEmpty(response.errorMessage)) { 1733 writer.printf("Error message: %s\n", response.errorMessage); 1734 } 1735 int numberAssociations = response.associations.size(); 1736 writer.printf("%d associations:\n", numberAssociations); 1737 for (int i = 0; i < numberAssociations; i++) { 1738 UserIdentificationAssociation association = response.associations.get(i); 1739 writer.printf(" %s\n", association); 1740 } 1741 } 1742 1743 private void showResponse(@NonNull IndentingPrintWriter writer, 1744 @NonNull UserIdentificationAssociationResponse response) { 1745 if (response == null) { 1746 writer.println("null response"); 1747 return; 1748 } 1749 if (!response.isSuccess()) { 1750 writer.printf("failed response: %s\n", response); 1751 return; 1752 } 1753 String errorMessage = response.getErrorMessage(); 1754 if (!TextUtils.isEmpty(errorMessage)) { 1755 writer.printf("Error message: %s\n", errorMessage); 1756 } 1757 int[] values = response.getValues(); 1758 if (values == null) { 1759 writer.printf("no associations on %s\n", response); 1760 return; 1761 } 1762 writer.printf("%d associations:\n", values.length); 1763 for (int i = 0; i < values.length; i++) { 1764 writer.printf(" %s\n", UserIdentificationAssociationValue.toString(values[i])); 1765 } 1766 } 1767 1768 private void setUserAuthAssociation(String[] args, IndentingPrintWriter writer) { 1769 if (args.length < 3) { 1770 writer.println("invalid usage, must pass at least 4 arguments"); 1771 return; 1772 } 1773 1774 boolean halOnly = false; 1775 int timeout = DEFAULT_HAL_TIMEOUT_MS; 1776 int userId = UserHandle.USER_CURRENT; 1777 1778 UserIdentificationSetRequest request = new UserIdentificationSetRequest(); 1779 for (int i = 1; i < args.length; i++) { 1780 String arg = args[i]; 1781 switch (arg) { 1782 case "--user": 1783 try { 1784 userId = Integer.parseInt(args[++i]); 1785 } catch (NumberFormatException e) { 1786 writer.printf("Invalid user id at index %d (from %s): %s\n", i + 1, 1787 Arrays.toString(args), arg); 1788 } 1789 break; 1790 case "--hal-only": 1791 halOnly = true; 1792 break; 1793 case "--timeout": 1794 timeout = Integer.parseInt(args[++i]); 1795 break; 1796 default: 1797 UserIdentificationSetAssociation association = 1798 new UserIdentificationSetAssociation(); 1799 association.type = parseAuthArg(VALID_USER_AUTH_TYPES, arg); 1800 if (association.type == INVALID_USER_AUTH_TYPE_OR_VALUE) { 1801 writer.printf("Invalid type at index %d (from %s): %s. %s\n", i + 1, 1802 Arrays.toString(args), arg, VALID_USER_AUTH_TYPES_HELP); 1803 return; 1804 } 1805 association.value = parseAuthArg(VALID_USER_AUTH_SET_VALUES, args[++i]); 1806 if (association.value == INVALID_USER_AUTH_TYPE_OR_VALUE) { 1807 writer.printf("Invalid value at index %d (from %s): %s. %s\n", i + 1, 1808 Arrays.toString(args), arg, VALID_USER_AUTH_SET_VALUES_HELP); 1809 return; 1810 } 1811 request.associations.add(association); 1812 } 1813 1814 } 1815 if (userId == UserHandle.USER_CURRENT) { 1816 userId = ActivityManager.getCurrentUser(); 1817 } 1818 int requestSize = request.associations.size(); 1819 if (halOnly) { 1820 request.numberAssociations = requestSize; 1821 request.userInfo.userId = userId; 1822 request.userInfo.flags = getUserHalFlags(userId); 1823 1824 Slog.d(TAG, "setUserAuthAssociation(): user=" + userId + ", halOnly=" + halOnly 1825 + ", request=" + request); 1826 CountDownLatch latch = new CountDownLatch(1); 1827 mHal.getUserHal().setUserAssociation(timeout, request, (status, response) -> { 1828 Slog.d(TAG, "setUserAuthAssociation(): response=" + response); 1829 try { 1830 showResponse(writer, response); 1831 } finally { 1832 latch.countDown(); 1833 } 1834 }); 1835 waitForHal(writer, latch, timeout); 1836 return; 1837 } 1838 CarUserManager carUserManager = getCarUserManager(writer, userId); 1839 int[] types = new int[requestSize]; 1840 int[] values = new int[requestSize]; 1841 for (int i = 0; i < requestSize; i++) { 1842 UserIdentificationSetAssociation association = request.associations.get(i); 1843 types[i] = association.type; 1844 values[i] = association.value; 1845 } 1846 AsyncFuture<UserIdentificationAssociationResponse> future = carUserManager 1847 .setUserIdentificationAssociation(types, values); 1848 UserIdentificationAssociationResponse response = waitForFuture(writer, future, timeout); 1849 if (response != null) { 1850 showResponse(writer, response); 1851 } 1852 } 1853 1854 private static int parseAuthArg(@NonNull SparseArray<String> types, @NonNull String type) { 1855 for (int i = 0; i < types.size(); i++) { 1856 if (types.valueAt(i).equals(type)) { 1857 return types.keyAt(i); 1858 } 1859 } 1860 return INVALID_USER_AUTH_TYPE_OR_VALUE; 1861 } 1862 1863 private void forceDayNightMode(String arg, IndentingPrintWriter writer) { 1864 int mode; 1865 switch (arg) { 1866 case PARAM_DAY_MODE: 1867 mode = CarNightService.FORCED_DAY_MODE; 1868 break; 1869 case PARAM_NIGHT_MODE: 1870 mode = CarNightService.FORCED_NIGHT_MODE; 1871 break; 1872 case PARAM_SENSOR_MODE: 1873 mode = CarNightService.FORCED_SENSOR_MODE; 1874 break; 1875 default: 1876 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s\n", 1877 arg, PARAM_DAY_MODE, PARAM_NIGHT_MODE, PARAM_SENSOR_MODE); 1878 return; 1879 } 1880 int current = mCarNightService.forceDayNightMode(mode); 1881 String currentMode = null; 1882 switch (current) { 1883 case UiModeManager.MODE_NIGHT_AUTO: 1884 currentMode = PARAM_SENSOR_MODE; 1885 break; 1886 case UiModeManager.MODE_NIGHT_YES: 1887 currentMode = PARAM_NIGHT_MODE; 1888 break; 1889 case UiModeManager.MODE_NIGHT_NO: 1890 currentMode = PARAM_DAY_MODE; 1891 break; 1892 } 1893 writer.println("DayNightMode changed to: " + currentMode); 1894 } 1895 1896 private void forceGarageMode(String arg, IndentingPrintWriter writer) { 1897 switch (arg) { 1898 case PARAM_ON_MODE: 1899 mSystemInterface.setDisplayState(false); 1900 mGarageModeService.forceStartGarageMode(); 1901 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 1902 break; 1903 case PARAM_OFF_MODE: 1904 mSystemInterface.setDisplayState(true); 1905 mGarageModeService.stopAndResetGarageMode(); 1906 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 1907 break; 1908 case PARAM_QUERY_MODE: 1909 mGarageModeService.dump(writer); 1910 break; 1911 case PARAM_REBOOT: 1912 mCarPowerManagementService.forceSuspendAndMaybeReboot(true); 1913 writer.println("Entering Garage Mode. Will reboot when it completes."); 1914 break; 1915 default: 1916 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s|%s\n", 1917 arg, PARAM_ON_MODE, PARAM_OFF_MODE, PARAM_QUERY_MODE, PARAM_REBOOT); 1918 } 1919 } 1920 1921 private void runSilentCommand(String arg, IndentingPrintWriter writer) { 1922 switch (arg) { 1923 case SILENT_MODE_FORCED_SILENT: 1924 writer.println("Forcing silent mode to silent"); 1925 mCarPowerManagementService.setSilentMode(SILENT_MODE_FORCED_SILENT); 1926 break; 1927 case SILENT_MODE_FORCED_NON_SILENT: 1928 writer.println("Forcing silent mode to non-silent"); 1929 mCarPowerManagementService.setSilentMode(SILENT_MODE_FORCED_NON_SILENT); 1930 break; 1931 case SILENT_MODE_NON_FORCED: 1932 writer.println("Not forcing silent mode"); 1933 mCarPowerManagementService.setSilentMode(SILENT_MODE_NON_FORCED); 1934 break; 1935 case PARAM_QUERY_MODE: 1936 mCarPowerManagementService.dumpSilentMode(writer); 1937 break; 1938 default: 1939 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s|%s\n", arg, 1940 SILENT_MODE_FORCED_SILENT, SILENT_MODE_FORCED_NON_SILENT, 1941 SILENT_MODE_NON_FORCED, PARAM_QUERY_MODE); 1942 } 1943 } 1944 1945 private void emulateDrivingState(String[] args, IndentingPrintWriter writer) { 1946 if (args.length != 2) { 1947 writer.println("invalid usage, must pass driving state"); 1948 return; 1949 } 1950 String mode = args[1]; 1951 switch (mode) { 1952 case DRIVING_STATE_DRIVE: 1953 emulateDrive(); 1954 break; 1955 case DRIVING_STATE_PARK: 1956 emulatePark(); 1957 break; 1958 case DRIVING_STATE_REVERSE: 1959 emulateReverse(); 1960 break; 1961 default: 1962 writer.printf("invalid driving mode %s; must be %s or %s\n", mode, 1963 DRIVING_STATE_DRIVE, DRIVING_STATE_PARK); 1964 } 1965 } 1966 1967 /** 1968 * Emulates driving mode. Called by 1969 * {@code adb shell cmd car_service emulate-driving-state drive}. 1970 */ 1971 private void emulateDrive() { 1972 Slog.i(TAG, "Emulating driving mode (speed=80mph, gear=8)"); 1973 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 1974 /* zone= */ 0, /* value= */ "80", /* delayTime= */ 2000); 1975 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 1976 /* zone= */ 0, Integer.toString(VehicleGear.GEAR_8), /* delayTime= */ 0); 1977 mHal.injectVhalEvent(VehiclePropertyIds.PARKING_BRAKE_ON, 1978 /* zone= */ 0, /* value= */ "false", /* delayTime= */ 0); 1979 } 1980 1981 /** 1982 * Emulates reverse driving mode. Called by 1983 * {@code adb shell cmd car_service emulate-driving-state reverse}. 1984 */ 1985 private void emulateReverse() { 1986 Slog.i(TAG, "Emulating reverse driving mode (speed=5mph)"); 1987 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 1988 /* zone= */ 0, /* value= */ "5", /* delayTime= */ 2000); 1989 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 1990 /* zone= */ 0, Integer.toString(VehicleGear.GEAR_REVERSE), /* delayTime= */ 0); 1991 mHal.injectVhalEvent(VehiclePropertyIds.PARKING_BRAKE_ON, 1992 /* zone= */ 0, /* value= */ "false", /* delayTime= */ 0); 1993 } 1994 1995 /** 1996 * Emulates parking mode. Called by 1997 * {@code adb shell cmd car_service emulate-driving-state park}. 1998 */ 1999 private void emulatePark() { 2000 Slog.i(TAG, "Emulating parking mode"); 2001 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 2002 /* zone= */ 0, /* value= */ "0", /* delayTime= */ 0); 2003 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 2004 /* zone= */ 0, Integer.toString(VehicleGear.GEAR_PARK), /* delayTime= */ 0); 2005 } 2006 2007 private int definePowerPolicy(String[] args, IndentingPrintWriter writer) { 2008 boolean result = mCarPowerManagementService.definePowerPolicyFromCommand(args, writer); 2009 if (result) return RESULT_OK; 2010 writer.printf("\nUsage: cmd car_service %s <POLICY_ID> [--enable COMP1,COMP2,...] " 2011 + "[--disable COMP1,COMP2,...]\n", COMMAND_DEFINE_POWER_POLICY); 2012 return RESULT_ERROR; 2013 } 2014 2015 private int applyPowerPolicy(String[] args, IndentingPrintWriter writer) { 2016 boolean result = mCarPowerManagementService.applyPowerPolicyFromCommand(args, writer); 2017 if (result) return RESULT_OK; 2018 writer.printf("\nUsage: cmd car_service %s <POLICY_ID>\n", COMMAND_APPLY_POWER_POLICY); 2019 return RESULT_ERROR; 2020 } 2021 2022 private int definePowerPolicyGroup(String[] args, IndentingPrintWriter writer) { 2023 boolean result = mCarPowerManagementService.definePowerPolicyGroupFromCommand(args, writer); 2024 if (result) return RESULT_OK; 2025 writer.printf("\nUsage: cmd car_service %s <POLICY_GROUP_ID> [%s:<POLICY_ID>] " 2026 + "[%s:<POLICY_ID>]\n", COMMAND_DEFINE_POWER_POLICY_GROUP, 2027 POWER_STATE_WAIT_FOR_VHAL, POWER_STATE_ON); 2028 return RESULT_ERROR; 2029 } 2030 2031 private int setPowerPolicyGroup(String[] args, IndentingPrintWriter writer) { 2032 boolean result = mCarPowerManagementService.setPowerPolicyGroupFromCommand(args, writer); 2033 if (result) return RESULT_OK; 2034 writer.printf("\nUsage: cmd car_service %s <POLICY_GROUP_ID>\n", 2035 COMMAND_SET_POWER_POLICY_GROUP); 2036 return RESULT_ERROR; 2037 } 2038 2039 private int applyCtsVerifierPowerPolicy(String policyId, String ops, String cmdName, 2040 IndentingPrintWriter writer) { 2041 String[] defArgs = {"define-power-policy", policyId, ops, "WIFI,BLUETOOTH,LOCATION"}; 2042 mCarPowerManagementService.definePowerPolicyFromCommand(defArgs, writer); 2043 2044 String[] appArgs = {"apply-power-policy", policyId}; 2045 boolean result = mCarPowerManagementService.applyPowerPolicyFromCommand(appArgs, writer); 2046 if (result) return RESULT_OK; 2047 2048 writer.printf("\nUsage: cmd car_service %s\n", cmdName); 2049 return RESULT_ERROR; 2050 } 2051 2052 private int applyCtsVerifierPowerOffPolicy(String[] unusedArgs, IndentingPrintWriter writer) { 2053 return applyCtsVerifierPowerPolicy("cts_verifier_off", "--disable", 2054 COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, writer); 2055 } 2056 2057 private int applyCtsVerifierPowerOnPolicy(String[] unusedArgs, IndentingPrintWriter writer) { 2058 return applyCtsVerifierPowerPolicy("cts_verifier_on", "--enable", 2059 COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, writer); 2060 } 2061 2062 private void powerOff(String[] args, IndentingPrintWriter writer) { 2063 int index = 1; 2064 boolean skipGarageMode = false; 2065 boolean shutdown = false; 2066 while (index < args.length) { 2067 switch (args[index]) { 2068 case POWER_OFF_SKIP_GARAGEMODE: 2069 skipGarageMode = true; 2070 break; 2071 case POWER_OFF_SHUTDOWN: 2072 shutdown = true; 2073 break; 2074 default: 2075 writer.printf("Not supported option: %s\n", args[index]); 2076 return; 2077 } 2078 index++; 2079 } 2080 mCarPowerManagementService.powerOffFromCommand(skipGarageMode, shutdown); 2081 } 2082 2083 /** 2084 * Inject a fake VHAL event 2085 * 2086 * @param property the Vehicle property Id as defined in the HAL 2087 * @param zone Zone that this event services 2088 * @param isErrorEvent indicates the type of event 2089 * @param value Data value of the event 2090 * @param delayTime the event timestamp is increased by delayTime 2091 * @param writer IndentingPrintWriter 2092 */ 2093 private void injectVhalEvent(String property, String zone, String value, 2094 boolean isErrorEvent, String delayTime, IndentingPrintWriter writer) { 2095 Slog.i(TAG, "Injecting VHAL event: prop=" + property + ", zone=" + zone + ", value=" 2096 + value + ", isError=" + isErrorEvent 2097 + (TextUtils.isEmpty(delayTime) ? "" : ", delayTime=" + delayTime)); 2098 if (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL)) { 2099 if (!isPropertyAreaTypeGlobal(property)) { 2100 writer.printf("Property area type inconsistent with given zone: %s \n", zone); 2101 return; 2102 } 2103 } 2104 try { 2105 if (isErrorEvent) { 2106 mHal.onPropertySetError(Integer.decode(value), Integer.decode(property), 2107 Integer.decode(zone)); 2108 } else { 2109 mHal.injectVhalEvent(Integer.decode(property), Integer.decode(zone), value, 2110 Integer.decode(delayTime)); 2111 } 2112 } catch (NumberFormatException e) { 2113 writer.printf("Invalid property Id zone Id or value: %s \n", e); 2114 showHelp(writer); 2115 } 2116 } 2117 2118 // Inject continuous vhal events. 2119 private void injectContinuousEvents(String[] args, IndentingPrintWriter writer) { 2120 if (args.length < 3 || args.length > 8) { 2121 showInvalidArguments(writer); 2122 return; 2123 } 2124 String areaId = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL; 2125 String sampleRate = PARAM_INJECT_EVENT_DEFAULT_RATE; 2126 String durationTime = PARAM_INJECT_EVENT_DEFAULT_DURATION; 2127 String propId = args[1]; 2128 String data = args[2]; 2129 // scan input 2130 for (int i = 3; i < args.length - 1; i++) { 2131 switch (args[i]) { 2132 case "-d": 2133 durationTime = args[++i]; 2134 break; 2135 case "-z" : 2136 areaId = args[++i]; 2137 break; 2138 case "-s" : 2139 sampleRate = args[++i]; 2140 break; 2141 default: 2142 writer.printf("%s is an invalid flag.\n", args[i]); 2143 showHelp(writer); 2144 return; 2145 } 2146 } 2147 try { 2148 float sampleRateFloat = Float.parseFloat(sampleRate); 2149 if (sampleRateFloat <= 0) { 2150 writer.printf("SampleRate: %s is an invalid value. " 2151 + "SampleRate must be greater than 0.\n", sampleRate); 2152 showHelp(writer); 2153 return; 2154 } 2155 mHal.injectContinuousVhalEvent(Integer.decode(propId), 2156 Integer.decode(areaId), data, 2157 sampleRateFloat, Long.parseLong(durationTime)); 2158 } catch (NumberFormatException e) { 2159 writer.printf("Invalid arguments: %s\n", e); 2160 showHelp(writer); 2161 } 2162 2163 } 2164 2165 // Set a target camera device for the rearview 2166 private void setRearviewCameraId(String[] args, IndentingPrintWriter writer) { 2167 if (args.length != 2) { 2168 showInvalidArguments(writer); 2169 return; 2170 } 2171 2172 if (!mCarEvsService.setRearviewCameraIdFromCommand(args[1])) { 2173 writer.println("Failed to set CarEvsService rearview camera device id."); 2174 } else { 2175 writer.printf("CarEvsService is set to use %s.\n", args[1]); 2176 } 2177 } 2178 2179 private void setDrivingSafetyRegion(String[] args, IndentingPrintWriter writer) { 2180 if (args.length != 1 && args.length != 2) { 2181 showInvalidArguments(writer); 2182 return; 2183 } 2184 String region = args.length == 2 ? args[1] : CarPackageManager.DRIVING_SAFETY_REGION_ALL; 2185 writer.println("Set driving safety region to:" + region); 2186 CarLocalServices.getService(CarPackageManagerService.class).resetDrivingSafetyRegion( 2187 region); 2188 } 2189 2190 private void getRearviewCameraId(IndentingPrintWriter writer) { 2191 writer.printf("CarEvsService is using %s for the rearview.\n", 2192 mCarEvsService.getRearviewCameraIdFromCommand()); 2193 } 2194 2195 private void controlWatchdogPackageKillableState(String[] args, IndentingPrintWriter writer) { 2196 if (args.length != 3) { 2197 showInvalidArguments(writer); 2198 return; 2199 } 2200 if (!args[1].equals("true") && !args[1].equals("false")) { 2201 writer.println("Failed to parse killable state argument. " 2202 + "Valid arguments: killable | not-killable"); 2203 return; 2204 } 2205 int currentUserId = ActivityManager.getCurrentUser(); 2206 mCarWatchdogService.setKillablePackageAsUser( 2207 args[2], UserHandle.of(currentUserId), args[1].equals("true")); 2208 writer.printf("Set package killable state as '%s' for user '%d' and package '%s'\n", 2209 args[1].equals("true") ? "killable" : "not killable", currentUserId, args[2]); 2210 } 2211 2212 // Set third-party foreground I/O threshold for car watchdog 2213 private void setWatchdogIoThirdPartyForegroundBytes(String[] args, 2214 IndentingPrintWriter writer) { 2215 if (args.length != 2) { 2216 showInvalidArguments(writer); 2217 return; 2218 } 2219 try { 2220 long newForegroundModeBytes = Long.parseLong(args[1]); 2221 ResourceOveruseConfiguration configuration = 2222 getThirdPartyResourceOveruseConfiguration( 2223 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 2224 if (configuration == null) { 2225 writer.println("Failed to get third-party resource overuse configurations."); 2226 return; 2227 } 2228 ResourceOveruseConfiguration newConfiguration = setComponentLevelForegroundIoBytes( 2229 configuration, newForegroundModeBytes); 2230 int result = mCarWatchdogService.setResourceOveruseConfigurations( 2231 Collections.singletonList(newConfiguration), 2232 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 2233 if (result == CarWatchdogManager.RETURN_CODE_SUCCESS) { 2234 writer.printf( 2235 "Successfully set third-party I/O overuse foreground threshold. { " 2236 + "foregroundModeBytes = %d } \n", 2237 newForegroundModeBytes); 2238 } else { 2239 writer.println("Failed to set third-party I/O overuse foreground threshold."); 2240 } 2241 } catch (NumberFormatException e) { 2242 writer.println("The argument provided does not contain a parsable long."); 2243 writer.println("Failed to set third-party I/O overuse foreground threshold."); 2244 } catch (RemoteException e) { 2245 writer.printf("Failed to set third-party I/O overuse foreground threshold: %s", 2246 e.getMessage()); 2247 } 2248 } 2249 2250 private void getWatchdogIoThirdPartyForegroundBytes(IndentingPrintWriter writer) { 2251 ResourceOveruseConfiguration configuration = 2252 getThirdPartyResourceOveruseConfiguration( 2253 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 2254 try { 2255 IoOveruseConfiguration ioOveruseConfiguration = Objects.requireNonNull( 2256 configuration).getIoOveruseConfiguration(); 2257 PerStateBytes componentLevelThresholds = Objects.requireNonNull(ioOveruseConfiguration) 2258 .getComponentLevelThresholds(); 2259 long foregroundBytes = Objects.requireNonNull( 2260 componentLevelThresholds).getForegroundModeBytes(); 2261 writer.printf("foregroundModeBytes = %d \n", foregroundBytes); 2262 } catch (NullPointerException e) { 2263 writer.println("Failed to get third-party I/O overuse foreground threshold."); 2264 } 2265 } 2266 2267 private ResourceOveruseConfiguration getThirdPartyResourceOveruseConfiguration( 2268 int resourceOveruseFlag) { 2269 for (ResourceOveruseConfiguration configuration : 2270 mCarWatchdogService.getResourceOveruseConfigurations(resourceOveruseFlag)) { 2271 if (configuration.getComponentType() 2272 == ResourceOveruseConfiguration.COMPONENT_TYPE_THIRD_PARTY) { 2273 return configuration; 2274 } 2275 } 2276 return null; 2277 } 2278 2279 private ResourceOveruseConfiguration setComponentLevelForegroundIoBytes( 2280 ResourceOveruseConfiguration configuration, long foregroundModeBytes) { 2281 IoOveruseConfiguration ioOveruseConfiguration = configuration.getIoOveruseConfiguration(); 2282 PerStateBytes componentLevelThresholds = 2283 ioOveruseConfiguration.getComponentLevelThresholds(); 2284 return constructResourceOveruseConfigurationBuilder( 2285 configuration).setIoOveruseConfiguration( 2286 new IoOveruseConfiguration.Builder( 2287 new PerStateBytes(foregroundModeBytes, 2288 componentLevelThresholds.getBackgroundModeBytes(), 2289 componentLevelThresholds.getGarageModeBytes()), 2290 ioOveruseConfiguration.getPackageSpecificThresholds(), 2291 ioOveruseConfiguration.getAppCategorySpecificThresholds(), 2292 ioOveruseConfiguration.getSystemWideThresholds()) 2293 .build()) 2294 .build(); 2295 } 2296 2297 private ResourceOveruseConfiguration.Builder constructResourceOveruseConfigurationBuilder( 2298 ResourceOveruseConfiguration configuration) { 2299 return new ResourceOveruseConfiguration.Builder(configuration.getComponentType(), 2300 configuration.getSafeToKillPackages(), 2301 configuration.getVendorPackagePrefixes(), 2302 configuration.getPackagesToAppCategoryTypes()) 2303 .setIoOveruseConfiguration(configuration.getIoOveruseConfiguration()); 2304 } 2305 2306 private void controlWatchdogProcessHealthCheck(String[] args, IndentingPrintWriter writer) { 2307 if (args.length != 2) { 2308 showInvalidArguments(writer); 2309 return; 2310 } 2311 if (!args[1].equals("enable") && !args[1].equals("disable")) { 2312 writer.println("Failed to parse argument. Valid arguments: enable | disable"); 2313 return; 2314 } 2315 mCarWatchdogService.controlProcessHealthCheck(args[1].equals("disable")); 2316 writer.printf("Watchdog health checking is now %sd \n", args[1]); 2317 } 2318 2319 // Check if the given property is global 2320 private static boolean isPropertyAreaTypeGlobal(@Nullable String property) { 2321 if (property == null) { 2322 return false; 2323 } 2324 return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL; 2325 } 2326 } 2327