1 /* 2 * Copyright (C) 2022 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_SETTINGS; 19 import static android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME; 20 import static android.car.Car.PERMISSION_CAR_POWER; 21 import static android.car.Car.PERMISSION_CONTROL_CAR_POWER_POLICY; 22 import static android.car.Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG; 23 import static android.car.Car.PERMISSION_USE_CAR_WATCHDOG; 24 import static android.car.VehicleAreaSeat.SEAT_UNKNOWN; 25 import static android.car.settings.CarSettings.Global.FORCED_DAY_NIGHT_MODE; 26 import static android.car.telemetry.CarTelemetryManager.STATUS_ADD_METRICS_CONFIG_SUCCEEDED; 27 import static android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue.ASSOCIATE_CURRENT_USER; 28 import static android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue.DISASSOCIATE_ALL_USERS; 29 import static android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue.DISASSOCIATE_CURRENT_USER; 30 import static android.hardware.automotive.vehicle.UserIdentificationAssociationType.CUSTOM_1; 31 import static android.hardware.automotive.vehicle.UserIdentificationAssociationType.CUSTOM_2; 32 import static android.hardware.automotive.vehicle.UserIdentificationAssociationType.CUSTOM_3; 33 import static android.hardware.automotive.vehicle.UserIdentificationAssociationType.CUSTOM_4; 34 import static android.hardware.automotive.vehicle.UserIdentificationAssociationType.KEY_FOB; 35 import static android.media.AudioManager.FLAG_SHOW_UI; 36 37 import static com.android.car.CarServiceUtils.toIntArray; 38 import static com.android.car.hal.property.HalPropertyDebugUtils.toAreaIdString; 39 import static com.android.car.hal.property.HalPropertyDebugUtils.toPropertyIdString; 40 import static com.android.car.hal.property.HalPropertyDebugUtils.toPropertyId; 41 import static com.android.car.power.PolicyReader.POWER_STATE_ON; 42 import static com.android.car.power.PolicyReader.POWER_STATE_WAIT_FOR_VHAL; 43 44 import android.annotation.NonNull; 45 import android.annotation.Nullable; 46 import android.annotation.UserIdInt; 47 import android.app.ActivityManager; 48 import android.app.ActivityOptions; 49 import android.app.UiModeManager; 50 import android.car.Car; 51 import android.car.CarOccupantZoneManager; 52 import android.car.CarVersion; 53 import android.car.SyncResultCallback; 54 import android.car.VehiclePropertyIds; 55 import android.car.builtin.content.pm.PackageManagerHelper; 56 import android.car.builtin.display.DisplayManagerHelper; 57 import android.car.builtin.input.InputManagerHelper; 58 import android.car.builtin.os.BuildHelper; 59 import android.car.builtin.os.UserManagerHelper; 60 import android.car.builtin.util.Slogf; 61 import android.car.builtin.widget.LockPatternHelper; 62 import android.car.content.pm.CarPackageManager; 63 import android.car.drivingstate.CarDrivingStateEvent; 64 import android.car.drivingstate.CarUxRestrictions; 65 import android.car.feature.Flags; 66 import android.car.hardware.power.CarPowerManager; 67 import android.car.hardware.power.CarPowerPolicy; 68 import android.car.input.CarInputManager; 69 import android.car.input.CustomInputEvent; 70 import android.car.input.RotaryEvent; 71 import android.car.media.IAudioZonesMirrorStatusCallback; 72 import android.car.telemetry.CarTelemetryManager; 73 import android.car.telemetry.TelemetryProto.TelemetryError; 74 import android.car.user.CarUserManager; 75 import android.car.user.UserCreationRequest; 76 import android.car.user.UserCreationResult; 77 import android.car.user.UserIdentificationAssociationResponse; 78 import android.car.user.UserRemovalRequest; 79 import android.car.user.UserRemovalResult; 80 import android.car.user.UserSwitchRequest; 81 import android.car.user.UserSwitchResult; 82 import android.car.util.concurrent.AsyncFuture; 83 import android.car.watchdog.CarWatchdogManager; 84 import android.car.watchdog.IoOveruseConfiguration; 85 import android.car.watchdog.PackageKillableState; 86 import android.car.watchdog.PerStateBytes; 87 import android.car.watchdog.ResourceOveruseConfiguration; 88 import android.content.ComponentName; 89 import android.content.Context; 90 import android.content.Intent; 91 import android.content.ServiceConnection; 92 import android.content.pm.PackageManager; 93 import android.hardware.automotive.vehicle.CreateUserRequest; 94 import android.hardware.automotive.vehicle.CreateUserStatus; 95 import android.hardware.automotive.vehicle.InitialUserInfoResponse; 96 import android.hardware.automotive.vehicle.InitialUserInfoResponseAction; 97 import android.hardware.automotive.vehicle.RemoveUserRequest; 98 import android.hardware.automotive.vehicle.SwitchUserMessageType; 99 import android.hardware.automotive.vehicle.SwitchUserRequest; 100 import android.hardware.automotive.vehicle.SwitchUserStatus; 101 import android.hardware.automotive.vehicle.UserIdentificationAssociation; 102 import android.hardware.automotive.vehicle.UserIdentificationAssociationValue; 103 import android.hardware.automotive.vehicle.UserIdentificationGetRequest; 104 import android.hardware.automotive.vehicle.UserIdentificationResponse; 105 import android.hardware.automotive.vehicle.UserIdentificationSetAssociation; 106 import android.hardware.automotive.vehicle.UserIdentificationSetRequest; 107 import android.hardware.automotive.vehicle.UserInfo; 108 import android.hardware.automotive.vehicle.UsersInfo; 109 import android.hardware.automotive.vehicle.VehicleArea; 110 import android.hardware.automotive.vehicle.VehicleDisplay; 111 import android.hardware.automotive.vehicle.VehicleGear; 112 import android.hardware.automotive.vehicle.VehiclePropError; 113 import android.hardware.display.DisplayManager; 114 import android.hardware.input.InputManager; 115 import android.os.Binder; 116 import android.os.FileUtils; 117 import android.os.IBinder; 118 import android.os.NewUserRequest; 119 import android.os.NewUserResponse; 120 import android.os.PersistableBundle; 121 import android.os.Process; 122 import android.os.RemoteException; 123 import android.os.ServiceSpecificException; 124 import android.os.SystemClock; 125 import android.os.UserHandle; 126 import android.os.UserManager; 127 import android.provider.Settings; 128 import android.text.TextUtils; 129 import android.util.ArrayMap; 130 import android.util.SparseArray; 131 import android.view.Display; 132 import android.view.InputDevice; 133 import android.view.KeyEvent; 134 import android.view.MotionEvent; 135 136 import com.android.car.am.FixedActivityService; 137 import com.android.car.audio.CarAudioService; 138 import com.android.car.evs.CarEvsService; 139 import com.android.car.garagemode.GarageModeService; 140 import com.android.car.hal.HalCallback; 141 import com.android.car.hal.HalPropConfig; 142 import com.android.car.hal.HalPropValue; 143 import com.android.car.hal.InputHalService; 144 import com.android.car.hal.PowerHalService; 145 import com.android.car.hal.UserHalHelper; 146 import com.android.car.hal.UserHalService; 147 import com.android.car.hal.VehicleHal; 148 import com.android.car.internal.util.DebugUtils; 149 import com.android.car.internal.util.IndentingPrintWriter; 150 import com.android.car.pm.CarPackageManagerService; 151 import com.android.car.power.CarPowerManagementService; 152 import com.android.car.systeminterface.SystemInterface; 153 import com.android.car.telemetry.CarTelemetryService; 154 import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutor; 155 import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorListener; 156 import com.android.car.telemetry.util.IoUtils; 157 import com.android.car.user.CarUserService; 158 import com.android.car.user.UserHandleHelper; 159 import com.android.car.watchdog.CarWatchdogService; 160 import com.android.internal.util.Preconditions; 161 import com.android.modules.utils.BasicShellCommandHandler; 162 163 import java.io.BufferedInputStream; 164 import java.io.ByteArrayOutputStream; 165 import java.io.File; 166 import java.io.FileInputStream; 167 import java.io.IOException; 168 import java.time.Duration; 169 import java.util.ArrayList; 170 import java.util.Arrays; 171 import java.util.Collections; 172 import java.util.List; 173 import java.util.Locale; 174 import java.util.Map; 175 import java.util.Objects; 176 import java.util.concurrent.CountDownLatch; 177 import java.util.concurrent.ExecutionException; 178 import java.util.concurrent.Executor; 179 import java.util.concurrent.Executors; 180 import java.util.concurrent.TimeUnit; 181 import java.util.concurrent.TimeoutException; 182 import java.util.concurrent.atomic.AtomicBoolean; 183 import java.util.concurrent.atomic.AtomicInteger; 184 import java.util.concurrent.atomic.AtomicLong; 185 186 final class CarShellCommand extends BasicShellCommandHandler { 187 188 private static final String NO_INITIAL_USER = "N/A"; 189 190 private static final String TAG = CarLog.tagFor(CarShellCommand.class); 191 private static final boolean VERBOSE = false; 192 193 // Same as android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS which is a hidden API. 194 private static final String CONTROL_DISPLAY_BRIGHTNESS = 195 "android.permission.CONTROL_DISPLAY_BRIGHTNESS"; 196 197 private static final String COMMAND_HELP = "-h"; 198 private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode"; 199 private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event"; 200 private static final String COMMAND_INJECT_ERROR_EVENT = "inject-error-event"; 201 private static final String COMMAND_INJECT_CONTINUOUS_EVENT = "inject-continuous-events"; 202 private static final String COMMAND_ENABLE_UXR = "enable-uxr"; 203 private static final String COMMAND_GARAGE_MODE = "garage-mode"; 204 private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities"; 205 private static final String COMMAND_GET_CARPROPERTYCONFIG = "get-carpropertyconfig"; 206 private static final String COMMAND_GET_PROPERTY_VALUE = "get-property-value"; 207 private static final String COMMAND_SET_PROPERTY_VALUE = "set-property-value"; 208 private static final String COMMAND_PROJECTION_AP_TETHERING = "projection-tethering"; 209 private static final String COMMAND_PROJECTION_AP_STABLE_CONFIG = 210 "projection-stable-lohs-config"; 211 private static final String COMMAND_PROJECTION_UI_MODE = "projection-ui-mode"; 212 private static final String COMMAND_RESUME = "resume"; 213 private static final String COMMAND_SUSPEND = "suspend"; 214 private static final String COMMAND_HIBERNATE = "hibernate"; 215 private static final String COMMAND_SET_DISPLAY_STATE = "set-display-state"; 216 private static final String COMMAND_SET_DISPLAY_BRIGHTNESS = "set-display-brightness"; 217 private static final String COMMAND_GET_DISPLAY_BRIGHTNESS = "get-display-brightness"; 218 private static final String PARAM_SIMULATE = "--simulate"; 219 private static final String PARAM_REAL = "--real"; 220 private static final String PARAM_AUTO = "--auto"; 221 private static final String PARAM_SKIP_GARAGEMODE = "--skip-garagemode"; 222 private static final String PARAM_REBOOT = "--reboot"; 223 private static final String PARAM_WAKEUP_AFTER = "--wakeup-after"; 224 private static final String PARAM_CANCEL_AFTER = "--cancel-after"; 225 private static final String PARAM_FREE_MEMORY = "--free-memory"; 226 private static final String COMMAND_SET_UID_TO_ZONE = "set-audio-zone-for-uid"; 227 private static final String COMMAND_RESET_VOLUME_CONTEXT = "reset-selected-volume-context"; 228 private static final String COMMAND_SET_MUTE_CAR_VOLUME_GROUP = "set-mute-car-volume-group"; 229 private static final String COMMAND_SET_GROUP_VOLUME = "set-group-volume"; 230 private static final String COMMAND_SET_AUDIO_MIRROR = "set-audio-mirror"; 231 private static final String COMMAND_UNSET_AUDIO_MIRROR = "unset-audio-mirror"; 232 private static final String COMMAND_START_FIXED_ACTIVITY_MODE = "start-fixed-activity-mode"; 233 private static final String COMMAND_STOP_FIXED_ACTIVITY_MODE = "stop-fixed-activity-mode"; 234 private static final String COMMAND_ENABLE_FEATURE = "enable-feature"; 235 private static final String COMMAND_DISABLE_FEATURE = "disable-feature"; 236 private static final String COMMAND_INJECT_KEY = "inject-key"; 237 private static final String COMMAND_INJECT_MOTION = "inject-motion"; 238 private static final String COMMAND_INJECT_ROTARY = "inject-rotary"; 239 private static final String COMMAND_INJECT_CUSTOM_INPUT = "inject-custom-input"; 240 private static final String COMMAND_CHECK_LOCK_IS_SECURE = "check-lock-is-secure"; 241 private static final String COMMAND_CHECK_FAKE_VHAL = "check-fake-vhal"; 242 private static final String COMMAND_GET_INITIAL_USER_INFO = "get-initial-user-info"; 243 private static final String COMMAND_SWITCH_USER = "switch-user"; 244 private static final String COMMAND_LOGOUT_USER = "logout-user"; 245 private static final String COMMAND_REMOVE_USER = "remove-user"; 246 private static final String COMMAND_CREATE_USER = "create-user"; 247 private static final String COMMAND_GET_INITIAL_USER = "get-initial-user"; 248 private static final String COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE = 249 "set-occupant-zone-for-user"; 250 private static final String COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE = 251 "reset-user-in-occupant-zone"; 252 private static final String COMMAND_GET_USER_AUTH_ASSOCIATION = 253 "get-user-auth-association"; 254 private static final String COMMAND_SET_USER_AUTH_ASSOCIATION = 255 "set-user-auth-association"; 256 private static final String COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE = 257 "set-start-bg-users-on-garage-mode"; 258 private static final String COMMAND_DEFINE_POWER_POLICY = "define-power-policy"; 259 private static final String COMMAND_APPLY_POWER_POLICY = "apply-power-policy"; 260 private static final String COMMAND_DEFINE_POWER_POLICY_GROUP = "define-power-policy-group"; 261 private static final String COMMAND_SET_POWER_POLICY_GROUP = "set-power-policy-group"; 262 private static final String COMMAND_GET_CURRENT_POWER_POLICY = "get-current-power-policy"; 263 private static final String COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY = 264 "apply-cts-verifier-power-off-policy"; 265 private static final String COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY = 266 "apply-cts-verifier-power-on-policy"; 267 private static final String COMMAND_POWER_OFF = "power-off"; 268 private static final String COMMAND_SILENT_MODE = "silent-mode"; 269 // Used with COMMAND_SILENT_MODE for forced silent: "forced-silent" 270 private static final String SILENT_MODE_FORCED_SILENT = 271 CarPowerManagementService.SILENT_MODE_FORCED_SILENT; 272 // Used with COMMAND_SILENT_MODE for forced non silent: "forced-non-silent" 273 private static final String SILENT_MODE_FORCED_NON_SILENT = 274 CarPowerManagementService.SILENT_MODE_FORCED_NON_SILENT; 275 // Used with COMMAND_SILENT_MODE for non forced silent mode: "non-forced-silent-mode" 276 private static final String SILENT_MODE_NON_FORCED = 277 CarPowerManagementService.SILENT_MODE_NON_FORCED; 278 279 private static final String COMMAND_EMULATE_DRIVING_STATE = "emulate-driving-state"; 280 private static final String DRIVING_STATE_DRIVE = "drive"; 281 private static final String DRIVING_STATE_PARK = "park"; 282 private static final String DRIVING_STATE_REVERSE = "reverse"; 283 private static final String DRIVING_STATE_NEUTRAL = "neutral"; 284 private static final String COMMAND_GET_DRIVING_STATE = "get-driving-state"; 285 private static final String COMMAND_SET_REARVIEW_CAMERA_ID = "set-rearview-camera-id"; 286 private static final String COMMAND_GET_REARVIEW_CAMERA_ID = "get-rearview-camera-id"; 287 private static final String COMMAND_SET_CAMERA_ID = "set-camera-id"; 288 private static final String COMMAND_GET_CAMERA_ID = "get-camera-id"; 289 private static final String COMMAND_ENABLE_CAMERA_SERVICE_TYPE = "enable-camera-service-type"; 290 private static final String COMMAND_CHECK_CAMERA_SERVICE_TYPE_ENABLED = 291 "check-camera-service-type-enabled"; 292 293 private static final String COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE = 294 "watchdog-control-package-killable-state"; 295 private static final String COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES = 296 "watchdog-io-set-3p-foreground-bytes"; 297 private static final String COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES = 298 "watchdog-io-get-3p-foreground-bytes"; 299 private static final String COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK = 300 "watchdog-control-health-check"; 301 private static final String COMMAND_WATCHDOG_RESOURCE_OVERUSE_KILL = 302 "watchdog-resource-overuse-kill"; 303 private static final String COMMAND_WATCHDOG_INJECT_POWER_STATE = "watchdog-inject-power-state"; 304 305 private static final String COMMAND_DRIVING_SAFETY_SET_REGION = 306 "set-drivingsafety-region"; 307 308 private static final String COMMAND_TELEMETRY = "telemetry"; 309 private static final String COMMAND_CONTROL_COMPONENT_ENABLED_STATE = 310 "control-component-enabled-state"; 311 312 private static final String COMMAND_LIST_VHAL_PROPS = "list-vhal-props"; 313 private static final String COMMAND_GET_VHAL_BACKEND = "get-vhal-backend"; 314 315 private static final String COMMAND_TEST_ECHO_REVERSE_BYTES = "test-echo-reverse-bytes"; 316 317 private static final String COMMAND_GET_TARGET_CAR_VERSION = "get-target-car-version"; 318 319 private static final String COMMAND_SET_PROCESS_GROUP = "set-process-group"; 320 private static final String COMMAND_GET_PROCESS_GROUP = "get-process-group"; 321 private static final String COMMAND_SET_PROCESS_PROFILE = "set-process-profile"; 322 323 private static final String COMMAND_GET_DISPLAY_BY_USER = "get-display-by-user"; 324 private static final String COMMAND_GET_USER_BY_DISPLAY = "get-user-by-display"; 325 private static final String COMMAND_ASSIGN_EXTRA_DISPLAY = "assign-extra-display"; 326 private static final String COMMAND_UNASSIGN_EXTRA_DISPLAY = "unassign-extra-display"; 327 private static final String COMMAND_GENERATE_TEST_VENDOR_CONFIGS = "gen-test-vendor-configs"; 328 private static final String COMMAND_RESTORE_TEST_VENDOR_CONFIGS = "restore-vendor-configs"; 329 330 331 private static final String COMMAND_GET_CURRENT_UX_RESTRICTIONS = "get-current-ux-restrictions"; 332 private static final String COMMAND_SET_CURRENT_UXR_MODE = "set-current-uxr-mode"; 333 private static final String COMMAND_GET_CURRENT_UXR_MODE = "get-current-uxr-mode"; 334 private static final String COMMAND_GET_SUPPORTED_UXR_MODES = "get-supported-uxr-modes"; 335 private static final String COMMAND_GET_UXR_CONFIG = "get-uxr-config"; 336 private static final String COMMAND_GET_INPUT_AND_DISPLAY_INFO = "get-input-and-display-info"; 337 private static final String COMMAND_ADD_INPUT_DESCRIPTOR_ASSOCIATION_TO_DISPLAY_UNIQUE_ID = 338 "add-input-descriptor-association-to-display-unique-id"; 339 private static final String COMMAND_REMOVE_INPUT_DESCRIPTOR_ASSOCIATION = 340 "remove-input-descriptor-association"; 341 342 private static final String[] CREATE_OR_MANAGE_USERS_PERMISSIONS = new String[] { 343 android.Manifest.permission.CREATE_USERS, 344 android.Manifest.permission.MANAGE_USERS 345 }; 346 347 private static final String[] CREATE_OR_MANAGE_OR_QUERY_USERS_PERMISSIONS = new String[] { 348 android.Manifest.permission.CREATE_USERS, 349 android.Manifest.permission.MANAGE_USERS, 350 android.Manifest.permission.QUERY_USERS 351 }; 352 353 // List of commands allowed in user build. All these command should be protected with 354 // a permission. K: command, V: required permissions (must have at least 1). 355 // Only commands with permission already granted to shell user should be allowed. 356 // Commands that can affect safety should be never allowed in user build. 357 // 358 // This map is looked up first, then USER_BUILD_COMMAND_TO_PERMISSION_MAP 359 private static final ArrayMap<String, String[]> USER_BUILD_COMMAND_TO_PERMISSIONS_MAP; 360 static { 361 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP = new ArrayMap<>(8); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_INITIAL_USER_INFO, CREATE_OR_MANAGE_USERS_PERMISSIONS)362 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_INITIAL_USER_INFO, 363 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SWITCH_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)364 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SWITCH_USER, 365 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_LOGOUT_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)366 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_LOGOUT_USER, 367 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_REMOVE_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)368 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_REMOVE_USER, 369 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_CREATE_USER, CREATE_OR_MANAGE_USERS_PERMISSIONS)370 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_CREATE_USER, 371 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_AUTH_ASSOCIATION, CREATE_OR_MANAGE_USERS_PERMISSIONS)372 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_AUTH_ASSOCIATION, 373 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_USER_AUTH_ASSOCIATION, CREATE_OR_MANAGE_USERS_PERMISSIONS)374 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_USER_AUTH_ASSOCIATION, 375 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)376 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE, 377 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_DISPLAY_BY_USER, CREATE_OR_MANAGE_OR_QUERY_USERS_PERMISSIONS)378 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_DISPLAY_BY_USER, 379 CREATE_OR_MANAGE_OR_QUERY_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_BY_DISPLAY, CREATE_OR_MANAGE_OR_QUERY_USERS_PERMISSIONS)380 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_GET_USER_BY_DISPLAY, 381 CREATE_OR_MANAGE_OR_QUERY_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_ASSIGN_EXTRA_DISPLAY, CREATE_OR_MANAGE_USERS_PERMISSIONS)382 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_ASSIGN_EXTRA_DISPLAY, 383 CREATE_OR_MANAGE_USERS_PERMISSIONS); USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_UNASSIGN_EXTRA_DISPLAY, CREATE_OR_MANAGE_USERS_PERMISSIONS)384 USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.put(COMMAND_UNASSIGN_EXTRA_DISPLAY, 385 CREATE_OR_MANAGE_USERS_PERMISSIONS); 386 } 387 388 // List of commands allowed in user build. All these command should be protected with 389 // a permission. K: command, V: required permission. 390 // Only commands with permission already granted to shell user should be allowed. 391 // Commands that can affect safety should be never allowed in user build. 392 private static final ArrayMap<String, String> USER_BUILD_COMMAND_TO_PERMISSION_MAP; 393 static { 394 USER_BUILD_COMMAND_TO_PERMISSION_MAP = new ArrayMap<>(27); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GARAGE_MODE, PERMISSION_CAR_POWER)395 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GARAGE_MODE, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESUME, PERMISSION_CAR_POWER)396 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESUME, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SUSPEND, PERMISSION_CAR_POWER)397 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SUSPEND, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_HIBERNATE, PERMISSION_CAR_POWER)398 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_HIBERNATE, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_DISPLAY_STATE, PERMISSION_CAR_POWER)399 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_DISPLAY_STATE, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_DISPLAY_BRIGHTNESS, CONTROL_DISPLAY_BRIGHTNESS)400 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_DISPLAY_BRIGHTNESS, 401 CONTROL_DISPLAY_BRIGHTNESS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_DISPLAY_BRIGHTNESS, CONTROL_DISPLAY_BRIGHTNESS)402 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_DISPLAY_BRIGHTNESS, 403 CONTROL_DISPLAY_BRIGHTNESS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_POWER_OFF, PERMISSION_CAR_POWER)404 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_POWER_OFF, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY, PERMISSION_CAR_POWER)405 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_POWER_POLICY, PERMISSION_CONTROL_CAR_POWER_POLICY)406 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_POWER_POLICY, 407 PERMISSION_CONTROL_CAR_POWER_POLICY); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY_GROUP, PERMISSION_CAR_POWER)408 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DEFINE_POWER_POLICY_GROUP, 409 PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_POWER_POLICY_GROUP, PERMISSION_CONTROL_CAR_POWER_POLICY)410 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_POWER_POLICY_GROUP, 411 PERMISSION_CONTROL_CAR_POWER_POLICY); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, PERMISSION_CONTROL_CAR_POWER_POLICY)412 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, 413 PERMISSION_CONTROL_CAR_POWER_POLICY); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, PERMISSION_CONTROL_CAR_POWER_POLICY)414 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, 415 PERMISSION_CONTROL_CAR_POWER_POLICY); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SILENT_MODE, PERMISSION_CAR_POWER)416 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SILENT_MODE, PERMISSION_CAR_POWER); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_INITIAL_USER, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)417 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_INITIAL_USER, 418 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)419 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_DAY_NIGHT_MODE, 420 android.Manifest.permission.MODIFY_DAY_NIGHT_MODE); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESET_VOLUME_CONTEXT, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)421 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_RESET_VOLUME_CONTEXT, 422 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_MUTE_CAR_VOLUME_GROUP, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)423 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_MUTE_CAR_VOLUME_GROUP, 424 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_GROUP_VOLUME, PERMISSION_CAR_CONTROL_AUDIO_VOLUME)425 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_GROUP_VOLUME, 426 PERMISSION_CAR_CONTROL_AUDIO_VOLUME); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_AUDIO_MIRROR, PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)427 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_SET_AUDIO_MIRROR, 428 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_UNSET_AUDIO_MIRROR, PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)429 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_UNSET_AUDIO_MIRROR, 430 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_KEY, android.Manifest.permission.INJECT_EVENTS)431 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_KEY, 432 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_MOTION, android.Manifest.permission.INJECT_EVENTS)433 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_MOTION, 434 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_ROTARY, android.Manifest.permission.INJECT_EVENTS)435 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_INJECT_ROTARY, 436 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)437 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE, 438 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)439 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES, 440 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES, PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG)441 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES, 442 PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK, PERMISSION_USE_CAR_WATCHDOG)443 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK, 444 PERMISSION_USE_CAR_WATCHDOG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_RESOURCE_OVERUSE_KILL, PERMISSION_USE_CAR_WATCHDOG)445 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_RESOURCE_OVERUSE_KILL, 446 PERMISSION_USE_CAR_WATCHDOG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_INJECT_POWER_STATE, PERMISSION_USE_CAR_WATCHDOG)447 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_INJECT_POWER_STATE, 448 PERMISSION_USE_CAR_WATCHDOG); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_CONTROL_COMPONENT_ENABLED_STATE, android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE)449 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_CONTROL_COMPONENT_ENABLED_STATE, 450 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); 451 // borrow the permission to pass assertHasAtLeastOnePermission() for a user build USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_CHECK_LOCK_IS_SECURE, android.Manifest.permission.INJECT_EVENTS)452 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_CHECK_LOCK_IS_SECURE, 453 android.Manifest.permission.INJECT_EVENTS); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_TEST_ECHO_REVERSE_BYTES, android.car.Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL)454 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_TEST_ECHO_REVERSE_BYTES, 455 android.car.Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL); USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_TARGET_CAR_VERSION, android.Manifest.permission.QUERY_ALL_PACKAGES)456 USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_GET_TARGET_CAR_VERSION, 457 android.Manifest.permission.QUERY_ALL_PACKAGES); 458 } 459 460 private static final String PARAM_DAY_MODE = "day"; 461 private static final String PARAM_NIGHT_MODE = "night"; 462 private static final String PARAM_SENSOR_MODE = "sensor"; 463 private static final String PARAM_VEHICLE_PROPERTY_GLOBAL_AREA_ID = "0"; 464 private static final String PARAM_INJECT_EVENT_DEFAULT_RATE = "10"; 465 private static final String PARAM_INJECT_EVENT_DEFAULT_DURATION = "60"; 466 private static final String PARAM_ALL_PROPERTIES_OR_AREA_IDS = "-1"; 467 private static final String PARAM_ON_MODE = "on"; 468 private static final String PARAM_OFF_MODE = "off"; 469 private static final String PARAM_QUERY_MODE = "query"; 470 private static final String PARAM_REBOOT_AFTER_GARAGEMODE = "reboot"; 471 private static final String PARAM_MUTE = "mute"; 472 private static final String PARAM_UNMUTE = "unmute"; 473 474 475 private static final int RESULT_OK = 0; 476 private static final int RESULT_ERROR = -1; // Arbitrary value, any non-0 is fine 477 478 private static final int DEFAULT_HAL_TIMEOUT_MS = 1_000; 479 480 private static final int DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS = 60_000; 481 482 private static final int INVALID_USER_AUTH_TYPE_OR_VALUE = -1; 483 484 private static final SparseArray<String> VALID_USER_AUTH_TYPES; 485 private static final String VALID_USER_AUTH_TYPES_HELP; 486 487 private static final SparseArray<String> VALID_USER_AUTH_SET_VALUES; 488 private static final String VALID_USER_AUTH_SET_VALUES_HELP; 489 490 private static final ArrayMap<String, Integer> CUSTOM_INPUT_FUNCTION_ARGS; 491 492 private static final int DEFAULT_DEVICE_ID = 0; 493 private static final float DEFAULT_PRESSURE = 1.0f; 494 private static final float NO_PRESSURE = 0.0f; 495 private static final float DEFAULT_SIZE = 1.0f; 496 private static final int DEFAULT_META_STATE = 0; 497 private static final float DEFAULT_PRECISION_X = 1.0f; 498 private static final float DEFAULT_PRECISION_Y = 1.0f; 499 private static final int DEFAULT_EDGE_FLAGS = 0; 500 private static final int DEFAULT_BUTTON_STATE = 0; 501 private static final int DEFAULT_FLAGS = 0; 502 503 private static final ArrayMap<String, Integer> MOTION_EVENT_SOURCES; 504 505 static { 506 VALID_USER_AUTH_TYPES = new SparseArray<>(5); VALID_USER_AUTH_TYPES.put(KEY_FOB, "KEY_FOB")507 VALID_USER_AUTH_TYPES.put(KEY_FOB, "KEY_FOB"); VALID_USER_AUTH_TYPES.put(CUSTOM_1, "CUSTOM_1")508 VALID_USER_AUTH_TYPES.put(CUSTOM_1, "CUSTOM_1"); VALID_USER_AUTH_TYPES.put(CUSTOM_2, "CUSTOM_2")509 VALID_USER_AUTH_TYPES.put(CUSTOM_2, "CUSTOM_2"); VALID_USER_AUTH_TYPES.put(CUSTOM_3, "CUSTOM_3")510 VALID_USER_AUTH_TYPES.put(CUSTOM_3, "CUSTOM_3"); VALID_USER_AUTH_TYPES.put(CUSTOM_4, "CUSTOM_4")511 VALID_USER_AUTH_TYPES.put(CUSTOM_4, "CUSTOM_4"); 512 VALID_USER_AUTH_TYPES_HELP = getHelpString("types", VALID_USER_AUTH_TYPES); 513 514 VALID_USER_AUTH_SET_VALUES = new SparseArray<>(3); VALID_USER_AUTH_SET_VALUES.put(ASSOCIATE_CURRENT_USER, "ASSOCIATE_CURRENT_USER")515 VALID_USER_AUTH_SET_VALUES.put(ASSOCIATE_CURRENT_USER, "ASSOCIATE_CURRENT_USER"); VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_CURRENT_USER, "DISASSOCIATE_CURRENT_USER")516 VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_CURRENT_USER, "DISASSOCIATE_CURRENT_USER"); VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_ALL_USERS, "DISASSOCIATE_ALL_USERS")517 VALID_USER_AUTH_SET_VALUES.put(DISASSOCIATE_ALL_USERS, "DISASSOCIATE_ALL_USERS"); 518 VALID_USER_AUTH_SET_VALUES_HELP = getHelpString("values", VALID_USER_AUTH_SET_VALUES); 519 520 CUSTOM_INPUT_FUNCTION_ARGS = new ArrayMap<>(10); 521 CUSTOM_INPUT_FUNCTION_ARGS.put("f1", CustomInputEvent.INPUT_CODE_F1); 522 CUSTOM_INPUT_FUNCTION_ARGS.put("f2", CustomInputEvent.INPUT_CODE_F2); 523 CUSTOM_INPUT_FUNCTION_ARGS.put("f3", CustomInputEvent.INPUT_CODE_F3); 524 CUSTOM_INPUT_FUNCTION_ARGS.put("f4", CustomInputEvent.INPUT_CODE_F4); 525 CUSTOM_INPUT_FUNCTION_ARGS.put("f5", CustomInputEvent.INPUT_CODE_F5); 526 CUSTOM_INPUT_FUNCTION_ARGS.put("f6", CustomInputEvent.INPUT_CODE_F6); 527 CUSTOM_INPUT_FUNCTION_ARGS.put("f7", CustomInputEvent.INPUT_CODE_F7); 528 CUSTOM_INPUT_FUNCTION_ARGS.put("f8", CustomInputEvent.INPUT_CODE_F8); 529 CUSTOM_INPUT_FUNCTION_ARGS.put("f9", CustomInputEvent.INPUT_CODE_F9); 530 CUSTOM_INPUT_FUNCTION_ARGS.put("f10", CustomInputEvent.INPUT_CODE_F10); 531 532 MOTION_EVENT_SOURCES = new ArrayMap<>(10); 533 MOTION_EVENT_SOURCES.put("keyboard", InputDevice.SOURCE_KEYBOARD); 534 MOTION_EVENT_SOURCES.put("dpad", InputDevice.SOURCE_DPAD); 535 MOTION_EVENT_SOURCES.put("gamepad", InputDevice.SOURCE_GAMEPAD); 536 MOTION_EVENT_SOURCES.put("touchscreen", InputDevice.SOURCE_TOUCHSCREEN); 537 MOTION_EVENT_SOURCES.put("mouse", InputDevice.SOURCE_MOUSE); 538 MOTION_EVENT_SOURCES.put("stylus", InputDevice.SOURCE_STYLUS); 539 MOTION_EVENT_SOURCES.put("trackball", InputDevice.SOURCE_TRACKBALL); 540 MOTION_EVENT_SOURCES.put("touchpad", InputDevice.SOURCE_TOUCHPAD); 541 MOTION_EVENT_SOURCES.put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION); 542 MOTION_EVENT_SOURCES.put("joystick", InputDevice.SOURCE_JOYSTICK); 543 } 544 545 // CarTelemetryManager may not send result back if there are not results for the given 546 // metrics config. 547 private static final Duration TELEMETRY_RESULT_WAIT_TIMEOUT = Duration.ofSeconds(5); 548 getHelpString(String name, SparseArray<String> values)549 private static String getHelpString(String name, SparseArray<String> values) { 550 StringBuilder help = new StringBuilder("Valid ").append(name).append(" are: "); 551 int size = values.size(); 552 for (int i = 0; i < size; i++) { 553 help.append(values.valueAt(i)); 554 if (i != size - 1) { 555 help.append(", "); 556 } 557 } 558 return help.append('.').toString(); 559 } 560 561 private final Context mContext; 562 private final VehicleHal mHal; 563 private final CarAudioService mCarAudioService; 564 private final CarPackageManagerService mCarPackageManagerService; 565 private final CarProjectionService mCarProjectionService; 566 private final CarPowerManagementService mCarPowerManagementService; 567 private final FixedActivityService mFixedActivityService; 568 private final CarFeatureController mFeatureController; 569 private final CarInputService mCarInputService; 570 private final CarNightService mCarNightService; 571 private final SystemInterface mSystemInterface; 572 private final GarageModeService mGarageModeService; 573 private final CarUserService mCarUserService; 574 private final CarOccupantZoneService mCarOccupantZoneService; 575 private final CarEvsService mCarEvsService; 576 private final CarWatchdogService mCarWatchdogService; 577 private final CarTelemetryService mCarTelemetryService; 578 private final CarUxRestrictionsManagerService mCarUxRestrictionsManagerService; 579 private final Map<Class, CarSystemService> mAllServicesByClazz; 580 private long mKeyDownTime; 581 private long mMotionDownTime; 582 private ServiceConnection mScriptExecutorConn; 583 private IScriptExecutor mScriptExecutor; 584 private AudioZoneMirrorStatusCallbackImpl mMirrorStatusCallback; 585 CarShellCommand(Context context, VehicleHal hal, CarFeatureController featureController, SystemInterface systemInterface, Map<Class, CarSystemService> allServicesByClazz)586 CarShellCommand(Context context, VehicleHal hal, CarFeatureController featureController, 587 SystemInterface systemInterface, Map<Class, CarSystemService> allServicesByClazz) { 588 mContext = context; 589 mHal = hal; 590 mFeatureController = featureController; 591 mSystemInterface = systemInterface; 592 mCarAudioService = (CarAudioService) allServicesByClazz.get(CarAudioService.class); 593 mCarPackageManagerService = (CarPackageManagerService) allServicesByClazz.get( 594 CarPackageManagerService.class); 595 mCarProjectionService = (CarProjectionService) allServicesByClazz.get( 596 CarProjectionService.class); 597 mCarPowerManagementService = (CarPowerManagementService) allServicesByClazz.get( 598 CarPowerManagementService.class); 599 mFixedActivityService = (FixedActivityService) allServicesByClazz.get( 600 FixedActivityService.class); 601 mCarInputService = (CarInputService) allServicesByClazz.get(CarInputService.class); 602 mCarNightService = (CarNightService) allServicesByClazz.get(CarNightService.class); 603 mGarageModeService = (GarageModeService) allServicesByClazz.get(GarageModeService.class); 604 mCarUserService = (CarUserService) allServicesByClazz.get(CarUserService.class); 605 mCarOccupantZoneService = (CarOccupantZoneService) 606 allServicesByClazz.get(CarOccupantZoneService.class); 607 mCarEvsService = (CarEvsService) allServicesByClazz.get(CarEvsService.class); 608 mCarWatchdogService = (CarWatchdogService) allServicesByClazz.get(CarWatchdogService.class); 609 mCarTelemetryService = (CarTelemetryService) 610 allServicesByClazz.get(CarTelemetryService.class); 611 mCarUxRestrictionsManagerService = (CarUxRestrictionsManagerService) 612 allServicesByClazz.get(CarUxRestrictionsManagerService.class); 613 mAllServicesByClazz = allServicesByClazz; 614 } 615 616 @Override onCommand(String cmd)617 public int onCommand(String cmd) { 618 if (cmd == null) { 619 onHelp(); 620 return RESULT_ERROR; 621 } 622 ArrayList<String> argsList = new ArrayList<>(); 623 argsList.add(cmd); 624 String arg = null; 625 do { 626 arg = getNextArg(); 627 if (arg != null) { 628 argsList.add(arg); 629 } 630 } while (arg != null); 631 String[] args = new String[argsList.size()]; 632 argsList.toArray(args); 633 try (IndentingPrintWriter pw = new IndentingPrintWriter(getOutPrintWriter())) { 634 return exec(args, pw); 635 } 636 } 637 638 @Override onHelp()639 public void onHelp() { 640 try (IndentingPrintWriter pw = new IndentingPrintWriter(getOutPrintWriter())) { 641 showHelp(pw); 642 } 643 } 644 showHelp(IndentingPrintWriter pw)645 private static void showHelp(IndentingPrintWriter pw) { 646 pw.println("Car service commands:"); 647 pw.println("\t-h"); 648 pw.println("\t Print this help text."); 649 pw.println("\tday-night-mode [day|night|sensor]"); 650 pw.println("\t Force into day/night mode or restore to auto."); 651 pw.println("\tinject-vhal-event <property name in SCREAMING_SNAKE_CASE or ID in Hex or " 652 + "Decimal> [area ID] data(can be comma separated list) [-t delay_time_seconds]"); 653 pw.println("\t Inject a vehicle property for testing."); 654 pw.println("\t delay_time_seconds: the event timestamp is increased by certain second."); 655 pw.println("\t If not specified, it will be 0."); 656 pw.println("\tinject-error-event <PROPERTY_ID in Hex or Decimal> zone <errorCode>"); 657 pw.println("\t Inject an error event from VHAL for testing."); 658 pw.println("\tinject-continuous-events <PROPERTY_ID in Hex or Decimal> " 659 + "data(can be comma separated list) " 660 + "[-z zone] [-s SampleRate in Hz] [-d time duration in seconds]"); 661 pw.println("\t Inject continuous vehicle events for testing."); 662 pw.printf("\t If not specified, CarService will inject fake events with areaId:%s " 663 + "at sample rate %s for %s seconds.", 664 PARAM_VEHICLE_PROPERTY_GLOBAL_AREA_ID, 665 PARAM_INJECT_EVENT_DEFAULT_RATE, PARAM_INJECT_EVENT_DEFAULT_DURATION); 666 pw.println("\tenable-uxr true|false"); 667 pw.println("\t Enable/Disable UX restrictions and App blocking."); 668 pw.println("\tgarage-mode [on|off|query|reboot]"); 669 pw.println("\t Force into or out of garage mode, or check status."); 670 pw.println("\t With 'reboot', enter garage mode, then reboot when it completes."); 671 pw.println("\tget-do-activities pkgname"); 672 pw.println("\t Get Distraction Optimized activities in given package."); 673 pw.println("\tget-carpropertyconfig [property name in SCREAMING_SNAKE_CASE or ID in Hex or" 674 + " Decimal]"); 675 pw.println("\t Get a specific CarPropertyConfig or list all CarPropertyConfigs"); 676 pw.println("\tget-property-value [property name in SCREAMING_SNAKE_CASE or ID in Hex or " 677 + "Decimal] [areaId]"); 678 pw.println("\t Get a vehicle property value by property id and areaId"); 679 pw.println("\t or list all property values for all areaId"); 680 pw.printf("\t%s\n", getSetPropertyValueUsage()); 681 pw.printf("\t%s\n", getSuspendCommandUsage(COMMAND_SUSPEND)); 682 pw.println("\t Suspend the system to RAM."); 683 pw.printf("\t %s forces the device to perform suspend-to-RAM.\n", PARAM_REAL); 684 pw.printf("\t %s simulates suspend-to-RAM instead of putting the device into deep sleep." 685 + "\n", PARAM_SIMULATE); 686 pw.printf("\t %s depending on the device capability, real or simulated suspend-to-RAM is " 687 + "performed.\n", PARAM_AUTO); 688 pw.printf("\t %s skips Garage Mode before going into sleep.\n", PARAM_SKIP_GARAGEMODE); 689 pw.printf("\t %s [RESUME_DELAY] wakes up the device RESUME_DELAY seconds after suspend.\n", 690 PARAM_WAKEUP_AFTER); 691 pw.printf("\t %s [RESUME_DELAY] cancels the wake up after RESUME_DELAY seconds, if this" 692 + " flag is set, device will not go into suspend mode and wait in shutdown" 693 + " prepare for RESUME_DELAY seconds.\n", 694 PARAM_CANCEL_AFTER); 695 pw.printf("\t%s\n", getSuspendCommandUsage(COMMAND_HIBERNATE)); 696 pw.println("\t Suspend the system to disk."); 697 pw.printf("\t %s forces the device to perform suspend-to-disk.\n", PARAM_REAL); 698 pw.printf("\t %s simulates suspend-to-disk instead of putting the device into " 699 + "hibernation.\n", PARAM_SIMULATE); 700 pw.printf("\t %s depending on the device capability, real or simulated suspend-to-disk is " 701 + "performed.\n", PARAM_AUTO); 702 pw.printf("\t %s skips Garage Mode before going into hibernation.\n", 703 PARAM_SKIP_GARAGEMODE); 704 pw.printf("\t %s frees cached apps memory before simulating hibernation.\n", 705 PARAM_FREE_MEMORY); 706 pw.println("\tresume"); 707 pw.println("\t Wake the system up after a simulated suspension/hibernation."); 708 pw.println("\tset-display-state [displayId] [true|false]"); 709 pw.println("\tset-display-brightness [displayId] [brightness_at_0_to_1_scale]"); 710 pw.println("\tget-display-brightness [displayId]"); 711 pw.println("\t Turn on or off the individual display."); 712 pw.println("\tprojection-tethering [true|false]"); 713 pw.println("\t Whether tethering should be used when creating access point for" 714 + " wireless projection"); 715 pw.println("\t--metrics"); 716 pw.println("\t When used with dumpsys, only metrics will be in the dumpsys output."); 717 pw.printf("\t%s [zoneid] [uid]\n", COMMAND_SET_UID_TO_ZONE); 718 pw.println("\t Maps the audio zoneid to uid."); 719 pw.printf("\t%s\n", COMMAND_RESET_VOLUME_CONTEXT); 720 pw.println("\t Resets the last selected volume context for volume changes."); 721 pw.printf("\t%s [zoneId] [groupId] [%s\\%s]\n", COMMAND_SET_MUTE_CAR_VOLUME_GROUP, 722 PARAM_MUTE, PARAM_UNMUTE); 723 pw.printf("\t %s\\%s groupId in zoneId\n", PARAM_MUTE, PARAM_UNMUTE); 724 pw.printf("\t%s [zoneId] [groupId] [volume]\n", COMMAND_SET_GROUP_VOLUME); 725 pw.println("\t sets the group volume for [groupId] in [zoneId] to %volume,"); 726 pw.println("\t [volume] must be an integer between 0 to 100"); 727 pw.printf("\t%s [zoneId1] [zoneId2]\n", COMMAND_SET_AUDIO_MIRROR); 728 pw.println("\t sets audio mirror for zones [zoneId1] and [zoneId2],"); 729 pw.println("\t [zoneId#] must be a valid zone id "); 730 pw.printf("\t%s [value] [--requestId]\n", COMMAND_UNSET_AUDIO_MIRROR); 731 pw.println("\t unsets audio mirror for zone [value],"); 732 pw.println("\t [value] must be a valid zone id"); 733 pw.println("\t use --requestId to disable a request id instead"); 734 pw.println("\tstart-fixed-activity displayId packageName activityName"); 735 pw.println("\t Start an Activity the specified display as fixed mode"); 736 pw.println("\tstop-fixed-mode displayId"); 737 pw.println("\t Stop fixed Activity mode for the given display. " 738 + "The Activity will not be restarted upon crash."); 739 pw.println("\tenable-feature featureName"); 740 pw.println("\t Enable the requested feature. Change will happen after reboot."); 741 pw.println("\t This requires root/su."); 742 pw.println("\tdisable-feature featureName"); 743 pw.println("\t Disable the requested feature. Change will happen after reboot"); 744 pw.println("\t This requires root/su."); 745 pw.println("\tinject-key [-d display] [-s seat] [-t down_delay_ms | -a down|up] key_code"); 746 pw.println("\t inject key down and/or up event to car service"); 747 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 748 pw.println("\t seat: int seat value defined in VeihicleAreaSeat. 0 for unknown,"); 749 pw.println("\t 0x0001 for row1 left, 0x0002 for row1 center, 0x0004 for row1 right,"); 750 pw.println("\t 0x0010 for row2 left, 0x0020 for row2 center, 0x0040 for row2 right,"); 751 pw.println("\t 0x0100 for row3 left, 0x0200 for row3 center, 0x0400 for row3 right."); 752 pw.println("\t If not specified, it will be driver seat."); 753 pw.println("\t down_delay_ms: delay from down to up key event. If not specified,"); 754 pw.println("\t it will be 0"); 755 pw.println("\t key_code: int key code defined in android KeyEvent"); 756 pw.println("\t If -a isn't specified, both down and up will be injected."); 757 pw.println("\tinject-motion [-d display] [-s seat] [--source source] [-t down_delay_ms] " 758 + "[-a action] [-c count] [-p pointer_id0 pointer_id1...] x0 y0 x1 y1 ..."); 759 pw.println("\t inject motion down or up or move or cancel event to car service"); 760 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 761 pw.println("\t seat: int seat value defined in VeihicleAreaSeat. 0 for unknown,"); 762 pw.println("\t 0x0001 for row1 left, 0x0002 for row1 center, 0x0004 for row1 right,"); 763 pw.println("\t 0x0010 for row2 left, 0x0020 for row2 center, 0x0040 for row2 right,"); 764 pw.println("\t 0x0100 for row3 left, 0x0200 for row3 center, 0x0400 for row3 right."); 765 pw.println("\t If not specified, it will be driver seat."); 766 pw.println("\t source: string source value for motion event."); 767 pw.println("\t If not specified, it will be touchscreen"); 768 pw.println("\t The sources are:"); 769 pw.println("\t touchnavigation"); 770 pw.println("\t touchscreen"); 771 pw.println("\t joystick"); 772 pw.println("\t stylus"); 773 pw.println("\t touchpad"); 774 pw.println("\t gamepad"); 775 pw.println("\t dpad"); 776 pw.println("\t mouse"); 777 pw.println("\t keyboard"); 778 pw.println("\t trackball"); 779 pw.println("\t down_delay_ms: delay from down to up motion event. If not specified,"); 780 pw.println("\t it will be 0"); 781 pw.println("\t action: the MotionEvent.ACTION_* for the event. If not specified,"); 782 pw.println("\t both down and up will be injected."); 783 pw.println("\t This can be a string value that is down|up|move|cancel"); 784 pw.println("\t or an integer value that must equal to MotionEvent.ACTION_*."); 785 pw.println("\t count: the count of pointers. If not specified, it will be 1."); 786 pw.println("\t If this value is greater than 1, there must be as many pointer_id,"); 787 pw.println("\t x, y as this value."); 788 pw.println("\t pointer_id: pointer ids of following coordinates, If not specified,"); 789 pw.println("\t they are automatically set in order from 0."); 790 pw.println("\t x: int x coordinate in android MotionEvent"); 791 pw.println("\t y: int y coordinate in android MotionEvent"); 792 pw.println("\t Must provide the 'count' number of x, y pairs."); 793 pw.println("\tinject-rotary [-d display] [-i input_type] [-c clockwise]"); 794 pw.println("\t [-dt delta_times_ms]"); 795 pw.println("\t inject rotary input event to car service."); 796 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 797 pw.println("\t input_type: 10 for navigation controller input, 11 for volume"); 798 pw.println("\t controller input. If not specified, it will be 10."); 799 pw.println("\t clockwise: true if the event is clockwise, false if the event is"); 800 pw.println("\t counter-clockwise. If not specified, it will be false."); 801 pw.println("\t delta_times_ms: a list of delta time (current time minus event time)"); 802 pw.println("\t in descending order. If not specified, it will be 0."); 803 pw.println("\tinject-custom-input [-d display] [-r repeatCounter] EVENT"); 804 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 805 pw.println("\t repeatCounter: number of times the button was hit (default value is 1)"); 806 pw.println("\t EVENT: mandatory last argument. Possible values for for this flag are "); 807 pw.println("\t F1, F2, up to F10 (functions to defined by OEM partners)"); 808 pw.printf("\t%s <REQ_TYPE> [--timeout TIMEOUT_MS]\n", COMMAND_GET_INITIAL_USER_INFO); 809 pw.println("\t Calls the Vehicle HAL to get the initial boot info, passing the given"); 810 pw.println("\t REQ_TYPE (which could be either FIRST_BOOT, FIRST_BOOT_AFTER_OTA, "); 811 pw.println("\t COLD_BOOT, RESUME, or any numeric value that would be passed 'as-is')"); 812 pw.println("\t and an optional TIMEOUT_MS to wait for the HAL response (if not set,"); 813 pw.println("\t it will use a default value)."); 814 pw.println("\t The --hal-only option only calls HAL, without using CarUserService."); 815 816 pw.printf("\t%s <USER_ID> [--hal-only] [--ignore-uxr] [--timeout TIMEOUT_MS]\n", 817 COMMAND_SWITCH_USER); 818 pw.println("\t Switches to user USER_ID using the HAL integration."); 819 pw.println("\t The --hal-only option only calls HAL, without switching the user,"); 820 pw.println("\t The --ignore-uxr option ignores any Ux restriction regarding user switch,"); 821 pw.println("\t while the --timeout defines how long to wait for the response."); 822 823 pw.printf("\t%s [--timeout TIMEOUT_MS]\n", COMMAND_LOGOUT_USER); 824 pw.println("\t Logout the current user (if the user was switched toby a device admin)."); 825 pw.println("\t The --timeout option defines how long to wait for the UserHal response."); 826 827 pw.printf("\t%s <USER_ID> [--hal-only]\n", COMMAND_REMOVE_USER); 828 pw.println("\t Removes user with USER_ID using the HAL integration."); 829 pw.println("\t The --hal-only option only calls HAL, without removing the user,"); 830 831 pw.printf("\t%s [--hal-only] [--timeout TIMEOUT_MS] [--guest] [--flags FLAGS] [NAME]\n", 832 COMMAND_CREATE_USER); 833 pw.println("\t Creates a new user using the HAL integration."); 834 pw.println("\t The --hal-only uses UserManager to create the user,"); 835 pw.println("\t while the --timeout defines how long to wait for the response."); 836 837 pw.printf("\t%s\n", COMMAND_GET_INITIAL_USER); 838 pw.printf("\t Gets the id of the initial user (or %s when it's not available)\n", 839 NO_INITIAL_USER); 840 841 pw.printf("\t%s [occupantZoneId] [userId]\n", COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE); 842 pw.println("\t Maps the occupant zone id to user id."); 843 pw.printf("\t%s [occupantZoneId]\n", COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE); 844 pw.println("\t Unmaps the user assigned to occupant zone id."); 845 846 pw.printf("\t%s [--hal-only] [--user USER_ID] TYPE1 [..TYPE_N]\n", 847 COMMAND_GET_USER_AUTH_ASSOCIATION); 848 pw.println("\t Gets the N user authentication values for the N types for the given user"); 849 pw.println("\t (or current user when not specified)."); 850 pw.println("\t By default it calls CarUserManager, but using --hal-only will call just " 851 + "UserHalService."); 852 853 pw.printf("\t%s [--hal-only] [--user USER_ID] TYPE1 VALUE1 [..TYPE_N VALUE_N]\n", 854 COMMAND_SET_USER_AUTH_ASSOCIATION); 855 pw.println("\t Sets the N user authentication types with the N values for the given user"); 856 pw.println("\t (or current user when not specified)."); 857 pw.println("\t By default it calls CarUserManager, but using --hal-only will call just " 858 + "UserHalService."); 859 pw.printf("\t %s\n", VALID_USER_AUTH_TYPES_HELP); 860 pw.printf("\t %s\n", VALID_USER_AUTH_SET_VALUES_HELP); 861 862 pw.printf("\t%s [true|false]\n", COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE); 863 pw.println("\t Controls backgroud user start and stop during garage mode."); 864 pw.println("\t If false, garage mode operations (background users start at garage mode" 865 + " entry and background users stop at garage mode exit) will be skipped."); 866 867 pw.printf("\t %s [%s|%s|%s|%s]\n", COMMAND_SILENT_MODE, SILENT_MODE_FORCED_SILENT, 868 SILENT_MODE_FORCED_NON_SILENT, SILENT_MODE_NON_FORCED, PARAM_QUERY_MODE); 869 pw.println("\t Forces silent mode silent or non-silent. With query (or no command) " 870 + "displays the silent state"); 871 pw.println("\t and shows how many listeners are monitoring the state."); 872 873 pw.printf("\t%s [%s|%s|%s|%s]\n", COMMAND_EMULATE_DRIVING_STATE, DRIVING_STATE_DRIVE, 874 DRIVING_STATE_PARK, DRIVING_STATE_REVERSE, DRIVING_STATE_NEUTRAL); 875 pw.println("\t Emulates the giving driving state."); 876 877 pw.printf("\t%s\n", COMMAND_GET_DRIVING_STATE); 878 pw.println("\t Gets the current driving state."); 879 880 pw.printf("\t%s <POLICY_ID> [--enable COMP1,COMP2,...] [--disable COMP1,COMP2,...]\n", 881 COMMAND_DEFINE_POWER_POLICY); 882 pw.println("\t Defines a power policy. Components not specified in --enable or --disable"); 883 pw.println("\t are unchanged when the policy is applied."); 884 pw.println("\t Components should be comma-separated without space."); 885 886 pw.printf("\t%s <POLICY_ID>\n", COMMAND_APPLY_POWER_POLICY); 887 pw.println("\t Applies power policy which is defined in " 888 + "/vendor/etc/automotive/power_policy.xml or"); 889 pw.printf("\t by %s command\n", COMMAND_DEFINE_POWER_POLICY); 890 891 pw.printf("\t%s <POLICY_GROUP_ID> [%s:<POLICY_ID>] [%s:<POLICY_ID>]\n", 892 COMMAND_DEFINE_POWER_POLICY_GROUP, POWER_STATE_WAIT_FOR_VHAL, POWER_STATE_ON); 893 pw.println("\t Defines a power policy group. The policy ID must be defined in advance."); 894 895 pw.printf("\t%s <POLICY_GROUP_ID>\n", COMMAND_SET_POWER_POLICY_GROUP); 896 pw.println("\t Sets power policy group which is defined in " 897 + "/vendor/etc/automotive/power_policy.xml "); 898 pw.printf("\t or by %s command\n", COMMAND_DEFINE_POWER_POLICY_GROUP); 899 900 pw.printf("\t%s\n", COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY); 901 pw.println("\t Define and apply the cts_verifier_off power policy with " 902 + "--disable WIFI,LOCATION,BLUETOOTH"); 903 904 pw.printf("\t%s\n", COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY); 905 pw.println("\t Define and apply the cts_verifier_on power policy with " 906 + "--enable WIFI,LOCATION,BLUETOOTH"); 907 908 pw.printf("\t%s\n", COMMAND_GET_CURRENT_POWER_POLICY); 909 pw.println("\t Gets the current power policy."); 910 911 pw.printf("\t%s [%s] [%s]\n", COMMAND_POWER_OFF, PARAM_SKIP_GARAGEMODE, PARAM_REBOOT); 912 pw.println("\t Powers off the car."); 913 914 pw.printf("\t%s <REARVIEW_CAMERA_ID>\n", COMMAND_SET_REARVIEW_CAMERA_ID); 915 pw.println("\t Configures a target camera device CarEvsService to use."); 916 pw.println("\t If CAMEAR_ID is \"default\", this command will configure CarEvsService "); 917 pw.println("\t to use its default camera device."); 918 919 pw.printf("\t%s\n", COMMAND_GET_REARVIEW_CAMERA_ID); 920 pw.println("\t Gets the name of the camera device CarEvsService is using for " + 921 "the rearview."); 922 923 pw.printf("\t%s <SERVICE_TYPE> <CAMERA_ID>\n", COMMAND_SET_CAMERA_ID); 924 pw.println("\t Configures a target camera device CarEvsService will use for a specified "); 925 pw.println("\t service type."); 926 pw.println("\t Possible SERVICE_TYPEs are REARVIEW, FRONTVIEW, LEFTVIEW, RIGHTVIEW, "); 927 pw.println("\t DRIVERVIEW, FRONT_PASSENGERSVIEW, REAR_PASSENGERSVIEW, or USER_DEFINED"); 928 pw.println("\t (* of CarEvsManager.SERVICE_TYPE_* to specify a service type)."); 929 930 pw.printf("\t%s <SERVICE_TYPE>\n", COMMAND_GET_CAMERA_ID); 931 pw.println("\t Gets the name of the camera device that is assigned to a specified "); 932 pw.println("\t service type."); 933 pw.println("\t Possible SERVICE_TYPEs are REARVIEW, FRONTVIEW, LEFTVIEW, RIGHTVIEW, "); 934 pw.println("\t DRIVERVIEW, FRONT_PASSENGERSVIEW, REAR_PASSENGERSVIEW, or USER_DEFINED"); 935 pw.println("\t (* of CarEvsManager.SERVICE_TYPE_* to specify a service type)."); 936 937 pw.printf("\t%s <SERVICE_TYPE> <CAMERA_ID>\n", COMMAND_ENABLE_CAMERA_SERVICE_TYPE); 938 pw.println("\t Enables a specified service type with a camera associated with a given "); 939 pw.println("\t camera id."); 940 pw.println("\t Use * of CarEvsManager.SERVICE_TYPE_* to specify a service type."); 941 942 pw.printf("\t%s <SERVICE_TYPE>\n", COMMAND_CHECK_CAMERA_SERVICE_TYPE_ENABLED); 943 pw.println("\t Checks whether or not a given service type is enabled."); 944 pw.println("\t Use * of CarEvsManager.SERVICE_TYPE_* to specify a service type."); 945 946 pw.printf("\t%s true|false <PACKAGE_NAME>\n", 947 COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE); 948 pw.println("\t Marks PACKAGE_NAME as killable or not killable on resource overuse "); 949 950 pw.printf("\t%s <FOREGROUND_MODE_BYTES>\n", COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES); 951 pw.println("\t Sets third-party apps foreground I/O overuse threshold"); 952 953 pw.printf("\t%s\n", COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES); 954 pw.println("\t Gets third-party apps foreground I/O overuse threshold"); 955 956 pw.printf("\t%s enable|disable\n", COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK); 957 pw.println("\t Enables/disables car watchdog process health check."); 958 959 pw.printf("\t%s <PACKAGE_NAME> [--user USER_ID]\n", COMMAND_WATCHDOG_RESOURCE_OVERUSE_KILL); 960 pw.println("\t Kills PACKAGE_NAME due to resource overuse."); 961 962 pw.printf("\t%s [REGION_STRING]", COMMAND_DRIVING_SAFETY_SET_REGION); 963 pw.println("\t Set driving safety region."); 964 pw.println("\t Skipping REGION_STRING leads into resetting to all regions"); 965 966 pw.printf("\t%s <subcommand>", COMMAND_TELEMETRY); 967 pw.println("\t Telemetry commands."); 968 pw.println("\t Provide -h to see the list of sub-commands."); 969 970 pw.printf("\t%s get|default|enable|disable_until_used <PACKAGE_NAME>\n", 971 COMMAND_CONTROL_COMPONENT_ENABLED_STATE); 972 pw.println("\t Gets the current EnabledState, or changes the Application EnabledState" 973 + " to DEFAULT, ENABLED or DISABLED_UNTIL_USED."); 974 pw.printf("\t%s [user]\n", COMMAND_CHECK_LOCK_IS_SECURE); 975 pw.println("\t check if the current or given user has a lock to secure"); 976 pw.printf("\t%s", COMMAND_LIST_VHAL_PROPS); 977 pw.println("\t list all supported property IDS by vehicle HAL"); 978 pw.printf("\t%s", COMMAND_GET_VHAL_BACKEND); 979 pw.println("\t list whether we are connected to AIDL or HIDL vehicle HAL backend"); 980 pw.printf("\t%s <PROP_ID> <REQUEST_SIZE>", COMMAND_TEST_ECHO_REVERSE_BYTES); 981 pw.println("\t test the ECHO_REVERSE_BYTES property. PROP_ID is the ID (int) for " 982 + "ECHO_REVERSE_BYTES, REQUEST_SIZE is how many byteValues in the request. " 983 + "This command can be used for testing LargeParcelable by passing large request."); 984 985 pw.printf("\t%s [--user USER] <APP1> [APPN]", COMMAND_GET_TARGET_CAR_VERSION); 986 pw.println("\t Gets the target API version (major and minor) defined by the given apps " 987 + "for the given user (or current user when --user is not set)."); 988 989 pw.printf("\t%s <PID> <CPU_GROUP_ID>", COMMAND_SET_PROCESS_GROUP); 990 pw.println("\t Change CPU group of a process. Check android.os.Process.setProcessGroup " 991 + "for details on the parameters."); 992 pw.printf("\t%s <PID>", COMMAND_GET_PROCESS_GROUP); 993 pw.println("\t Get the CPU group of a process. Check android.os.Process.getProcessGroup " 994 + "for details on the parameters."); 995 pw.printf("\t%s <PID> <UID> <CPU_PROFILE>", COMMAND_SET_PROCESS_PROFILE); 996 pw.println("\t Change CPU profile (=CPUSet) of a process. Check " 997 + "android.os.Process.setProcessProfile for details on the parameters."); 998 999 pw.printf("\t%s <USER>", COMMAND_GET_DISPLAY_BY_USER); 1000 pw.println("\t Gets the display associated to the given user"); 1001 pw.printf("\t%s <DISPLAY>", COMMAND_GET_USER_BY_DISPLAY); 1002 pw.println("\t Gets the user associated with the given display"); 1003 pw.printf("\t%s <USER_ID> <DISPLAY_ID>", COMMAND_ASSIGN_EXTRA_DISPLAY); 1004 pw.println("\t Assigns the user to the extra display."); 1005 pw.printf("\t%s <USER_ID> <DISPLAY_ID>", COMMAND_UNASSIGN_EXTRA_DISPLAY); 1006 pw.println("\t Unassigns the user from the extra display."); 1007 1008 pw.printf("\t%s <DISPLAY>", COMMAND_GET_CURRENT_UX_RESTRICTIONS); 1009 pw.println("\t Gets the current UX restriction on given display. If no display is " 1010 + "provided, return current UX restrictions on default display."); 1011 pw.printf("\t%s <mode>", COMMAND_SET_CURRENT_UXR_MODE); 1012 pw.println("\t Sets current mode for UX restrictions."); 1013 pw.printf("\t%s", COMMAND_GET_CURRENT_UXR_MODE); 1014 pw.println("\t Gets current mode for UX restrictions."); 1015 pw.printf("\t%s", COMMAND_GET_SUPPORTED_UXR_MODES); 1016 pw.println("\t Gets all supported UX restrictions modes."); 1017 pw.printf("\t%s", COMMAND_GET_UXR_CONFIG); 1018 pw.println("\t Gets UX restrictions configuration."); 1019 pw.printf("\t%s", COMMAND_GET_INPUT_AND_DISPLAY_INFO); 1020 pw.println("\t Gets input devices & their descriptor; and gets display devices & their " 1021 + "uniqueId"); 1022 pw.printf("\t%s <input descriptor> <display unique id>", 1023 COMMAND_ADD_INPUT_DESCRIPTOR_ASSOCIATION_TO_DISPLAY_UNIQUE_ID); 1024 pw.println("\t Add association of the input device to the particular display by using " 1025 + "input descriptor."); 1026 pw.printf("\t%s <input descriptor>", COMMAND_REMOVE_INPUT_DESCRIPTOR_ASSOCIATION); 1027 pw.println("\t Remove association of the input device descriptor to any display."); 1028 pw.printf("\t%s shutdown-prepare|shutdown-enter", COMMAND_WATCHDOG_INJECT_POWER_STATE); 1029 pw.println("\t Sends a power signal to CarWatchdog."); 1030 } 1031 showInvalidArguments(IndentingPrintWriter pw)1032 private static int showInvalidArguments(IndentingPrintWriter pw) { 1033 pw.println("Incorrect number of arguments."); 1034 showHelp(pw); 1035 return RESULT_ERROR; 1036 } 1037 runSetZoneIdForUid(String zoneString, String uidString)1038 private void runSetZoneIdForUid(String zoneString, String uidString) { 1039 int uid = Integer.parseInt(uidString); 1040 int zoneId = Integer.parseInt(zoneString); 1041 mCarAudioService.setZoneIdForUid(zoneId, uid); 1042 } 1043 runSetMuteCarVolumeGroup(String zoneString, String groupIdString, String muteString)1044 private void runSetMuteCarVolumeGroup(String zoneString, String groupIdString, 1045 String muteString) { 1046 int groupId = Integer.parseInt(groupIdString); 1047 int zoneId = Integer.parseInt(zoneString); 1048 if (!PARAM_MUTE.equalsIgnoreCase(muteString) 1049 && !PARAM_UNMUTE.equalsIgnoreCase(muteString)) { 1050 throw new IllegalArgumentException("Failed to set volume group mute for " 1051 + groupIdString + " in zone " + zoneString 1052 + ", bad mute argument: " + muteString); 1053 } 1054 boolean muteState = PARAM_MUTE.equalsIgnoreCase(muteString); 1055 mCarAudioService.setVolumeGroupMute(zoneId, groupId, muteState, FLAG_SHOW_UI); 1056 } 1057 1058 runSetGroupVolume(String zoneIdString, String groupIdString, String volumeString)1059 private void runSetGroupVolume(String zoneIdString, String groupIdString, String volumeString) { 1060 int groupId = Integer.parseInt(groupIdString); 1061 int zoneId = Integer.parseInt(zoneIdString); 1062 int percentVolume = Integer.parseInt(volumeString); 1063 Preconditions.checkArgumentInRange(percentVolume, 0, 100, 1064 "%volume for group " + groupIdString + " in zone " + zoneIdString); 1065 int minIndex = mCarAudioService.getGroupMinVolume(zoneId, groupId); 1066 int maxIndex = mCarAudioService.getGroupMaxVolume(zoneId, groupId); 1067 int index = minIndex 1068 + (int) ((float) (maxIndex - minIndex) * ((float) percentVolume / 100.0f)); 1069 mCarAudioService.setGroupVolume(zoneId, groupId, index, FLAG_SHOW_UI); 1070 } 1071 runSetAudioMirror(String zoneId1String, String zoneId2String, IndentingPrintWriter writer)1072 private void runSetAudioMirror(String zoneId1String, String zoneId2String, 1073 IndentingPrintWriter writer) { 1074 int zoneId1 = Integer.parseInt(zoneId1String); 1075 int zoneId2 = Integer.parseInt(zoneId2String); 1076 1077 if (mMirrorStatusCallback == null) { 1078 mMirrorStatusCallback = new AudioZoneMirrorStatusCallbackImpl(); 1079 boolean registered = mCarAudioService.registerAudioZonesMirrorStatusCallback( 1080 mMirrorStatusCallback); 1081 if (!registered) { 1082 writer.printf("Could not register audio mirror status callback for zones %s %s\n", 1083 zoneId1String, zoneId2String); 1084 mMirrorStatusCallback = null; 1085 return; 1086 } 1087 } 1088 mMirrorStatusCallback.reset(); 1089 1090 mCarAudioService.enableMirrorForAudioZones(new int[] {zoneId1, zoneId2}); 1091 boolean called; 1092 try { 1093 called = mMirrorStatusCallback.waitForCallback(); 1094 } catch (Exception e) { 1095 Slogf.e(TAG, e, "runSetAudioMirror wait for callback failed for zones %s %s", 1096 zoneId1String, zoneId2String); 1097 return; 1098 } 1099 1100 if (!called) { 1101 writer.printf("Did not receive mirror status callback for zones %s %s\n", 1102 zoneId1String, zoneId2String); 1103 return; 1104 } 1105 1106 writer.printf("Received mirror status callback for zones %s %s\n", zoneId1String, 1107 zoneId2String); 1108 writer.increaseIndent(); 1109 for (int c = 0; c < mMirrorStatusCallback.mZoneIds.length; c++) { 1110 writer.printf("Received zone[%d] %d\n", c , mMirrorStatusCallback.mZoneIds[c]); 1111 } 1112 writer.printf("Received status %d\n", mMirrorStatusCallback.mStatus); 1113 writer.decreaseIndent(); 1114 } 1115 runUnsetAudioMirror(String[] args, IndentingPrintWriter writer)1116 private void runUnsetAudioMirror(String[] args, IndentingPrintWriter writer) { 1117 boolean useConfig = false; 1118 for (int i = 2; i < args.length; i++) { 1119 String arg = args[i]; 1120 switch (arg) { 1121 case "--requestId": 1122 useConfig = true; 1123 break; 1124 default: 1125 writer.println("Invalid option at index " + i + ": " + arg); 1126 return; 1127 } 1128 } 1129 String inputString = args[1]; 1130 if (mMirrorStatusCallback == null) { 1131 mMirrorStatusCallback = new AudioZoneMirrorStatusCallbackImpl(); 1132 boolean registered = mCarAudioService.registerAudioZonesMirrorStatusCallback( 1133 mMirrorStatusCallback); 1134 if (!registered) { 1135 mMirrorStatusCallback = null; 1136 return; 1137 } 1138 } 1139 mMirrorStatusCallback.reset(); 1140 1141 if (useConfig) { 1142 long requestId = Long.parseLong(inputString); 1143 mCarAudioService.disableAudioMirror(requestId); 1144 } else { 1145 int zoneId = Integer.parseInt(inputString); 1146 mCarAudioService.disableAudioMirrorForZone(zoneId); 1147 } 1148 1149 boolean called; 1150 try { 1151 called = mMirrorStatusCallback.waitForCallback(); 1152 } catch (Exception e) { 1153 Slogf.e(TAG, e, "runUnsetAudioMirror wait for callback failed for zones %s", 1154 inputString); 1155 return; 1156 } 1157 1158 if (!called) { 1159 writer.printf("Did not receive mirror status callback for zones %s\n", inputString); 1160 return; 1161 } 1162 1163 writer.printf("Received mirror status callback for zones %s\n", inputString); 1164 writer.increaseIndent(); 1165 for (int c = 0; c < mMirrorStatusCallback.mZoneIds.length; c++) { 1166 writer.printf("Received zone[%d] %d\n", c , mMirrorStatusCallback.mZoneIds[c]); 1167 } 1168 writer.printf("Received status %d\n", mMirrorStatusCallback.mStatus); 1169 writer.decreaseIndent(); 1170 1171 mCarAudioService.unregisterAudioZonesMirrorStatusCallback(mMirrorStatusCallback); 1172 } 1173 runResetSelectedVolumeContext()1174 private void runResetSelectedVolumeContext() { 1175 mCarAudioService.resetSelectedVolumeContext(); 1176 } 1177 runSetOccupantZoneIdForUserId(String occupantZoneIdString, String userIdString)1178 private void runSetOccupantZoneIdForUserId(String occupantZoneIdString, 1179 String userIdString) { 1180 int userId = Integer.parseInt(userIdString); 1181 int occupantZoneId = Integer.parseInt(occupantZoneIdString); 1182 if (!mCarOccupantZoneService.assignProfileUserToOccupantZone(occupantZoneId, userId)) { 1183 throw new IllegalStateException("Failed to set userId " + userId + " to occupantZoneId " 1184 + occupantZoneIdString); 1185 } 1186 } 1187 runResetOccupantZoneId(String occupantZoneIdString)1188 private void runResetOccupantZoneId(String occupantZoneIdString) { 1189 int occupantZoneId = Integer.parseInt(occupantZoneIdString); 1190 if (!mCarOccupantZoneService 1191 .assignProfileUserToOccupantZone(occupantZoneId, UserManagerHelper.USER_NULL)) { 1192 throw new IllegalStateException("Failed to reset occupantZoneId " 1193 + occupantZoneIdString); 1194 } 1195 } 1196 assertHasAtLeastOnePermission(String cmd, String[] requiredPermissions)1197 private void assertHasAtLeastOnePermission(String cmd, String[] requiredPermissions) { 1198 for (String requiredPermission : requiredPermissions) { 1199 if (CarServiceUtils.hasPermission(mContext, requiredPermission)) return; 1200 } 1201 if (requiredPermissions.length == 1) { 1202 throw new SecurityException("The command '" + cmd + "' requires permission:" 1203 + requiredPermissions[0]); 1204 } 1205 throw new SecurityException( 1206 "The command " + cmd + " requires one of the following permissions:" 1207 + Arrays.toString(requiredPermissions)); 1208 } 1209 exec(String[] args, IndentingPrintWriter writer)1210 int exec(String[] args, IndentingPrintWriter writer) { 1211 String cmd = args[0]; 1212 String[] requiredPermissions = USER_BUILD_COMMAND_TO_PERMISSIONS_MAP.get(cmd); 1213 if (requiredPermissions == null) { 1214 String requiredPermission = USER_BUILD_COMMAND_TO_PERMISSION_MAP.get(cmd); 1215 if (requiredPermission != null) { 1216 requiredPermissions = new String[] { requiredPermission }; 1217 } 1218 1219 } 1220 if (VERBOSE) { 1221 Slogf.v(TAG, "cmd: " + cmd + ", requiredPermissions: " 1222 + Arrays.toString(requiredPermissions)); 1223 } 1224 if (BuildHelper.isUserBuild() && requiredPermissions == null) { 1225 throw new SecurityException("The command '" + cmd + "' requires non-user build"); 1226 } 1227 if (requiredPermissions != null) { 1228 assertHasAtLeastOnePermission(cmd, requiredPermissions); 1229 } 1230 1231 switch (cmd) { 1232 case COMMAND_HELP: 1233 showHelp(writer); 1234 break; 1235 case COMMAND_DAY_NIGHT_MODE: { 1236 String value = args.length < 2 ? "" : args[1]; 1237 forceDayNightMode(value, writer); 1238 break; 1239 } 1240 case COMMAND_GARAGE_MODE: { 1241 String value = args.length < 2 ? "" : args[1]; 1242 forceGarageMode(value, writer); 1243 break; 1244 } 1245 case COMMAND_INJECT_VHAL_EVENT: 1246 injectVhalEvent(args, writer); 1247 break; 1248 case COMMAND_INJECT_CONTINUOUS_EVENT: 1249 injectContinuousEvents(args, writer); 1250 break; 1251 case COMMAND_INJECT_ERROR_EVENT: 1252 injectErrorEvent(args, writer); 1253 break; 1254 case COMMAND_ENABLE_UXR: 1255 if (args.length != 2) { 1256 return showInvalidArguments(writer); 1257 } 1258 boolean enableBlocking = Boolean.valueOf(args[1]); 1259 if (mCarPackageManagerService != null) { 1260 // Need to clear the binder identity if calling process is root since 1261 // signature will not match with that of car service. 1262 final long identity = Binder.clearCallingIdentity(); 1263 try { 1264 mCarPackageManagerService.setEnableActivityBlocking(enableBlocking); 1265 } finally { 1266 Binder.restoreCallingIdentity(identity); 1267 } 1268 } 1269 break; 1270 case COMMAND_GET_DO_ACTIVITIES: 1271 if (args.length != 2) { 1272 return showInvalidArguments(writer); 1273 } 1274 String pkgName = args[1].toLowerCase(Locale.US); 1275 if (mCarPackageManagerService != null) { 1276 String[] doActivities = 1277 mCarPackageManagerService.getDistractionOptimizedActivities( 1278 pkgName); 1279 if (doActivities != null) { 1280 writer.println("DO Activities for " + pkgName); 1281 for (String a : doActivities) { 1282 writer.println(a); 1283 } 1284 } else { 1285 writer.println("No DO Activities for " + pkgName); 1286 } 1287 } 1288 break; 1289 case COMMAND_GET_CARPROPERTYCONFIG: 1290 getCarPropertyConfig(args, writer); 1291 break; 1292 case COMMAND_GET_PROPERTY_VALUE: 1293 getPropertyValue(args, writer); 1294 break; 1295 case COMMAND_GENERATE_TEST_VENDOR_CONFIGS: 1296 try (CarTestService.NativePipe pipe = CarTestService.NativePipe.newPipe()) { 1297 mHal.dumpVhal(pipe.getFileDescriptor(), List.of("--genTestVendorConfigs")); 1298 writer.print(pipe.getOutput(DEFAULT_HAL_TIMEOUT_MS)); 1299 } catch (Exception e) { 1300 Slogf.w(TAG, "dumpVhal --genTestVendorConfigs Failed", e); 1301 return showInvalidArguments(writer); 1302 } 1303 break; 1304 case COMMAND_RESTORE_TEST_VENDOR_CONFIGS: 1305 try (CarTestService.NativePipe pipe = CarTestService.NativePipe.newPipe()) { 1306 mHal.dumpVhal(pipe.getFileDescriptor(), List.of("--restoreVendorConfigs")); 1307 writer.print(pipe.getOutput(DEFAULT_HAL_TIMEOUT_MS)); 1308 } catch (Exception e) { 1309 Slogf.w(TAG, "dumpVhal --genTestVendorConfigs Failed", e); 1310 return showInvalidArguments(writer); 1311 } 1312 break; 1313 case COMMAND_SET_PROPERTY_VALUE: 1314 setPropertyValue(args, writer); 1315 break; 1316 case COMMAND_PROJECTION_UI_MODE: 1317 if (args.length != 2) { 1318 return showInvalidArguments(writer); 1319 } 1320 mCarProjectionService.setUiMode(Integer.valueOf(args[1])); 1321 break; 1322 case COMMAND_PROJECTION_AP_TETHERING: 1323 if (args.length != 2) { 1324 return showInvalidArguments(writer); 1325 } 1326 mCarProjectionService.setAccessPointTethering(Boolean.parseBoolean(args[1])); 1327 break; 1328 case COMMAND_PROJECTION_AP_STABLE_CONFIG: 1329 if (args.length != 2) { 1330 return showInvalidArguments(writer); 1331 } 1332 mCarProjectionService.setStableLocalOnlyHotspotConfig( 1333 Boolean.parseBoolean(args[1])); 1334 break; 1335 case COMMAND_RESUME: 1336 mCarPowerManagementService.forceSimulatedResume(); 1337 writer.println("Resume: Simulating resuming from Deep Sleep"); 1338 break; 1339 case COMMAND_SUSPEND: 1340 // fall-through 1341 case COMMAND_HIBERNATE: 1342 runSuspendCommand(args, writer); 1343 break; 1344 case COMMAND_SET_DISPLAY_STATE: 1345 if (args.length != 3) { 1346 return showInvalidArguments(writer); 1347 } 1348 try { 1349 mCarPowerManagementService.setDisplayPowerState( 1350 Integer.valueOf(args[1]), Boolean.parseBoolean(args[2])); 1351 } catch (Exception e) { 1352 Slogf.w(TAG, "Invalid argument: %s %s %s", COMMAND_SET_DISPLAY_STATE, args[1], 1353 args[2]); 1354 return showInvalidArguments(writer); 1355 } 1356 break; 1357 case COMMAND_SET_DISPLAY_BRIGHTNESS: 1358 return setDisplayBrightness(args, writer); 1359 case COMMAND_GET_DISPLAY_BRIGHTNESS: 1360 return getDisplayBrightness(args, writer); 1361 case COMMAND_SET_UID_TO_ZONE: 1362 if (args.length != 3) { 1363 return showInvalidArguments(writer); 1364 } 1365 runSetZoneIdForUid(args[1], args[2]); 1366 break; 1367 case COMMAND_RESET_VOLUME_CONTEXT: 1368 if (args.length > 1) { 1369 return showInvalidArguments(writer); 1370 } 1371 runResetSelectedVolumeContext(); 1372 break; 1373 case COMMAND_SET_MUTE_CAR_VOLUME_GROUP: 1374 if (args.length != 4) { 1375 return showInvalidArguments(writer); 1376 } 1377 runSetMuteCarVolumeGroup(args[1], args[2], args[3]); 1378 break; 1379 case COMMAND_SET_GROUP_VOLUME: 1380 if (args.length != 4) { 1381 return showInvalidArguments(writer); 1382 } 1383 runSetGroupVolume(args[1], args[2], args[3]); 1384 break; 1385 case COMMAND_SET_AUDIO_MIRROR: 1386 if (args.length != 3) { 1387 return showInvalidArguments(writer); 1388 } 1389 runSetAudioMirror(args[1], args[2], writer); 1390 break; 1391 case COMMAND_UNSET_AUDIO_MIRROR: 1392 if (args.length < 1) { 1393 return showInvalidArguments(writer); 1394 } 1395 runUnsetAudioMirror(args, writer); 1396 break; 1397 case COMMAND_SET_USER_ID_TO_OCCUPANT_ZONE: 1398 if (args.length != 3) { 1399 return showInvalidArguments(writer); 1400 } 1401 runSetOccupantZoneIdForUserId(args[1], args[2]); 1402 break; 1403 case COMMAND_SILENT_MODE: { 1404 String value = args.length < 2 ? "" 1405 : args.length == 2 ? args[1] : "too many arguments"; 1406 runSilentCommand(value, writer); 1407 break; 1408 } 1409 case COMMAND_RESET_USER_ID_IN_OCCUPANT_ZONE: 1410 if (args.length != 2) { 1411 return showInvalidArguments(writer); 1412 } 1413 runResetOccupantZoneId(args[1]); 1414 break; 1415 case COMMAND_START_FIXED_ACTIVITY_MODE: 1416 startFixedActivity(args, writer); 1417 break; 1418 case COMMAND_STOP_FIXED_ACTIVITY_MODE: 1419 stopFixedMode(args, writer); 1420 break; 1421 case COMMAND_ENABLE_FEATURE: 1422 if (args.length != 2) { 1423 return showInvalidArguments(writer); 1424 } 1425 enableDisableFeature(args, writer, /* enable= */ true); 1426 break; 1427 case COMMAND_DISABLE_FEATURE: 1428 if (args.length != 2) { 1429 return showInvalidArguments(writer); 1430 } 1431 enableDisableFeature(args, writer, /* enable= */ false); 1432 break; 1433 case COMMAND_INJECT_KEY: 1434 if (args.length < 2) { 1435 return showInvalidArguments(writer); 1436 } 1437 injectKey(args, writer); 1438 break; 1439 case COMMAND_INJECT_MOTION: 1440 if (args.length < 2) { 1441 return showInvalidArguments(writer); 1442 } 1443 injectMotion(args, writer); 1444 break; 1445 case COMMAND_INJECT_ROTARY: 1446 if (args.length < 1) { 1447 return showInvalidArguments(writer); 1448 } 1449 injectRotary(args, writer); 1450 break; 1451 case COMMAND_INJECT_CUSTOM_INPUT: 1452 if (args.length < 2) { 1453 return showInvalidArguments(writer); 1454 } 1455 injectCustomInputEvent(args, writer); 1456 break; 1457 case COMMAND_GET_INITIAL_USER_INFO: 1458 getInitialUserInfo(args, writer); 1459 break; 1460 case COMMAND_SWITCH_USER: 1461 switchUser(args, writer); 1462 break; 1463 case COMMAND_LOGOUT_USER: 1464 logoutUser(args, writer); 1465 break; 1466 case COMMAND_REMOVE_USER: 1467 removeUser(args, writer); 1468 break; 1469 case COMMAND_CREATE_USER: 1470 createUser(args, writer); 1471 break; 1472 case COMMAND_GET_INITIAL_USER: 1473 getInitialUser(writer); 1474 break; 1475 case COMMAND_GET_USER_AUTH_ASSOCIATION: 1476 getUserAuthAssociation(args, writer); 1477 break; 1478 case COMMAND_SET_USER_AUTH_ASSOCIATION: 1479 setUserAuthAssociation(args, writer); 1480 break; 1481 case COMMAND_SET_START_BG_USERS_ON_GARAGE_MODE: 1482 setStartBackgroundUsersOnGarageMode(args, writer); 1483 break; 1484 case COMMAND_EMULATE_DRIVING_STATE: 1485 emulateDrivingState(args, writer); 1486 break; 1487 case COMMAND_GET_DRIVING_STATE: 1488 getDrivingState(writer); 1489 break; 1490 case COMMAND_DEFINE_POWER_POLICY: 1491 return definePowerPolicy(args, writer); 1492 case COMMAND_APPLY_POWER_POLICY: 1493 return applyPowerPolicy(args, writer); 1494 case COMMAND_DEFINE_POWER_POLICY_GROUP: 1495 return definePowerPolicyGroup(args, writer); 1496 case COMMAND_SET_POWER_POLICY_GROUP: 1497 return setPowerPolicyGroup(args, writer); 1498 case COMMAND_GET_CURRENT_POWER_POLICY: 1499 getCurrentPowerPolicy(writer); 1500 break; 1501 case COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY: 1502 return applyCtsVerifierPowerOffPolicy(args, writer); 1503 case COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY: 1504 return applyCtsVerifierPowerOnPolicy(args, writer); 1505 case COMMAND_POWER_OFF: 1506 powerOff(args, writer); 1507 break; 1508 case COMMAND_SET_REARVIEW_CAMERA_ID: 1509 setRearviewCameraId(args, writer); 1510 break; 1511 case COMMAND_GET_REARVIEW_CAMERA_ID: 1512 getRearviewCameraId(writer); 1513 break; 1514 case COMMAND_SET_CAMERA_ID: 1515 setCameraId(args, writer); 1516 break; 1517 case COMMAND_GET_CAMERA_ID: 1518 getCameraId(args, writer); 1519 break; 1520 case COMMAND_ENABLE_CAMERA_SERVICE_TYPE: 1521 enableCameraServiceType(args, writer); 1522 break; 1523 case COMMAND_CHECK_CAMERA_SERVICE_TYPE_ENABLED: 1524 checkCameraServiceTypeEnabled(args, writer); 1525 break; 1526 case COMMAND_WATCHDOG_CONTROL_PACKAGE_KILLABLE_STATE: 1527 controlWatchdogPackageKillableState(args, writer); 1528 break; 1529 case COMMAND_WATCHDOG_IO_SET_3P_FOREGROUND_BYTES: 1530 setWatchdogIoThirdPartyForegroundBytes(args, writer); 1531 break; 1532 case COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES: 1533 getWatchdogIoThirdPartyForegroundBytes(writer); 1534 break; 1535 case COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK: 1536 controlWatchdogProcessHealthCheck(args, writer); 1537 break; 1538 case COMMAND_WATCHDOG_RESOURCE_OVERUSE_KILL: 1539 performResourceOveruseKill(args, writer); 1540 break; 1541 case COMMAND_WATCHDOG_INJECT_POWER_STATE: 1542 setWatchdogPowerState(args, writer); 1543 break; 1544 case COMMAND_DRIVING_SAFETY_SET_REGION: 1545 setDrivingSafetyRegion(args, writer); 1546 break; 1547 case COMMAND_TELEMETRY: 1548 handleTelemetryCommands(args, writer); 1549 break; 1550 case COMMAND_CONTROL_COMPONENT_ENABLED_STATE: 1551 controlComponentEnabledState(args, writer); 1552 break; 1553 case COMMAND_CHECK_LOCK_IS_SECURE: 1554 checkLockIsSecure(args, writer); 1555 break; 1556 case COMMAND_CHECK_FAKE_VHAL: 1557 writer.printf("Car Service connects to FakeVehicleStub: %b\n", 1558 mHal.isFakeModeEnabled()); 1559 break; 1560 case COMMAND_LIST_VHAL_PROPS: 1561 listVhalProps(writer); 1562 break; 1563 case COMMAND_GET_VHAL_BACKEND: 1564 getVhalBackend(writer); 1565 break; 1566 case COMMAND_TEST_ECHO_REVERSE_BYTES: 1567 testEchoReverseBytes(args, writer); 1568 break; 1569 case COMMAND_GET_TARGET_CAR_VERSION: 1570 getTargetCarVersion(args, writer); 1571 break; 1572 case COMMAND_SET_PROCESS_GROUP: 1573 setProcessGroup(args, writer); 1574 break; 1575 case COMMAND_GET_PROCESS_GROUP: 1576 getProcessGroup(args, writer); 1577 break; 1578 case COMMAND_SET_PROCESS_PROFILE: 1579 setProcessProfile(args, writer); 1580 break; 1581 case COMMAND_GET_DISPLAY_BY_USER: 1582 getDisplayByUser(args, writer); 1583 break; 1584 case COMMAND_GET_USER_BY_DISPLAY: 1585 getUserByDisplay(args, writer); 1586 break; 1587 case COMMAND_ASSIGN_EXTRA_DISPLAY: 1588 assignExtraDisplay(args, writer); 1589 break; 1590 case COMMAND_UNASSIGN_EXTRA_DISPLAY: 1591 unassignExtraDisplay(args, writer); 1592 break; 1593 case COMMAND_GET_CURRENT_UX_RESTRICTIONS: 1594 getCurrentUxRestrictions(args, writer); 1595 break; 1596 case COMMAND_SET_CURRENT_UXR_MODE: 1597 setCurrentUxrMode(args, writer); 1598 break; 1599 case COMMAND_GET_CURRENT_UXR_MODE: 1600 getCurrentUxrMode(args, writer); 1601 break; 1602 case COMMAND_GET_SUPPORTED_UXR_MODES: 1603 getSupportedUxRModes(writer); 1604 break; 1605 case COMMAND_GET_UXR_CONFIG: 1606 getUxrConfig(writer); 1607 break; 1608 case COMMAND_GET_INPUT_AND_DISPLAY_INFO: 1609 getInputAndDisplayInfo(writer); 1610 break; 1611 case COMMAND_ADD_INPUT_DESCRIPTOR_ASSOCIATION_TO_DISPLAY_UNIQUE_ID: 1612 addInputDescriptorAssociationToDisplayUniqueId(args, writer); 1613 break; 1614 case COMMAND_REMOVE_INPUT_DESCRIPTOR_ASSOCIATION: 1615 removeInputDescriptorAssociation(args, writer); 1616 break; 1617 default: 1618 writer.println("Unknown command: \"" + cmd + "\""); 1619 showHelp(writer); 1620 return RESULT_ERROR; 1621 } 1622 return RESULT_OK; 1623 } 1624 1625 private boolean isDisplayIdValid(int displayId) { 1626 DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); 1627 Display display = displayManager.getDisplay(displayId); 1628 return (display != null); 1629 } 1630 1631 private int setDisplayBrightness(String[] args, IndentingPrintWriter writer) { 1632 if (args.length != 3) { 1633 return showInvalidArguments(writer); 1634 } 1635 int displayId; 1636 float brightness; 1637 try { 1638 displayId = Integer.valueOf(args[1]); 1639 } catch (Exception e) { 1640 writer.println("Invalid displayId: " + args[1] + ", must be a valid integer"); 1641 return RESULT_ERROR; 1642 } 1643 try { 1644 brightness = Float.valueOf(args[2]); 1645 } catch (Exception e) { 1646 writer.println("Invalid brightness: " + args[2] + ", must be a valid float"); 1647 return RESULT_ERROR; 1648 } 1649 if (!isDisplayIdValid(displayId)) { 1650 writer.println("Invalid display Id: " + displayId); 1651 return RESULT_ERROR; 1652 } 1653 try { 1654 DisplayManagerHelper.setBrightness(mContext, displayId, brightness); 1655 } catch (SecurityException e) { 1656 writer.println("Car shell does not have permission to set display brightness"); 1657 return RESULT_ERROR; 1658 } 1659 return RESULT_OK; 1660 } 1661 1662 private int getDisplayBrightness(String[] args, IndentingPrintWriter writer) { 1663 if (args.length != 2) { 1664 return showInvalidArguments(writer); 1665 } 1666 int displayId; 1667 try { 1668 displayId = Integer.valueOf(args[1]); 1669 } catch (Exception e) { 1670 writer.println("Invalid displayId: " + args[1] + ", must be a valid integer"); 1671 return RESULT_ERROR; 1672 } 1673 if (!isDisplayIdValid(displayId)) { 1674 writer.println("Invalid display Id: " + displayId); 1675 return RESULT_ERROR; 1676 } 1677 try { 1678 float brightness = DisplayManagerHelper.getBrightness(mContext, displayId); 1679 writer.println("Brightness for display Id " + displayId + ": " + brightness); 1680 } catch (SecurityException e) { 1681 writer.println("Car shell does not have permission to get display brightness"); 1682 return RESULT_ERROR; 1683 } 1684 1685 return RESULT_OK; 1686 } 1687 1688 private void getUxrConfig(IndentingPrintWriter writer) { 1689 writer.println(mCarUxRestrictionsManagerService.getConfigs()); 1690 } 1691 1692 private void getSupportedUxRModes(IndentingPrintWriter writer) { 1693 writer.println(mCarUxRestrictionsManagerService.getSupportedRestrictionModes()); 1694 } 1695 1696 private void getCurrentUxrMode(String[] args, IndentingPrintWriter writer) { 1697 writer.printf("Current Uxr restrictions mode: %s\n", 1698 mCarUxRestrictionsManagerService.getRestrictionMode()); 1699 } 1700 1701 private void setCurrentUxrMode(String[] args, IndentingPrintWriter writer) { 1702 if (args.length < 2) { 1703 writer.println("Insufficient number of args"); 1704 return; 1705 } 1706 1707 String mode = args[1]; 1708 mCarUxRestrictionsManagerService.setRestrictionMode(mode); 1709 writer.printf("Current Uxr restrictions mode set to: %s\n", mode); 1710 } 1711 1712 private void getCurrentUxRestrictions(String[] args, IndentingPrintWriter writer) { 1713 int displayId = Display.DEFAULT_DISPLAY; 1714 if (args.length == 2) { 1715 displayId = Integer.parseInt(args[1]); 1716 } 1717 1718 CarUxRestrictions restrictions = mCarUxRestrictionsManagerService 1719 .getCurrentUxRestrictions(displayId); 1720 writer.printf("Current Restrictions:\n %s", restrictions.getActiveRestrictionsString()); 1721 } 1722 1723 private void getInputAndDisplayInfo(IndentingPrintWriter writer) { 1724 InputManager inputManager = mContext.getSystemService(InputManager.class); 1725 int[] inputDeviceIds = inputManager.getInputDeviceIds(); 1726 1727 for (int inputDeviceId : inputDeviceIds) { 1728 InputDevice device = inputManager.getInputDevice(inputDeviceId); 1729 String deviceInfo = "Input Device " + device.getId() + ": " + device.getName() + "\n" 1730 + "\tDescriptor: " + device.getDescriptor() + "\n"; 1731 writer.printf(deviceInfo); 1732 } 1733 1734 DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); 1735 Display[] displays = displayManager.getDisplays(); 1736 for (Display display : displays) { 1737 String displayInfo = "Display Devices " + display.getDisplayId() + ": \n" 1738 + "\tUniqueId: " + DisplayManagerHelper.getUniqueId(display) + " \n"; 1739 writer.printf(displayInfo); 1740 } 1741 } 1742 1743 private void addInputDescriptorAssociationToDisplayUniqueId(String[] args, 1744 IndentingPrintWriter writer) { 1745 InputManager inputManager = mContext.getSystemService(InputManager.class); 1746 if (args.length == 3) { 1747 InputManagerHelper.addUniqueIdAssociationByDescriptor(inputManager, args[1], args[2]); 1748 writer.println("Associated input " + args[1] + " with display " + args[2] + "\n"); 1749 } else { 1750 writer.printf("Incorrect Usage.\nUsage: %s <inputDeviceDescriptor> <displayUniqueId>\n", 1751 COMMAND_ADD_INPUT_DESCRIPTOR_ASSOCIATION_TO_DISPLAY_UNIQUE_ID); 1752 } 1753 } 1754 1755 private void removeInputDescriptorAssociation(String[] args, IndentingPrintWriter writer) { 1756 InputManager inputManager = mContext.getSystemService(InputManager.class); 1757 if (args.length == 2) { 1758 InputManagerHelper.removeUniqueIdAssociationByDescriptor(inputManager, args[1]); 1759 writer.println("Input " + args[1] + " association removed.\n"); 1760 } else { 1761 writer.printf("Incorrect Usage.\nUsage: %s <inputDeviceDescriptor>\n", 1762 COMMAND_REMOVE_INPUT_DESCRIPTOR_ASSOCIATION); 1763 } 1764 } 1765 1766 private void setStartBackgroundUsersOnGarageMode(String[] args, IndentingPrintWriter writer) { 1767 if (args.length < 2) { 1768 writer.println("Insufficient number of args"); 1769 return; 1770 } 1771 1772 boolean enabled = Boolean.parseBoolean(args[1]); 1773 Slogf.d(TAG, "setStartBackgroundUsersOnGarageMode(): " 1774 + (enabled ? "enabled" : "disabled")); 1775 mCarUserService.setStartBackgroundUsersOnGarageMode(enabled); 1776 writer.printf("StartBackgroundUsersOnGarageMode set to %b\n", enabled); 1777 } 1778 1779 private void startFixedActivity(String[] args, IndentingPrintWriter writer) { 1780 if (args.length != 4) { 1781 writer.println("Incorrect number of arguments"); 1782 showHelp(writer); 1783 return; 1784 } 1785 int displayId; 1786 try { 1787 displayId = Integer.parseInt(args[1]); 1788 } catch (NumberFormatException e) { 1789 writer.println("Wrong display id:" + args[1]); 1790 return; 1791 } 1792 String packageName = args[2]; 1793 String activityName = args[3]; 1794 Intent intent = new Intent(); 1795 intent.setComponent(new ComponentName(packageName, activityName)); 1796 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1797 ActivityOptions options = ActivityOptions.makeBasic(); 1798 options.setLaunchDisplayId(displayId); 1799 if (!mFixedActivityService.startFixedActivityModeForDisplayAndUser(intent, options, 1800 displayId, ActivityManager.getCurrentUser())) { 1801 writer.println("Failed to start"); 1802 return; 1803 } 1804 writer.println("Succeeded"); 1805 } 1806 1807 private void stopFixedMode(String[] args, IndentingPrintWriter writer) { 1808 if (args.length != 2) { 1809 writer.println("Incorrect number of arguments"); 1810 showHelp(writer); 1811 return; 1812 } 1813 int displayId; 1814 try { 1815 displayId = Integer.parseInt(args[1]); 1816 } catch (NumberFormatException e) { 1817 writer.println("Wrong display id:" + args[1]); 1818 return; 1819 } 1820 mFixedActivityService.stopFixedActivityMode(displayId); 1821 } 1822 1823 private void enableDisableFeature(String[] args, IndentingPrintWriter writer, boolean enable) { 1824 if (Binder.getCallingUid() != Process.ROOT_UID) { 1825 writer.println("Only allowed to root/su"); 1826 return; 1827 } 1828 String featureName = args[1]; 1829 long id = Binder.clearCallingIdentity(); 1830 // no permission check here 1831 int r; 1832 if (enable) { 1833 r = mFeatureController.enableFeature(featureName); 1834 } else { 1835 r = mFeatureController.disableFeature(featureName); 1836 } 1837 switch (r) { 1838 case Car.FEATURE_REQUEST_SUCCESS: 1839 if (enable) { 1840 writer.println("Enabled feature:" + featureName); 1841 } else { 1842 writer.println("Disabled feature:" + featureName); 1843 } 1844 break; 1845 case Car.FEATURE_REQUEST_ALREADY_IN_THE_STATE: 1846 if (enable) { 1847 writer.println("Already enabled:" + featureName); 1848 } else { 1849 writer.println("Already disabled:" + featureName); 1850 } 1851 break; 1852 case Car.FEATURE_REQUEST_MANDATORY: 1853 writer.println("Cannot change mandatory feature:" + featureName); 1854 break; 1855 case Car.FEATURE_REQUEST_NOT_EXISTING: 1856 writer.println("Non-existing feature:" + featureName); 1857 break; 1858 default: 1859 writer.println("Unknown error:" + r); 1860 break; 1861 } 1862 Binder.restoreCallingIdentity(id); 1863 } 1864 1865 private static int decodeAreaId(String areaIdString) { 1866 try { 1867 return Integer.decode(areaIdString); 1868 } catch (NumberFormatException e) { 1869 throw new NumberFormatException( 1870 "Failed to decode area ID from: " + areaIdString + " - exception: " 1871 + e); 1872 } 1873 } 1874 1875 private static int decodePropertyId(String propertyIdString) { 1876 if (toPropertyId(propertyIdString) != null) { 1877 return toPropertyId(propertyIdString).intValue(); 1878 } 1879 1880 try { 1881 return Integer.decode(propertyIdString); 1882 } catch (NumberFormatException e) { 1883 throw new NumberFormatException( 1884 "Failed to decode property ID from: " + propertyIdString + " - exception: " 1885 + e); 1886 } 1887 } 1888 1889 private void injectKey(String[] args, IndentingPrintWriter writer) { 1890 int i = 1; // 0 is command itself 1891 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 1892 int delayMs = 0; 1893 int keyCode = KeyEvent.KEYCODE_UNKNOWN; 1894 int action = -1; 1895 int seat = SEAT_UNKNOWN; 1896 try { 1897 while (i < args.length) { 1898 switch (args[i]) { 1899 case "-d": 1900 i++; 1901 int vehicleDisplay = Integer.parseInt(args[i]); 1902 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 1903 return; 1904 } 1905 display = InputHalService.convertDisplayType(vehicleDisplay); 1906 break; 1907 case "-t": 1908 i++; 1909 delayMs = Integer.parseInt(args[i]); 1910 break; 1911 case "-a": 1912 i++; 1913 if (args[i].equalsIgnoreCase("down")) { 1914 action = KeyEvent.ACTION_DOWN; 1915 } else if (args[i].equalsIgnoreCase("up")) { 1916 action = KeyEvent.ACTION_UP; 1917 } else { 1918 throw new IllegalArgumentException("Invalid action: " + args[i]); 1919 } 1920 break; 1921 case "-s": 1922 i++; 1923 seat = parseUnsignedInt(args[i]); 1924 break; 1925 default: 1926 if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { 1927 throw new IllegalArgumentException("key_code already set:" 1928 + keyCode); 1929 } 1930 keyCode = Integer.parseInt(args[i]); 1931 } 1932 i++; 1933 } 1934 } catch (NumberFormatException e) { 1935 writer.println("Invalid args:" + e); 1936 showHelp(writer); 1937 return; 1938 } 1939 1940 if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { 1941 writer.println("Missing key code or invalid keycode"); 1942 showHelp(writer); 1943 return; 1944 } 1945 if (delayMs < 0) { 1946 writer.println("Invalid delay:" + delayMs); 1947 showHelp(writer); 1948 return; 1949 } 1950 if (action == -1) { 1951 injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, display, seat); 1952 SystemClock.sleep(delayMs); 1953 injectKeyEvent(KeyEvent.ACTION_UP, keyCode, display, seat); 1954 } else { 1955 injectKeyEvent(action, keyCode, display, seat); 1956 } 1957 writer.println("Succeeded"); 1958 } 1959 1960 private void injectKeyEvent(int action, int keyCode, int display, int seat) { 1961 long currentTime = SystemClock.uptimeMillis(); 1962 if (action == KeyEvent.ACTION_DOWN) mKeyDownTime = currentTime; 1963 long token = Binder.clearCallingIdentity(); 1964 try { 1965 KeyEvent keyEvent = new KeyEvent(/* downTime= */ mKeyDownTime, 1966 /* eventTime= */ currentTime, action, keyCode, /* repeat= */ 0); 1967 if (seat == SEAT_UNKNOWN) { 1968 // Overwrite with the driver seat 1969 seat = mCarOccupantZoneService.getDriverSeat(); 1970 } 1971 mCarInputService.injectKeyEventForSeat(keyEvent, display, seat); 1972 } finally { 1973 Binder.restoreCallingIdentity(token); 1974 } 1975 } 1976 1977 private void injectMotion(String[] args, IndentingPrintWriter writer) { 1978 int i = 1; // 0 is command itself 1979 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 1980 int delayMs = 0; 1981 int action = -1; 1982 int seat = SEAT_UNKNOWN; 1983 int count = 1; 1984 List<Float> coordXs = new ArrayList<>(); 1985 List<Float> coordYs = new ArrayList<>(); 1986 List<Integer> pointerIds = new ArrayList<>(); 1987 int source = InputDevice.SOURCE_TOUCHSCREEN; 1988 try { 1989 while (i < args.length) { 1990 switch (args[i]) { 1991 case "-d": 1992 i++; 1993 int vehicleDisplay = Integer.parseInt(args[i]); 1994 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 1995 return; 1996 } 1997 display = InputHalService.convertDisplayType(vehicleDisplay); 1998 break; 1999 case "-t": 2000 i++; 2001 delayMs = Integer.parseInt(args[i]); 2002 break; 2003 case "-a": 2004 i++; 2005 if (args[i].equalsIgnoreCase("down")) { 2006 action = MotionEvent.ACTION_DOWN; 2007 } else if (args[i].equalsIgnoreCase("up")) { 2008 action = MotionEvent.ACTION_UP; 2009 } else if (args[i].equalsIgnoreCase("move")) { 2010 action = MotionEvent.ACTION_MOVE; 2011 } else if (args[i].equalsIgnoreCase("cancel")) { 2012 action = MotionEvent.ACTION_CANCEL; 2013 } else { 2014 action = parseUnsignedInt(args[i]); 2015 } 2016 break; 2017 case "-s": 2018 i++; 2019 seat = parseUnsignedInt(args[i]); 2020 break; 2021 case "-c": 2022 i++; 2023 count = Integer.parseInt(args[i]); 2024 break; 2025 case "-p": 2026 for (int j = 0; j < count; j++) { 2027 i++; 2028 pointerIds.add(Integer.parseInt(args[i])); 2029 } 2030 break; 2031 case "--source": 2032 i++; 2033 if (MOTION_EVENT_SOURCES.containsKey(args[i])) { 2034 source = MOTION_EVENT_SOURCES.get(args[i]); 2035 } 2036 break; 2037 default: 2038 int remainedArgNum = args.length - i; 2039 if (remainedArgNum != (count * 2)) { 2040 throw new IllegalArgumentException("Invalid coordinate: It needs " 2041 + count + " coordinates."); 2042 } 2043 while (i < args.length) { 2044 coordXs.add(Float.parseFloat(args[i])); 2045 i++; 2046 coordYs.add(Float.parseFloat(args[i])); 2047 i++; 2048 } 2049 } 2050 i++; 2051 } 2052 } catch (NumberFormatException e) { 2053 writer.println("Invalid args:" + e); 2054 showHelp(writer); 2055 return; 2056 } 2057 2058 if (delayMs < 0) { 2059 writer.println("Invalid delay:" + delayMs); 2060 showHelp(writer); 2061 return; 2062 } 2063 if (coordXs.isEmpty() || coordYs.isEmpty()) { 2064 writer.println("Missing x, y coordinate"); 2065 showHelp(writer); 2066 return; 2067 } 2068 if (action == -1) { 2069 injectMotionEvent(source, MotionEvent.ACTION_DOWN, coordXs, coordYs, pointerIds, 2070 display, seat); 2071 SystemClock.sleep(delayMs); 2072 injectMotionEvent(source, MotionEvent.ACTION_UP, coordXs, coordYs, pointerIds, 2073 display, seat); 2074 } else { 2075 injectMotionEvent(source, action, coordXs, coordYs, pointerIds, display, seat); 2076 } 2077 writer.println("Succeeded"); 2078 } 2079 2080 // value can be a hex or decimal string. 2081 private static int parseUnsignedInt(String value) { 2082 if (value.startsWith("0x")) { 2083 return Integer.parseUnsignedInt(value.substring(2), 16); 2084 } else { 2085 return Integer.parseUnsignedInt(value); 2086 } 2087 } 2088 2089 private static int getToolType(int inputSource) { 2090 switch(inputSource) { 2091 case InputDevice.SOURCE_MOUSE: 2092 case InputDevice.SOURCE_MOUSE_RELATIVE: 2093 case InputDevice.SOURCE_TRACKBALL: 2094 return MotionEvent.TOOL_TYPE_MOUSE; 2095 2096 case InputDevice.SOURCE_STYLUS: 2097 case InputDevice.SOURCE_BLUETOOTH_STYLUS: 2098 return MotionEvent.TOOL_TYPE_STYLUS; 2099 2100 case InputDevice.SOURCE_TOUCHPAD: 2101 case InputDevice.SOURCE_TOUCHSCREEN: 2102 case InputDevice.SOURCE_TOUCH_NAVIGATION: 2103 return MotionEvent.TOOL_TYPE_FINGER; 2104 } 2105 return MotionEvent.TOOL_TYPE_UNKNOWN; 2106 } 2107 2108 private static int getInputDeviceId(int inputSource) { 2109 int[] devIds = InputDevice.getDeviceIds(); 2110 for (int devId : devIds) { 2111 InputDevice inputDev = InputDevice.getDevice(devId); 2112 if (inputDev.supportsSource(inputSource)) { 2113 return devId; 2114 } 2115 } 2116 return DEFAULT_DEVICE_ID; 2117 } 2118 2119 private void injectMotionEvent(int source, int action, List<Float> xs, List<Float> ys, 2120 List<Integer> pointerIds, int display, int seat) { 2121 long currentTime = SystemClock.uptimeMillis(); 2122 if (action == MotionEvent.ACTION_DOWN) { 2123 mMotionDownTime = currentTime; 2124 } 2125 long token = Binder.clearCallingIdentity(); 2126 2127 int pointerCount = xs.size(); 2128 float pressure = NO_PRESSURE; 2129 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { 2130 pressure = DEFAULT_PRESSURE; 2131 } 2132 MotionEvent.PointerProperties[] pointerProperties = 2133 new MotionEvent.PointerProperties[pointerCount]; 2134 MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount]; 2135 int toolType = getToolType(source); 2136 for (int i = 0; i < pointerCount; i++) { 2137 pointerProperties[i] = new MotionEvent.PointerProperties(); 2138 pointerProperties[i].id = pointerIds.isEmpty() ? i : pointerIds.get(i); 2139 pointerProperties[i].toolType = toolType; 2140 pointerCoords[i] = new MotionEvent.PointerCoords(); 2141 pointerCoords[i].x = xs.get(i); 2142 pointerCoords[i].y = ys.get(i); 2143 pointerCoords[i].pressure = pressure; 2144 pointerCoords[i].size = DEFAULT_SIZE; 2145 } 2146 2147 MotionEvent event = MotionEvent.obtain( 2148 /* downTime= */ mMotionDownTime, 2149 /* when= */ currentTime, 2150 action, 2151 pointerCount, 2152 pointerProperties, 2153 pointerCoords, 2154 DEFAULT_META_STATE, 2155 DEFAULT_BUTTON_STATE, 2156 DEFAULT_PRECISION_X, 2157 DEFAULT_PRECISION_Y, 2158 getInputDeviceId(source), 2159 DEFAULT_EDGE_FLAGS, 2160 source, 2161 DEFAULT_FLAGS 2162 ); 2163 try { 2164 if (seat == SEAT_UNKNOWN) { 2165 // Overwrite with the driver seat 2166 seat = mCarOccupantZoneService.getDriverSeat(); 2167 } 2168 mCarInputService.injectMotionEventForSeat(event, display, seat); 2169 } finally { 2170 Binder.restoreCallingIdentity(token); 2171 } 2172 } 2173 2174 private void injectRotary(String[] args, IndentingPrintWriter writer) { 2175 int i = 1; // 0 is command itself 2176 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 2177 int inputType = CarInputManager.INPUT_TYPE_ROTARY_NAVIGATION; 2178 boolean clockwise = false; 2179 List<Long> deltaTimeMs = new ArrayList<>(); 2180 try { 2181 while (i < args.length) { 2182 switch (args[i]) { 2183 case "-d": 2184 i++; 2185 int vehicleDisplay = Integer.parseInt(args[i]); 2186 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 2187 return; 2188 } 2189 display = InputHalService.convertDisplayType(vehicleDisplay); 2190 break; 2191 case "-i": 2192 i++; 2193 inputType = Integer.parseInt(args[i]); 2194 break; 2195 case "-c": 2196 i++; 2197 clockwise = Boolean.parseBoolean(args[i]); 2198 break; 2199 case "-dt": 2200 i++; 2201 while (i < args.length) { 2202 deltaTimeMs.add(Long.parseLong(args[i])); 2203 i++; 2204 } 2205 break; 2206 default: 2207 writer.println("Invalid option at index " + i + ": " + args[i]); 2208 return; 2209 } 2210 i++; 2211 } 2212 } catch (NumberFormatException e) { 2213 writer.println("Invalid args:" + e); 2214 showHelp(writer); 2215 return; 2216 } 2217 if (deltaTimeMs.isEmpty()) { 2218 deltaTimeMs.add(0L); 2219 } 2220 for (int j = 0; j < deltaTimeMs.size(); j++) { 2221 if (deltaTimeMs.get(j) < 0) { 2222 writer.println("Delta time shouldn't be negative: " + deltaTimeMs.get(j)); 2223 showHelp(writer); 2224 return; 2225 } 2226 if (j > 0 && deltaTimeMs.get(j) > deltaTimeMs.get(j - 1)) { 2227 writer.println("Delta times should be in descending order"); 2228 showHelp(writer); 2229 return; 2230 } 2231 } 2232 long[] uptimeMs = new long[deltaTimeMs.size()]; 2233 long currentUptime = SystemClock.uptimeMillis(); 2234 for (int j = 0; j < deltaTimeMs.size(); j++) { 2235 uptimeMs[j] = currentUptime - deltaTimeMs.get(j); 2236 } 2237 RotaryEvent rotaryEvent = new RotaryEvent(inputType, clockwise, uptimeMs); 2238 mCarInputService.onRotaryEvent(rotaryEvent, display); 2239 writer.println("Succeeded in injecting: " + rotaryEvent); 2240 } 2241 2242 private void injectCustomInputEvent(String[] args, IndentingPrintWriter writer) { 2243 int display = CarOccupantZoneManager.DISPLAY_TYPE_MAIN; 2244 int repeatCounter = 1; 2245 2246 int argIdx = 1; 2247 for (; argIdx < args.length - 1; argIdx++) { 2248 switch (args[argIdx]) { 2249 case "-d": 2250 int vehicleDisplay = Integer.parseInt(args[++argIdx]); 2251 if (!checkVehicleDisplay(vehicleDisplay, writer)) { 2252 return; 2253 } 2254 display = InputHalService.convertDisplayType(vehicleDisplay); 2255 break; 2256 case "-r": 2257 repeatCounter = Integer.parseInt(args[++argIdx]); 2258 break; 2259 default: 2260 writer.printf("Unrecognized argument: {%s}\n", args[argIdx]); 2261 writer.println("Pass -help to see the full list of options"); 2262 return; 2263 } 2264 } 2265 2266 if (argIdx == args.length) { 2267 writer.println("Last mandatory argument (fn) not passed."); 2268 writer.println("Pass -help to see the full list of options"); 2269 return; 2270 } 2271 2272 // Processing the last remaining argument. Argument is expected one of the tem functions 2273 // ('f1', 'f2', ..., 'f10') or just a plain integer representing the custom input event. 2274 String eventValue = args[argIdx].toLowerCase(Locale.US); 2275 Integer inputCode; 2276 if (eventValue.startsWith("f")) { 2277 inputCode = CUSTOM_INPUT_FUNCTION_ARGS.get(eventValue); 2278 if (inputCode == null) { 2279 writer.printf("Invalid input event value {%s}, valid values are f1, f2, ..., f10\n", 2280 eventValue); 2281 writer.println("Pass -help to see the full list of options"); 2282 return; 2283 } 2284 } else { 2285 inputCode = Integer.parseInt(eventValue); 2286 } 2287 CustomInputEvent event = new CustomInputEvent(inputCode, display, repeatCounter); 2288 mCarInputService.onCustomInputEvent(event); 2289 writer.printf("Succeeded in injecting {%s}\n", event); 2290 } 2291 2292 private boolean checkVehicleDisplay(int vehicleDisplay, IndentingPrintWriter writer) { 2293 if (vehicleDisplay != VehicleDisplay.MAIN 2294 && vehicleDisplay != VehicleDisplay.INSTRUMENT_CLUSTER) { 2295 writer.println("Invalid display:" + vehicleDisplay); 2296 showHelp(writer); 2297 return false; 2298 } 2299 return true; 2300 } 2301 2302 private void getInitialUserInfo(String[] args, IndentingPrintWriter writer) { 2303 if (args.length < 2) { 2304 writer.println("Insufficient number of args"); 2305 return; 2306 } 2307 2308 // Gets the request type 2309 String typeArg = args[1]; 2310 int requestType = UserHalHelper.parseInitialUserInfoRequestType(typeArg); 2311 2312 int timeout = DEFAULT_HAL_TIMEOUT_MS; 2313 for (int i = 2; i < args.length; i++) { 2314 String arg = args[i]; 2315 switch (arg) { 2316 case "--timeout": 2317 timeout = Integer.parseInt(args[++i]); 2318 break; 2319 default: 2320 writer.println("Invalid option at index " + i + ": " + arg); 2321 return; 2322 2323 } 2324 } 2325 2326 Slogf.d(TAG, "handleGetInitialUserInfo(): type=" + requestType + " (" + typeArg 2327 + "), timeout=" + timeout); 2328 2329 CountDownLatch latch = new CountDownLatch(1); 2330 HalCallback<InitialUserInfoResponse> callback = (status, resp) -> { 2331 try { 2332 Slogf.d(TAG, "GetUserInfoResponse: status=" + status + ", resp=" + resp); 2333 writer.printf("Call status: %s\n", 2334 UserHalHelper.halCallbackStatusToString(status)); 2335 if (status != HalCallback.STATUS_OK) { 2336 return; 2337 } 2338 writer.printf("Request id: %d\n", resp.requestId); 2339 writer.printf("Action: %s\n", DebugUtils.constantToString( 2340 InitialUserInfoResponseAction.class, resp.action)); 2341 if (!TextUtils.isEmpty(resp.userNameToCreate)) { 2342 writer.printf("User name: %s\n", resp.userNameToCreate); 2343 } 2344 if (resp.userToSwitchOrCreate.userId != UserManagerHelper.USER_NULL) { 2345 writer.printf("User id: %d\n", resp.userToSwitchOrCreate.userId); 2346 } 2347 if (resp.userToSwitchOrCreate.flags != 0) { 2348 writer.printf("User flags: %s\n", 2349 UserHalHelper.userFlagsToString(resp.userToSwitchOrCreate.flags)); 2350 } 2351 if (!TextUtils.isEmpty(resp.userLocales)) { 2352 writer.printf("User locales: %s\n", resp.userLocales); 2353 } 2354 } finally { 2355 latch.countDown(); 2356 } 2357 }; 2358 2359 UsersInfo usersInfo = generateUsersInfo(); 2360 mHal.getUserHal().getInitialUserInfo(requestType, timeout, usersInfo, callback); 2361 waitForHal(writer, latch, timeout); 2362 } 2363 2364 private UsersInfo generateUsersInfo() { 2365 UserManager um = mContext.getSystemService(UserManager.class); 2366 UserHandleHelper userHandleHelper = new UserHandleHelper(mContext, um); 2367 return UserHalHelper.newUsersInfo(um, userHandleHelper); 2368 } 2369 2370 private int getUserHalFlags(@UserIdInt int userId) { 2371 UserManager um = mContext.getSystemService(UserManager.class); 2372 UserHandleHelper userHandleHelper = new UserHandleHelper(mContext, um); 2373 return UserHalHelper.getFlags(userHandleHelper, userId); 2374 } 2375 2376 private static void waitForHal(IndentingPrintWriter writer, CountDownLatch latch, 2377 int timeoutMs) { 2378 try { 2379 if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { 2380 writer.printf("HAL didn't respond in %dms\n", timeoutMs); 2381 } 2382 } catch (InterruptedException e) { 2383 Thread.currentThread().interrupt(); 2384 writer.println("Interrupted waiting for HAL"); 2385 } 2386 } 2387 2388 private void switchUser(String[] args, IndentingPrintWriter writer) { 2389 if (args.length < 2) { 2390 writer.println("Insufficient number of args"); 2391 return; 2392 } 2393 2394 int targetUserId = Integer.parseInt(args[1]); 2395 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 2396 boolean halOnly = false; 2397 boolean ignoreUxr = false; 2398 2399 for (int i = 2; i < args.length; i++) { 2400 String arg = args[i]; 2401 switch (arg) { 2402 case "--timeout": 2403 timeout = Integer.parseInt(args[++i]); 2404 break; 2405 case "--hal-only": 2406 halOnly = true; 2407 break; 2408 case "--ignore-uxr": 2409 ignoreUxr = true; 2410 break; 2411 default: 2412 writer.println("Invalid option at index " + i + ": " + arg); 2413 return; 2414 } 2415 } 2416 2417 Slogf.d(TAG, "switchUser(): target=" + targetUserId + ", halOnly=" + halOnly 2418 + ", timeout=" + timeout); 2419 2420 if (halOnly) { 2421 CountDownLatch latch = new CountDownLatch(1); 2422 UserHalService userHal = mHal.getUserHal(); 2423 UserInfo targetUserInfo = new UserInfo(); 2424 targetUserInfo.userId = targetUserId; 2425 targetUserInfo.flags = getUserHalFlags(targetUserId); 2426 2427 SwitchUserRequest request = UserHalHelper.emptySwitchUserRequest(); 2428 request.targetUser = targetUserInfo; 2429 request.usersInfo = generateUsersInfo(); 2430 2431 userHal.switchUser(request, timeout, (status, resp) -> { 2432 try { 2433 Slogf.d(TAG, "SwitchUserResponse: status=" + status + ", resp=" + resp); 2434 writer.printf("Call Status: %s\n", 2435 UserHalHelper.halCallbackStatusToString(status)); 2436 if (status != HalCallback.STATUS_OK) { 2437 return; 2438 } 2439 writer.printf("Request id: %d\n", resp.requestId); 2440 writer.printf("Message type: %s\n", DebugUtils.constantToString( 2441 SwitchUserMessageType.class, resp.messageType)); 2442 writer.printf("Switch Status: %s\n", DebugUtils.constantToString( 2443 SwitchUserStatus.class, resp.status)); 2444 String errorMessage = resp.errorMessage; 2445 if (!TextUtils.isEmpty(errorMessage)) { 2446 writer.printf("Error message: %s", errorMessage); 2447 } 2448 // If HAL returned OK, make a "post-switch" call to the HAL indicating an 2449 // Android error. This is to "rollback" the HAL switch. 2450 if (status == HalCallback.STATUS_OK 2451 && resp.status == SwitchUserStatus.SUCCESS) { 2452 userHal.postSwitchResponse(request); 2453 } 2454 } finally { 2455 latch.countDown(); 2456 } 2457 }); 2458 waitForHal(writer, latch, timeout); 2459 return; 2460 } 2461 CarUserManager carUserManager = getCarUserManager(mContext); 2462 2463 SyncResultCallback<UserSwitchResult> syncResultCallback = new SyncResultCallback<>(); 2464 2465 if (ignoreUxr) { 2466 carUserManager.switchUserIgnoringUxRestriction( 2467 new UserSwitchRequest.Builder(UserHandle.of(targetUserId)).build(), 2468 Runnable::run, syncResultCallback); 2469 2470 } else { 2471 carUserManager.switchUser( 2472 new UserSwitchRequest.Builder(UserHandle.of(targetUserId)).build(), 2473 Runnable::run, syncResultCallback); 2474 } 2475 2476 try { 2477 showUserSwitchResult(writer, syncResultCallback.get(timeout, TimeUnit.MILLISECONDS)); 2478 } catch (TimeoutException e) { 2479 writer.printf("UserSwitchResult: timed out waitng for result"); 2480 } catch (InterruptedException e) { 2481 writer.printf("UserSwitchResult: interrupted waitng for result"); 2482 Thread.currentThread().interrupt(); 2483 } 2484 } 2485 2486 private void showUserSwitchResult(IndentingPrintWriter writer, UserSwitchResult result) { 2487 if (result == null) return; 2488 writer.printf("UserSwitchResult: status=%s", 2489 UserSwitchResult.statusToString(result.getStatus())); 2490 String msg = result.getErrorMessage(); 2491 if (!TextUtils.isEmpty(msg)) { 2492 writer.printf(", errorMessage=%s", msg); 2493 } 2494 writer.println(); 2495 } 2496 2497 private void logoutUser(String[] args, IndentingPrintWriter writer) { 2498 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 2499 2500 if (args.length > 1) { 2501 for (int i = 1; i < args.length; i++) { 2502 String arg = args[i]; 2503 switch (arg) { 2504 case "--timeout": 2505 timeout = Integer.parseInt(args[++i]); 2506 break; 2507 default: 2508 writer.println("Invalid option at index " + i + ": " + arg); 2509 return; 2510 } 2511 } 2512 } 2513 2514 Slogf.d(TAG, "logoutUser(): timeout=%d", timeout); 2515 2516 CarUserManager carUserManager = getCarUserManager(mContext); 2517 AsyncFuture<UserSwitchResult> future = carUserManager.logoutUser(); 2518 UserSwitchResult result = waitForFuture(writer, future, timeout); 2519 showUserSwitchResult(writer, result); 2520 } 2521 2522 private void createUser(String[] args, IndentingPrintWriter writer) { 2523 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 2524 int flags = 0; 2525 boolean isGuest = false; 2526 boolean halOnly = false; 2527 String name = null; 2528 2529 for (int i = 1; i < args.length; i++) { 2530 String arg = args[i]; 2531 switch (arg) { 2532 case "--timeout": 2533 timeout = Integer.parseInt(args[++i]); 2534 break; 2535 case "--guest": 2536 isGuest = true; 2537 break; 2538 case "--hal-only": 2539 halOnly = true; 2540 break; 2541 case "--flags": 2542 flags = Integer.parseInt(args[++i]); 2543 break; 2544 case "--type": 2545 // print an error and quit. 2546 writer.printf("Error: --type is not supported. Use --guest to create a guest."); 2547 writer.println(); 2548 return; 2549 default: 2550 if (name != null) { 2551 writer.println("Invalid option at index " + i + ": " + arg); 2552 return; 2553 } 2554 name = arg; 2555 } 2556 } 2557 2558 Slogf.d(TAG, "createUser(): name=" + name 2559 + ", flags=" + flags 2560 + ", guest=" + isGuest + ", halOnly=" + halOnly + ", timeout=" + timeout); 2561 2562 if (!halOnly) { 2563 CarUserManager carUserManager = getCarUserManager(mContext); 2564 2565 SyncResultCallback<UserCreationResult> syncResultCallback = 2566 new SyncResultCallback<UserCreationResult>(); 2567 UserCreationRequest.Builder builder = new UserCreationRequest.Builder(); 2568 if (name != null) { 2569 builder.setName(name); 2570 } 2571 2572 if (isGuest) { 2573 builder.setGuest(); 2574 } 2575 2576 if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 2577 builder.setAdmin(); 2578 } 2579 2580 if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) { 2581 builder.setEphemeral(); 2582 } 2583 2584 carUserManager.createUser(builder.build(), Runnable::run, syncResultCallback); 2585 2586 UserCreationResult result; 2587 try { 2588 result = syncResultCallback.get(timeout, TimeUnit.MILLISECONDS); 2589 } catch (TimeoutException e) { 2590 writer.printf("UserCreationResult: Got Timeout Exception - %s", e); 2591 return; 2592 } catch (InterruptedException e) { 2593 Thread.currentThread().interrupt(); 2594 writer.printf("UserCreationResult: Got InterruptedException - %s", e); 2595 return; 2596 } 2597 2598 if (result == null) return; 2599 2600 UserHandle user = result.getUser(); 2601 // NOTE: must always show the id=%d, as it's used by CTS tests 2602 writer.printf("UserCreationResult: status=%s, user=%s, id=%d", 2603 UserCreationResult.statusToString(result.getStatus()), 2604 user == null ? "N/A" : user.toString(), 2605 user == null ? UserManagerHelper.USER_NULL : user.getIdentifier()); 2606 Integer androidFailureStatus = result.getAndroidFailureStatus(); 2607 if (androidFailureStatus != null) { 2608 writer.printf(", androidStatus=%s", DebugUtils.constantToString(UserManager.class, 2609 "USER_OPERATION_", androidFailureStatus)); 2610 } 2611 String msg = result.getErrorMessage(); 2612 if (!TextUtils.isEmpty(msg)) { 2613 writer.printf(", errorMessage=%s", msg); 2614 } 2615 String internalMsg = result.getInternalErrorMessage(); 2616 if (!TextUtils.isEmpty(internalMsg)) { 2617 writer.printf(", internalErrorMessage=%s", internalMsg); 2618 } 2619 writer.println(); 2620 return; 2621 } 2622 2623 CountDownLatch latch = new CountDownLatch(1); 2624 UserHalService userHal = mHal.getUserHal(); 2625 2626 CreateUserRequest request = UserHalHelper.emptyCreateUserRequest(); 2627 2628 UserManager um = mContext.getSystemService(UserManager.class); 2629 2630 NewUserRequest newUserRequest; 2631 try { 2632 newUserRequest = getCreateUserRequest(name, isGuest, flags); 2633 } catch (Exception e) { 2634 Slogf.e(TAG, e, "Error creating new user request. name: %s isGuest: %b and flags: %s", 2635 name, isGuest, flags); 2636 writer.println("Failed to create user"); 2637 return; 2638 } 2639 2640 NewUserResponse newUserResponse = um.createUser(newUserRequest); 2641 2642 if (!newUserResponse.isSuccessful()) { 2643 writer.printf("Failed to create user"); 2644 return; 2645 } 2646 2647 UserHandle newUser = newUserResponse.getUser(); 2648 2649 writer.printf("New user: %s\n", newUser); 2650 Slogf.i(TAG, "Created new user: " + newUser); 2651 2652 request.newUserInfo.userId = newUser.getIdentifier(); 2653 request.newUserInfo.flags = UserHalHelper.convertFlags(new UserHandleHelper(mContext, um), 2654 newUser); 2655 2656 request.usersInfo = generateUsersInfo(); 2657 2658 AtomicBoolean halOk = new AtomicBoolean(false); 2659 try { 2660 userHal.createUser(request, timeout, (status, resp) -> { 2661 Slogf.d(TAG, "CreateUserResponse: status=" + status + ", resp=" + resp); 2662 writer.printf("Call Status: %s\n", 2663 UserHalHelper.halCallbackStatusToString(status)); 2664 if (status == HalCallback.STATUS_OK) { 2665 halOk.set(resp.status == CreateUserStatus.SUCCESS); 2666 writer.printf("Request id: %d\n", resp.requestId); 2667 writer.printf("Create Status: %s\n", DebugUtils.constantToString( 2668 CreateUserStatus.class, resp.status)); 2669 String errorMessage = resp.errorMessage; 2670 if (!TextUtils.isEmpty(errorMessage)) { 2671 writer.printf("Error message: %s", errorMessage); 2672 } 2673 } 2674 latch.countDown(); 2675 }); 2676 waitForHal(writer, latch, timeout); 2677 } catch (RuntimeException e) { 2678 writer.printf("HAL failed: %s\n", e); 2679 } finally { 2680 if (!halOk.get()) { 2681 writer.printf("Removing user %d due to HAL failure\n", newUser.getIdentifier()); 2682 boolean removed = um.removeUser(newUser); 2683 writer.printf("User removed: %b\n", removed); 2684 } 2685 } 2686 } 2687 2688 private NewUserRequest getCreateUserRequest(String name, boolean isGuest, int flags) { 2689 NewUserRequest.Builder builder = new NewUserRequest.Builder().setName(name); 2690 if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 2691 builder.setAdmin(); 2692 } 2693 2694 if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) { 2695 builder.setEphemeral(); 2696 } 2697 2698 if (isGuest) { 2699 builder.setUserType(UserManager.USER_TYPE_FULL_GUEST); 2700 } 2701 2702 return builder.build(); 2703 } 2704 2705 private void removeUser(String[] args, IndentingPrintWriter writer) { 2706 if (args.length < 2) { 2707 writer.println("Insufficient number of args"); 2708 return; 2709 } 2710 2711 int userId = Integer.parseInt(args[1]); 2712 int timeout = DEFAULT_HAL_TIMEOUT_MS + DEFAULT_CAR_USER_SERVICE_TIMEOUT_MS; 2713 boolean halOnly = false; 2714 2715 for (int i = 2; i < args.length; i++) { 2716 String arg = args[i]; 2717 switch (arg) { 2718 case "--hal-only": 2719 halOnly = true; 2720 break; 2721 default: 2722 writer.println("Invalid option at index " + i + ": " + arg); 2723 return; 2724 } 2725 } 2726 2727 Slogf.d(TAG, "handleRemoveUser(): User to remove=" + userId + ", halOnly=" + halOnly); 2728 2729 if (halOnly) { 2730 UserHalService userHal = mHal.getUserHal(); 2731 UsersInfo usersInfo = generateUsersInfo(); 2732 UserInfo userInfo = new UserInfo(); 2733 userInfo.userId = userId; 2734 userInfo.flags = getUserHalFlags(userId); 2735 2736 RemoveUserRequest request = UserHalHelper.emptyRemoveUserRequest(); 2737 request.removedUserInfo = userInfo; 2738 request.usersInfo = usersInfo; 2739 2740 userHal.removeUser(request); 2741 writer.printf("User removal sent for HAL only.\n"); 2742 return; 2743 } 2744 2745 CarUserManager carUserManager = getCarUserManager(mContext); 2746 SyncResultCallback<UserRemovalResult> syncResultCallback = new SyncResultCallback<>(); 2747 carUserManager.removeUser(new UserRemovalRequest.Builder( 2748 UserHandle.of(userId)).build(), Runnable::run, syncResultCallback); 2749 try { 2750 UserRemovalResult result = syncResultCallback.get(timeout, TimeUnit.MILLISECONDS); 2751 writer.printf("UserRemovalResult: status = %s\n", 2752 UserRemovalResult.statusToString(result.getStatus())); 2753 } catch (TimeoutException e) { 2754 writer.printf("UserRemovalResult: timed out waitng for result"); 2755 } catch (InterruptedException e) { 2756 writer.printf("UserRemovalResult: interrupted waitng for result"); 2757 Thread.currentThread().interrupt(); 2758 } 2759 } 2760 2761 private static <T> T waitForFuture(IndentingPrintWriter writer, 2762 AsyncFuture<T> future, int timeoutMs) { 2763 T result = null; 2764 try { 2765 result = future.get(timeoutMs, TimeUnit.MILLISECONDS); 2766 if (result == null) { 2767 writer.printf("Service didn't respond in %d ms", timeoutMs); 2768 } 2769 } catch (InterruptedException e) { 2770 Thread.currentThread().interrupt(); 2771 } catch (ExecutionException | TimeoutException e) { 2772 writer.printf("Exception getting future: %s", e); 2773 } 2774 return result; 2775 } 2776 2777 private void getInitialUser(IndentingPrintWriter writer) { 2778 UserHandle user = mCarUserService.getInitialUser(); 2779 writer.println(user == null ? NO_INITIAL_USER : user.getIdentifier()); 2780 } 2781 2782 private void getUserAuthAssociation(String[] args, IndentingPrintWriter writer) { 2783 if (args.length < 2) { 2784 writer.println("invalid usage, must pass at least 1 argument"); 2785 return; 2786 } 2787 2788 boolean halOnly = false; 2789 int userId = UserHandle.CURRENT.getIdentifier(); 2790 2791 UserIdentificationGetRequest request = UserHalHelper.emptyUserIdentificationGetRequest(); 2792 ArrayList<Integer> associationTypes = new ArrayList<>(); 2793 for (int i = 1; i < args.length; i++) { 2794 String arg = args[i]; 2795 switch (arg) { 2796 case "--user": 2797 try { 2798 userId = Integer.parseInt(args[++i]); 2799 } catch (NumberFormatException e) { 2800 writer.printf("Invalid user id at index %d (from %s): %s\n", i + 1, 2801 Arrays.toString(args), arg); 2802 } 2803 break; 2804 case "--hal-only": 2805 halOnly = true; 2806 break; 2807 default: 2808 int type = parseAuthArg(VALID_USER_AUTH_TYPES, arg); 2809 if (type == INVALID_USER_AUTH_TYPE_OR_VALUE) { 2810 writer.printf("Invalid type at index %d (from %s): %s. %s\n", i + 1, 2811 Arrays.toString(args), arg, VALID_USER_AUTH_TYPES_HELP); 2812 return; 2813 } 2814 associationTypes.add(type); 2815 } 2816 } 2817 request.associationTypes = toIntArray(associationTypes); 2818 if (userId == UserHandle.CURRENT.getIdentifier()) { 2819 userId = ActivityManager.getCurrentUser(); 2820 } 2821 int requestSize = request.associationTypes.length; 2822 if (halOnly) { 2823 request.numberAssociationTypes = requestSize; 2824 request.userInfo.userId = userId; 2825 request.userInfo.flags = getUserHalFlags(userId); 2826 2827 Slogf.d(TAG, "getUserAuthAssociation(): user=" + userId + ", halOnly=" + halOnly 2828 + ", request=" + request); 2829 UserIdentificationResponse response = mHal.getUserHal().getUserAssociation(request); 2830 Slogf.d(TAG, "getUserAuthAssociation(): response=" + response); 2831 showResponse(writer, response); 2832 return; 2833 } 2834 2835 CarUserManager carUserManager = getCarUserManager(writer, userId); 2836 int[] types = new int[requestSize]; 2837 for (int i = 0; i < requestSize; i++) { 2838 types[i] = request.associationTypes[i]; 2839 } 2840 UserIdentificationAssociationResponse response = carUserManager 2841 .getUserIdentificationAssociation(types); 2842 showResponse(writer, response); 2843 } 2844 2845 private CarUserManager getCarUserManager(IndentingPrintWriter writer, 2846 @UserIdInt int userId) { 2847 Context context = getContextForUser(userId); 2848 int actualUserId = Binder.getCallingUid(); 2849 if (actualUserId != userId) { 2850 writer.printf("Emulating call for user id %d, but caller's user id is %d, so that's " 2851 + "what CarUserService will use when calling HAL.\n", userId, actualUserId); 2852 } 2853 2854 return getCarUserManager(context); 2855 } 2856 2857 private Context getContextForUser(int userId) { 2858 if (userId == mContext.getUser().getIdentifier()) { 2859 return mContext; 2860 } 2861 return mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0); 2862 } 2863 2864 private CarUserManager getCarUserManager(Context context) { 2865 Car car = Car.createCar(context); 2866 CarUserManager carUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE); 2867 return carUserManager; 2868 } 2869 2870 private void showResponse( 2871 IndentingPrintWriter writer, UserIdentificationResponse response) { 2872 if (response == null) { 2873 writer.println("null response"); 2874 return; 2875 } 2876 2877 if (!TextUtils.isEmpty(response.errorMessage)) { 2878 writer.printf("Error message: %s\n", response.errorMessage); 2879 } 2880 int numberAssociations = response.associations.length; 2881 writer.printf("%d associations:\n", numberAssociations); 2882 for (int i = 0; i < numberAssociations; i++) { 2883 UserIdentificationAssociation association = response.associations[i]; 2884 writer.printf(" %s\n", association); 2885 } 2886 } 2887 2888 private void showResponse(IndentingPrintWriter writer, 2889 UserIdentificationAssociationResponse response) { 2890 if (response == null) { 2891 writer.println("null response"); 2892 return; 2893 } 2894 if (!response.isSuccess()) { 2895 writer.printf("failed response: %s\n", response); 2896 return; 2897 } 2898 String errorMessage = response.getErrorMessage(); 2899 if (!TextUtils.isEmpty(errorMessage)) { 2900 writer.printf("Error message: %s\n", errorMessage); 2901 } 2902 int[] values = response.getValues(); 2903 if (values == null) { 2904 writer.printf("no associations on %s\n", response); 2905 return; 2906 } 2907 writer.printf("%d associations:\n", values.length); 2908 for (int i = 0; i < values.length; i++) { 2909 writer.printf(" %s\n", DebugUtils.constantToString( 2910 UserIdentificationAssociationValue.class, values[i])); 2911 } 2912 } 2913 2914 private void setUserAuthAssociation(String[] args, IndentingPrintWriter writer) { 2915 if (args.length < 3) { 2916 writer.println("invalid usage, must pass at least 4 arguments"); 2917 return; 2918 } 2919 2920 boolean halOnly = false; 2921 int timeout = DEFAULT_HAL_TIMEOUT_MS; 2922 int userId = UserHandle.CURRENT.getIdentifier(); 2923 2924 UserIdentificationSetRequest request = UserHalHelper.emptyUserIdentificationSetRequest(); 2925 ArrayList<UserIdentificationSetAssociation> associations = new ArrayList<>(); 2926 for (int i = 1; i < args.length; i++) { 2927 String arg = args[i]; 2928 switch (arg) { 2929 case "--user": 2930 try { 2931 userId = Integer.parseInt(args[++i]); 2932 } catch (NumberFormatException e) { 2933 writer.printf("Invalid user id at index %d (from %s): %s\n", i + 1, 2934 Arrays.toString(args), arg); 2935 } 2936 break; 2937 case "--hal-only": 2938 halOnly = true; 2939 break; 2940 case "--timeout": 2941 timeout = Integer.parseInt(args[++i]); 2942 break; 2943 default: 2944 UserIdentificationSetAssociation association = 2945 new UserIdentificationSetAssociation(); 2946 association.type = parseAuthArg(VALID_USER_AUTH_TYPES, arg); 2947 if (association.type == INVALID_USER_AUTH_TYPE_OR_VALUE) { 2948 writer.printf("Invalid type at index %d (from %s): %s. %s\n", i + 1, 2949 Arrays.toString(args), arg, VALID_USER_AUTH_TYPES_HELP); 2950 return; 2951 } 2952 association.value = parseAuthArg(VALID_USER_AUTH_SET_VALUES, args[++i]); 2953 if (association.value == INVALID_USER_AUTH_TYPE_OR_VALUE) { 2954 writer.printf("Invalid value at index %d (from %s): %s. %s\n", i + 1, 2955 Arrays.toString(args), arg, VALID_USER_AUTH_SET_VALUES_HELP); 2956 return; 2957 } 2958 associations.add(association); 2959 } 2960 } 2961 int requestSize = associations.size(); 2962 request.associations = associations.toArray( 2963 new UserIdentificationSetAssociation[requestSize]); 2964 2965 if (userId == UserHandle.CURRENT.getIdentifier()) { 2966 userId = ActivityManager.getCurrentUser(); 2967 } 2968 if (halOnly) { 2969 request.numberAssociations = requestSize; 2970 request.userInfo.userId = userId; 2971 request.userInfo.flags = getUserHalFlags(userId); 2972 2973 Slogf.d(TAG, "setUserAuthAssociation(): user=" + userId + ", halOnly=" + halOnly 2974 + ", request=" + request); 2975 CountDownLatch latch = new CountDownLatch(1); 2976 mHal.getUserHal().setUserAssociation(timeout, request, (status, response) -> { 2977 Slogf.d(TAG, "setUserAuthAssociation(): response=" + response); 2978 try { 2979 showResponse(writer, response); 2980 } finally { 2981 latch.countDown(); 2982 } 2983 }); 2984 waitForHal(writer, latch, timeout); 2985 return; 2986 } 2987 CarUserManager carUserManager = getCarUserManager(writer, userId); 2988 int[] types = new int[requestSize]; 2989 int[] values = new int[requestSize]; 2990 for (int i = 0; i < requestSize; i++) { 2991 UserIdentificationSetAssociation association = request.associations[i]; 2992 types[i] = association.type; 2993 values[i] = association.value; 2994 } 2995 AsyncFuture<UserIdentificationAssociationResponse> future = carUserManager 2996 .setUserIdentificationAssociation(types, values); 2997 UserIdentificationAssociationResponse response = waitForFuture(writer, future, timeout); 2998 if (response != null) { 2999 showResponse(writer, response); 3000 } 3001 } 3002 3003 private static int parseAuthArg(SparseArray<String> types, String type) { 3004 for (int i = 0; i < types.size(); i++) { 3005 if (types.valueAt(i).equals(type)) { 3006 return types.keyAt(i); 3007 } 3008 } 3009 return INVALID_USER_AUTH_TYPE_OR_VALUE; 3010 } 3011 3012 private void forceDayNightMode(String arg, IndentingPrintWriter writer) { 3013 int mode; 3014 switch (arg) { 3015 case PARAM_DAY_MODE: 3016 mode = CarNightService.FORCED_DAY_MODE; 3017 break; 3018 case PARAM_NIGHT_MODE: 3019 mode = CarNightService.FORCED_NIGHT_MODE; 3020 break; 3021 case PARAM_SENSOR_MODE: 3022 mode = CarNightService.FORCED_SENSOR_MODE; 3023 break; 3024 default: 3025 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s\n", 3026 arg, PARAM_DAY_MODE, PARAM_NIGHT_MODE, PARAM_SENSOR_MODE); 3027 return; 3028 } 3029 if (Flags.carNightGlobalSetting()) { 3030 Settings.Global.putInt(mContext.getContentResolver(), FORCED_DAY_NIGHT_MODE, mode); 3031 writer.println("DayNightMode changed to: " + arg); 3032 } else { 3033 int current = mCarNightService.forceDayNightMode(mode); 3034 String currentMode = null; 3035 switch (current) { 3036 case UiModeManager.MODE_NIGHT_AUTO: 3037 currentMode = PARAM_SENSOR_MODE; 3038 break; 3039 case UiModeManager.MODE_NIGHT_YES: 3040 currentMode = PARAM_NIGHT_MODE; 3041 break; 3042 case UiModeManager.MODE_NIGHT_NO: 3043 currentMode = PARAM_DAY_MODE; 3044 break; 3045 default: 3046 break; 3047 } 3048 writer.println("DayNightMode changed to: " + currentMode); 3049 } 3050 } 3051 3052 private void runSuspendCommand(String[] args, IndentingPrintWriter writer) { 3053 // args[0] is always either COMMAND_SUSPEND or COMMAND_HIBERNE. 3054 String command = args[0]; 3055 boolean isHibernation = Objects.equals(command, COMMAND_HIBERNATE); 3056 // Default is --auto, so simulate is decided based on device capability. 3057 boolean simulate = !mCarPowerManagementService.isSuspendAvailable(isHibernation); 3058 boolean modeSet = false; 3059 boolean skipGarageMode = false; 3060 boolean freeMemory = false; 3061 int resumeDelay = CarPowerManagementService.NO_WAKEUP_BY_TIMER; 3062 int cancelDelay = CarPowerManagementService.NO_WAKEUP_BY_TIMER; 3063 int index = 1; 3064 while (index < args.length) { 3065 switch (args[index]) { 3066 case PARAM_SIMULATE: 3067 if (modeSet) { 3068 writer.printf("Invalid command syntax.\nUsage: %s\n", 3069 getSuspendCommandUsage(command)); 3070 return; 3071 } 3072 simulate = true; 3073 modeSet = true; 3074 break; 3075 case PARAM_AUTO: 3076 if (modeSet) { 3077 writer.printf("Invalid command syntax.\nUsage: %s\n", 3078 getSuspendCommandUsage(command)); 3079 return; 3080 } 3081 simulate = !mCarPowerManagementService.isSuspendAvailable(isHibernation); 3082 modeSet = true; 3083 break; 3084 case PARAM_REAL: 3085 if (modeSet) { 3086 writer.printf("Invalid command syntax.\nUsage: %s\n", 3087 getSuspendCommandUsage(command)); 3088 return; 3089 } 3090 simulate = false; 3091 modeSet = true; 3092 break; 3093 case PARAM_SKIP_GARAGEMODE: 3094 skipGarageMode = true; 3095 break; 3096 case PARAM_WAKEUP_AFTER: 3097 index++; 3098 if (index >= args.length) { 3099 writer.printf("Invalid command syntax.\nUsage: %s\n", 3100 getSuspendCommandUsage(command)); 3101 return; 3102 } 3103 resumeDelay = Integer.parseInt(args[index]); 3104 break; 3105 case PARAM_CANCEL_AFTER: 3106 index++; 3107 if (index >= args.length) { 3108 writer.printf("Invalid command syntax.\nUsage: %s\n", 3109 getSuspendCommandUsage(command)); 3110 return; 3111 } 3112 cancelDelay = Integer.parseInt(args[index]); 3113 break; 3114 case PARAM_FREE_MEMORY: 3115 freeMemory = true; 3116 break; 3117 default: 3118 writer.printf("Invalid command syntax.\nUsage: %s\n", 3119 getSuspendCommandUsage(command)); 3120 return; 3121 } 3122 index++; 3123 } 3124 if ((cancelDelay >= 0 || resumeDelay >= 0) && !simulate) { 3125 writer.printf("Wake up and cancel by timer is available only with simulated suspend." 3126 + "\n"); 3127 return; 3128 } 3129 3130 if (cancelDelay >= 0 && resumeDelay >= 0 && simulate) { 3131 writer.printf("Cancel and resume cannot be set at the same time.\n"); 3132 return; 3133 } 3134 3135 if (freeMemory && !simulate) { 3136 writer.printf("Free memory can be used only with simulated hibernation.\n"); 3137 return; 3138 } 3139 3140 String suspendType = isHibernation ? "disk" : "RAM"; 3141 if (simulate) { 3142 try { 3143 writer.printf("Suspend: simulating suspend-to-%s.\n", suspendType); 3144 if (Flags.carPowerCancelShellCommand()) { 3145 mCarPowerManagementService.simulateSuspendAndMaybeReboot( 3146 isHibernation ? PowerHalService.PowerState.SHUTDOWN_TYPE_HIBERNATION 3147 : PowerHalService.PowerState.SHUTDOWN_TYPE_DEEP_SLEEP, 3148 /* shouldReboot= */ false, skipGarageMode, resumeDelay, cancelDelay, 3149 freeMemory); 3150 } else { 3151 mCarPowerManagementService.simulateSuspendAndMaybeReboot( 3152 isHibernation ? PowerHalService.PowerState.SHUTDOWN_TYPE_HIBERNATION 3153 : PowerHalService.PowerState.SHUTDOWN_TYPE_DEEP_SLEEP, 3154 /* shouldReboot= */ false, skipGarageMode, resumeDelay, freeMemory); 3155 } 3156 } catch (Exception e) { 3157 writer.printf("Simulating suspend-to-%s failed: %s\n", suspendType, e.getMessage()); 3158 } 3159 } else { 3160 try { 3161 mCarPowerManagementService.suspendFromCommand(isHibernation, skipGarageMode); 3162 } catch (Exception e) { 3163 writer.printf("Suspend to %s failed: %s.\n", suspendType, e.getMessage()); 3164 } 3165 } 3166 } 3167 3168 private void forceGarageMode(String arg, IndentingPrintWriter writer) { 3169 switch (arg) { 3170 case PARAM_ON_MODE: 3171 mSystemInterface.setAllDisplayState(false); 3172 mGarageModeService.forceStartGarageMode(); 3173 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 3174 break; 3175 case PARAM_OFF_MODE: 3176 mSystemInterface.setAllDisplayState(true); 3177 mGarageModeService.stopAndResetGarageMode(); 3178 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 3179 break; 3180 case PARAM_QUERY_MODE: 3181 mGarageModeService.dump(writer); 3182 break; 3183 case PARAM_REBOOT_AFTER_GARAGEMODE: 3184 writer.printf("\"cmd car_service garagemode reboot\" is deprecated. Use " 3185 + "\"cmd car_service power-off --reboot\" next time"); 3186 try { 3187 mCarPowerManagementService.powerOffFromCommand(/*skipGarageMode= */ false, 3188 /* reboot= */ true); 3189 writer.println("Entering Garage Mode. Will reboot when it completes."); 3190 } catch (IllegalStateException e) { 3191 writer.printf("Entering Garage Mode failed: %s\n", e.getMessage()); 3192 } 3193 break; 3194 default: 3195 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s|%s\n", 3196 arg, PARAM_ON_MODE, PARAM_OFF_MODE, PARAM_QUERY_MODE, 3197 PARAM_REBOOT_AFTER_GARAGEMODE); 3198 } 3199 } 3200 3201 private void runSilentCommand(String arg, IndentingPrintWriter writer) { 3202 switch (arg) { 3203 case SILENT_MODE_FORCED_SILENT: 3204 writer.println("Forcing silent mode to silent"); 3205 mCarPowerManagementService.setSilentMode(SILENT_MODE_FORCED_SILENT); 3206 break; 3207 case SILENT_MODE_FORCED_NON_SILENT: 3208 writer.println("Forcing silent mode to non-silent"); 3209 mCarPowerManagementService.setSilentMode(SILENT_MODE_FORCED_NON_SILENT); 3210 break; 3211 case SILENT_MODE_NON_FORCED: 3212 writer.println("Not forcing silent mode"); 3213 mCarPowerManagementService.setSilentMode(SILENT_MODE_NON_FORCED); 3214 break; 3215 case PARAM_QUERY_MODE: 3216 mCarPowerManagementService.dumpSilentMode(writer); 3217 break; 3218 default: 3219 writer.printf("Unknown value: %s. Valid argument: %s|%s|%s|%s\n", arg, 3220 SILENT_MODE_FORCED_SILENT, SILENT_MODE_FORCED_NON_SILENT, 3221 SILENT_MODE_NON_FORCED, PARAM_QUERY_MODE); 3222 } 3223 } 3224 3225 private void emulateDrivingState(String[] args, IndentingPrintWriter writer) { 3226 if (args.length != 2) { 3227 writer.println("invalid usage, must pass driving state"); 3228 return; 3229 } 3230 String mode = args[1]; 3231 switch (mode) { 3232 case DRIVING_STATE_DRIVE: 3233 emulateDrive(); 3234 break; 3235 case DRIVING_STATE_PARK: 3236 emulatePark(); 3237 break; 3238 case DRIVING_STATE_REVERSE: 3239 emulateReverse(); 3240 break; 3241 case DRIVING_STATE_NEUTRAL: 3242 emulateNeutral(); 3243 break; 3244 default: 3245 writer.printf("invalid driving mode %s; must be %s or %s\n", mode, 3246 DRIVING_STATE_DRIVE, DRIVING_STATE_PARK); 3247 } 3248 } 3249 3250 private void getDrivingState(IndentingPrintWriter writer) { 3251 CarDrivingStateService service = 3252 (CarDrivingStateService) mAllServicesByClazz.get(CarDrivingStateService.class); 3253 int driveState = service.getCurrentDrivingState().eventValue; 3254 3255 switch (driveState) { 3256 case CarDrivingStateEvent.DRIVING_STATE_PARKED: 3257 writer.println("Parked"); 3258 break; 3259 case CarDrivingStateEvent.DRIVING_STATE_IDLING: 3260 writer.println("Idling"); 3261 break; 3262 case CarDrivingStateEvent.DRIVING_STATE_MOVING: 3263 writer.println("Moving"); 3264 break; 3265 default: 3266 writer.println("Unknown"); 3267 } 3268 } 3269 3270 /** 3271 * Emulates driving mode. Called by 3272 * {@code adb shell cmd car_service emulate-driving-state drive}. 3273 */ 3274 private void emulateDrive() { 3275 Slogf.i(TAG, "Emulating driving mode (speed=80mph, gear=8)"); 3276 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 3277 /* areaId= */ 0, /* value= */ "80", /* delayTimeSeconds= */ 2000); 3278 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 3279 /* areaId= */ 0, Integer.toString(VehicleGear.GEAR_8), /* delayTimeSeconds= */ 0); 3280 mHal.injectVhalEvent(VehiclePropertyIds.PARKING_BRAKE_ON, 3281 /* areaId= */ 0, /* value= */ "false", /* delayTimeSeconds= */ 0); 3282 } 3283 3284 /** 3285 * Emulates reverse driving mode. Called by 3286 * {@code adb shell cmd car_service emulate-driving-state reverse}. 3287 */ 3288 private void emulateReverse() { 3289 Slogf.i(TAG, "Emulating reverse driving mode (speed=5mph)"); 3290 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 3291 /* areaId= */ 0, /* value= */ "5", /* delayTimeSeconds= */ 2000); 3292 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 3293 /* areaId= */ 0, Integer.toString(VehicleGear.GEAR_REVERSE), 3294 /* delayTimeSeconds= */ 0); 3295 mHal.injectVhalEvent(VehiclePropertyIds.PARKING_BRAKE_ON, 3296 /* areaId= */ 0, /* value= */ "false", /* delayTimeSeconds= */ 0); 3297 } 3298 3299 /** 3300 * Emulates parking mode. Called by 3301 * {@code adb shell cmd car_service emulate-driving-state park}. 3302 */ 3303 private void emulatePark() { 3304 Slogf.i(TAG, "Emulating parking mode"); 3305 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 3306 /* areaId= */ 0, /* value= */ "0", /* delayTimeSeconds= */ 0); 3307 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 3308 /* areaId= */ 0, Integer.toString(VehicleGear.GEAR_PARK), 3309 /* delayTimeSeconds= */ 0); 3310 } 3311 3312 /** 3313 * Emulates neutral driving state. Called by 3314 * {@code adb shell cmd car_service emulate-driving-state neutral}. 3315 */ 3316 private void emulateNeutral() { 3317 Slogf.i(TAG, "Emulating neutral driving mode"); 3318 mHal.injectVhalEvent(VehiclePropertyIds.PERF_VEHICLE_SPEED, 3319 /* areaId= */ 0, /* value= */ "0", /* delayTimeSeconds= */ 0); 3320 mHal.injectVhalEvent(VehiclePropertyIds.GEAR_SELECTION, 3321 /* areaId= */ 0, Integer.toString(VehicleGear.GEAR_NEUTRAL), 3322 /* delayTimeSeconds= */ 0); 3323 mHal.injectVhalEvent(VehiclePropertyIds.PARKING_BRAKE_ON, 3324 /* areaId= */ 0, /* value= */ "true", /* delayTimeSeconds= */ 0); 3325 } 3326 3327 private int definePowerPolicy(String[] args, IndentingPrintWriter writer) { 3328 boolean result = mCarPowerManagementService.definePowerPolicyFromCommand(args, writer); 3329 if (result) return RESULT_OK; 3330 writer.printf("\nUsage: cmd car_service %s <POLICY_ID> [--enable COMP1,COMP2,...] " 3331 + "[--disable COMP1,COMP2,...]\n", COMMAND_DEFINE_POWER_POLICY); 3332 return RESULT_ERROR; 3333 } 3334 3335 private int applyPowerPolicy(String[] args, IndentingPrintWriter writer) { 3336 boolean result = mCarPowerManagementService.applyPowerPolicyFromCommand(args, writer); 3337 if (result) return RESULT_OK; 3338 writer.printf("\nUsage: cmd car_service %s <POLICY_ID>\n", COMMAND_APPLY_POWER_POLICY); 3339 return RESULT_ERROR; 3340 } 3341 3342 private int definePowerPolicyGroup(String[] args, IndentingPrintWriter writer) { 3343 boolean result = mCarPowerManagementService.definePowerPolicyGroupFromCommand(args, writer); 3344 if (result) return RESULT_OK; 3345 writer.printf("\nUsage: cmd car_service %s <POLICY_GROUP_ID> [%s:<POLICY_ID>] " 3346 + "[%s:<POLICY_ID>]\n", COMMAND_DEFINE_POWER_POLICY_GROUP, 3347 POWER_STATE_WAIT_FOR_VHAL, POWER_STATE_ON); 3348 return RESULT_ERROR; 3349 } 3350 3351 private int setPowerPolicyGroup(String[] args, IndentingPrintWriter writer) { 3352 boolean result = mCarPowerManagementService.setPowerPolicyGroupFromCommand(args, writer); 3353 if (result) return RESULT_OK; 3354 writer.printf("\nUsage: cmd car_service %s <POLICY_GROUP_ID>\n", 3355 COMMAND_SET_POWER_POLICY_GROUP); 3356 return RESULT_ERROR; 3357 } 3358 3359 private void getCurrentPowerPolicy(IndentingPrintWriter writer) { 3360 CarPowerPolicy powerPolicy = mCarPowerManagementService.getCurrentPowerPolicy(); 3361 writer.printf("Current power policy is: %s", powerPolicy); 3362 } 3363 3364 private int applyCtsVerifierPowerPolicy(String policyId, String ops, String cmdName, 3365 IndentingPrintWriter writer) { 3366 String[] defArgs = {"define-power-policy", policyId, ops, "WIFI,BLUETOOTH,LOCATION"}; 3367 mCarPowerManagementService.definePowerPolicyFromCommand(defArgs, writer); 3368 3369 String[] appArgs = {"apply-power-policy", policyId}; 3370 boolean result = mCarPowerManagementService.applyPowerPolicyFromCommand(appArgs, writer); 3371 if (result) return RESULT_OK; 3372 3373 writer.printf("\nUsage: cmd car_service %s\n", cmdName); 3374 return RESULT_ERROR; 3375 } 3376 3377 private int applyCtsVerifierPowerOffPolicy(String[] unusedArgs, IndentingPrintWriter writer) { 3378 return applyCtsVerifierPowerPolicy("cts_verifier_off", "--disable", 3379 COMMAND_APPLY_CTS_VERIFIER_POWER_OFF_POLICY, writer); 3380 } 3381 3382 private int applyCtsVerifierPowerOnPolicy(String[] unusedArgs, IndentingPrintWriter writer) { 3383 return applyCtsVerifierPowerPolicy("cts_verifier_on", "--enable", 3384 COMMAND_APPLY_CTS_VERIFIER_POWER_ON_POLICY, writer); 3385 } 3386 3387 private void powerOff(String[] args, IndentingPrintWriter writer) { 3388 boolean skipGarageMode = false; 3389 boolean reboot = false; 3390 int index = 1; 3391 while (index < args.length) { 3392 switch (args[index]) { 3393 case PARAM_SKIP_GARAGEMODE: 3394 skipGarageMode = true; 3395 break; 3396 case PARAM_REBOOT: 3397 reboot = true; 3398 break; 3399 default: 3400 writer.printf("Invalid usage: %s [%s] [%s]\n", COMMAND_POWER_OFF, 3401 PARAM_SKIP_GARAGEMODE, PARAM_REBOOT); 3402 return; 3403 } 3404 index++; 3405 } 3406 mCarPowerManagementService.powerOffFromCommand(skipGarageMode, reboot); 3407 } 3408 3409 /** 3410 * Get config for VHAL property 3411 * 3412 * @param args the command line arguments to parse for VHAL property details 3413 * @param writer IndentingPrintWriter 3414 */ 3415 private void getCarPropertyConfig(String[] args, IndentingPrintWriter writer) { 3416 String propertyIdString = args.length < 2 ? PARAM_ALL_PROPERTIES_OR_AREA_IDS : args[1]; 3417 mHal.dumpPropertyConfigs(writer, decodePropertyId(propertyIdString)); 3418 } 3419 3420 /** 3421 * Get current value for VHAL property 3422 * 3423 * @param args the command line arguments to parse for VHAL property details 3424 * @param writer IndentingPrintWriter 3425 */ 3426 private void getPropertyValue(String[] args, IndentingPrintWriter writer) { 3427 String propertyIdString = 3428 args.length < 2 ? PARAM_ALL_PROPERTIES_OR_AREA_IDS : args[1]; 3429 String areaIdString = args.length < 3 ? PARAM_ALL_PROPERTIES_OR_AREA_IDS : args[2]; 3430 mHal.dumpPropertyValueByCommand(writer, decodePropertyId(propertyIdString), 3431 decodeAreaId(areaIdString)); 3432 } 3433 /** 3434 * Inject a fake VHAL event 3435 * 3436 * @param args the command line arguments to parse for VHAL event details 3437 * @param writer IndentingPrintWriter 3438 */ 3439 private void injectVhalEvent(String[] args, IndentingPrintWriter writer) { 3440 int argNum = args.length; 3441 if (argNum < 3 || argNum > 6) { 3442 showInvalidArguments(writer); 3443 return; 3444 } 3445 int propertyId = decodePropertyId(args[1]); 3446 String delayTimeSeconds = Objects.equals(args[argNum - 2], "-t") ? args[argNum - 1] : "0"; 3447 int areaId; 3448 String value; 3449 if (argNum == 4 || argNum == 6) { 3450 areaId = decodeAreaId(args[2]); 3451 value = args[3]; 3452 } else { 3453 // area ID is not specified, assume global area ID 3454 if (!isPropertyAreaTypeGlobal(propertyId)) { 3455 writer.println("Property " + toPropertyIdString(propertyId) 3456 + " is not a global area type property. The area ID must be specified. " 3457 + "Skipping injection."); 3458 return; 3459 } 3460 areaId = 0; 3461 value = args[2]; 3462 } 3463 String debugOutput = "Injecting VHAL event: property=" + toPropertyIdString(propertyId) 3464 + ", areaId=" + toAreaIdString(propertyId, areaId) + ", value=" + value + ( 3465 TextUtils.isEmpty(delayTimeSeconds) ? "" 3466 : ", delayTimeSeconds=" + delayTimeSeconds); 3467 Slogf.i(TAG, debugOutput); 3468 writer.println(debugOutput); 3469 mHal.injectVhalEvent(propertyId, areaId, value, Integer.decode(delayTimeSeconds)); 3470 } 3471 3472 /** 3473 * Inject a fake VHAL error error event 3474 * 3475 * @param args the command line arguments to parse for error event details 3476 * @param writer IndentingPrintWriter 3477 */ 3478 private void injectErrorEvent(String[] args, IndentingPrintWriter writer) { 3479 if (args.length != 4) { 3480 showInvalidArguments(writer); 3481 return; 3482 } 3483 int propertyId = decodePropertyId(args[1]); 3484 int areaId = decodeAreaId(args[2]); 3485 int errorCode = Integer.decode(args[3]); 3486 Slogf.i(TAG, 3487 "Injecting VHAL error event: property=" + toPropertyIdString( 3488 propertyId) + ", areaId=" + toAreaIdString(propertyId, areaId) 3489 + ", errorCode=" + errorCode); 3490 VehiclePropError vehiclePropError = new VehiclePropError(); 3491 vehiclePropError.propId = propertyId; 3492 vehiclePropError.areaId = areaId; 3493 vehiclePropError.errorCode = errorCode; 3494 mHal.onPropertySetError(new ArrayList<VehiclePropError>(List.of(vehiclePropError))); 3495 } 3496 3497 // Inject continuous vhal events. 3498 private void injectContinuousEvents(String[] args, IndentingPrintWriter writer) { 3499 if (args.length < 3 || args.length > 8) { 3500 showInvalidArguments(writer); 3501 return; 3502 } 3503 String areaId = PARAM_VEHICLE_PROPERTY_GLOBAL_AREA_ID; 3504 String sampleRate = PARAM_INJECT_EVENT_DEFAULT_RATE; 3505 String durationTime = PARAM_INJECT_EVENT_DEFAULT_DURATION; 3506 String propId = args[1]; 3507 String data = args[2]; 3508 // scan input 3509 for (int i = 3; i < args.length - 1; i++) { 3510 switch (args[i]) { 3511 case "-d": 3512 durationTime = args[++i]; 3513 break; 3514 case "-z" : 3515 areaId = args[++i]; 3516 break; 3517 case "-s" : 3518 sampleRate = args[++i]; 3519 break; 3520 default: 3521 writer.printf("%s is an invalid flag.\n", args[i]); 3522 showHelp(writer); 3523 return; 3524 } 3525 } 3526 try { 3527 float sampleRateFloat = Float.parseFloat(sampleRate); 3528 if (sampleRateFloat <= 0) { 3529 writer.printf("SampleRate: %s is an invalid value. " 3530 + "SampleRate must be greater than 0.\n", sampleRate); 3531 showHelp(writer); 3532 return; 3533 } 3534 mHal.injectContinuousVhalEvent(Integer.decode(propId), 3535 Integer.decode(areaId), data, 3536 sampleRateFloat, Long.parseLong(durationTime)); 3537 } catch (NumberFormatException e) { 3538 writer.printf("Invalid arguments: %s\n", e); 3539 showHelp(writer); 3540 } 3541 3542 } 3543 3544 private void setPropertyValue(String[] args, IndentingPrintWriter writer) { 3545 if (args.length != 4) { 3546 writer.println("Invalid command syntax:"); 3547 writer.printf("Usage: %s\n", getSetPropertyValueUsage()); 3548 return; 3549 } 3550 int propertyId = decodePropertyId(args[1]); 3551 int areaId = decodeAreaId(args[2]); 3552 String value = args[3]; 3553 Slogf.i(TAG, "Setting vehicle property ID= %s, areaId= %s, value= %s", 3554 toPropertyIdString(propertyId), toAreaIdString(propertyId, areaId), value); 3555 if (areaId == 0 && !isPropertyAreaTypeGlobal(propertyId)) { 3556 writer.printf("Property area type is inconsistent with given area ID: %s\n", 3557 toAreaIdString(propertyId, areaId)); 3558 return; 3559 } 3560 try { 3561 mHal.setPropertyFromCommand(propertyId, areaId, value, writer); 3562 writer.printf("Property %s area ID %s is set to %s successfully\n", 3563 toPropertyIdString(propertyId), toAreaIdString(propertyId, areaId), value); 3564 } catch (Exception e) { 3565 writer.printf("Cannot set a property: %s\n", e); 3566 } 3567 } 3568 3569 private static String getSetPropertyValueUsage() { 3570 return COMMAND_SET_PROPERTY_VALUE 3571 + " <property name in SCREAMING_SNAKE_CASE or ID in Hex or Decimal> <areaId> " 3572 + "<data (can be comma-separated)>"; 3573 } 3574 3575 // Set a target camera device for the rearview 3576 private void setRearviewCameraId(String[] args, IndentingPrintWriter writer) { 3577 if (args.length != 2) { 3578 showInvalidArguments(writer); 3579 return; 3580 } 3581 3582 if (!mCarEvsService.setRearviewCameraIdFromCommand(args[1])) { 3583 writer.println("Failed to set CarEvsService rearview camera device id."); 3584 } else { 3585 writer.printf("CarEvsService is set to use %s.\n", args[1]); 3586 } 3587 } 3588 3589 private void setCameraId(String[] args, IndentingPrintWriter writer) { 3590 if (args.length != 3) { 3591 showInvalidArguments(writer); 3592 return; 3593 } 3594 3595 if (!mCarEvsService.setCameraIdFromCommand(args[1], args[2])) { 3596 writer.printf("Failed to set CarEvsService camera device id for %s.", args[1]); 3597 } else { 3598 writer.printf("CarEvsService is set to use %s for %s.\n", args[2], args[1]); 3599 } 3600 } 3601 3602 private void enableCameraServiceType(String[] args, IndentingPrintWriter writer) { 3603 if (args.length != 3) { 3604 showInvalidArguments(writer); 3605 return; 3606 } 3607 3608 if (!mCarEvsService.enableServiceTypeFromCommand(args[1], args[2])) { 3609 writer.printf("Failed to enable %s with a camera %s.\n", 3610 args[1], args[2]); 3611 return; 3612 } 3613 3614 writer.printf("%s is successfully enabled and set to use a camera %s.\n", 3615 args[1], args[2]); 3616 } 3617 3618 private void setDrivingSafetyRegion(String[] args, IndentingPrintWriter writer) { 3619 if (args.length != 1 && args.length != 2) { 3620 showInvalidArguments(writer); 3621 return; 3622 } 3623 String region = args.length == 2 ? args[1] : CarPackageManager.DRIVING_SAFETY_REGION_ALL; 3624 writer.println("Set driving safety region to:" + region); 3625 CarLocalServices.getService(CarPackageManagerService.class).resetDrivingSafetyRegion( 3626 region); 3627 } 3628 3629 private void getRearviewCameraId(IndentingPrintWriter writer) { 3630 writer.printf("CarEvsService is using %s for the rearview.\n", 3631 mCarEvsService.getRearviewCameraIdFromCommand()); 3632 } 3633 3634 private void getCameraId(String[] args, IndentingPrintWriter writer) { 3635 if (args.length != 2) { 3636 showInvalidArguments(writer); 3637 return; 3638 } 3639 3640 writer.printf("CarEvsService is using %s for %s.\n", 3641 mCarEvsService.getCameraIdFromCommand(args[1]), args[1]); 3642 } 3643 3644 private void checkCameraServiceTypeEnabled(String[] args, IndentingPrintWriter writer) { 3645 if (args.length != 2) { 3646 showInvalidArguments(writer); 3647 return; 3648 } 3649 3650 if (!mCarEvsService.isServiceTypeEnabledFromCommand(args[1])) { 3651 writer.printf("%s is not enabled.\n", args[1]); 3652 return; 3653 } 3654 3655 String cameraId = mCarEvsService.getCameraIdFromCommand(args[1]); 3656 writer.printf("%s is enabled and set to use %s.\n", args[1], cameraId); 3657 } 3658 3659 private void controlWatchdogPackageKillableState(String[] args, IndentingPrintWriter writer) { 3660 if (args.length != 3) { 3661 showInvalidArguments(writer); 3662 return; 3663 } 3664 if (!Objects.equals(args[1], "true") && !Objects.equals(args[1], "false")) { 3665 writer.println("Failed to parse killable state argument. " 3666 + "Valid arguments: killable | not-killable"); 3667 return; 3668 } 3669 int currentUserId = ActivityManager.getCurrentUser(); 3670 mCarWatchdogService.setKillablePackageAsUser( 3671 args[2], UserHandle.of(currentUserId), Objects.equals(args[1], "true")); 3672 writer.printf("Set package killable state as '%s' for user '%d' and package '%s'\n", 3673 Objects.equals(args[1], "true") ? "killable" : "not killable", currentUserId, 3674 args[2]); 3675 } 3676 3677 // Set third-party foreground I/O threshold for car watchdog 3678 private void setWatchdogIoThirdPartyForegroundBytes(String[] args, 3679 IndentingPrintWriter writer) { 3680 if (args.length != 2) { 3681 showInvalidArguments(writer); 3682 return; 3683 } 3684 try { 3685 long newForegroundModeBytes = Long.parseLong(args[1]); 3686 ResourceOveruseConfiguration configuration = 3687 getThirdPartyResourceOveruseConfiguration( 3688 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 3689 if (configuration == null) { 3690 writer.println("Failed to get third-party resource overuse configurations."); 3691 return; 3692 } 3693 ResourceOveruseConfiguration newConfiguration = setComponentLevelForegroundIoBytes( 3694 configuration, newForegroundModeBytes); 3695 int result = mCarWatchdogService.setResourceOveruseConfigurations( 3696 Collections.singletonList(newConfiguration), 3697 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 3698 if (result == CarWatchdogManager.RETURN_CODE_SUCCESS) { 3699 writer.printf( 3700 "Successfully set third-party I/O overuse foreground threshold. { " 3701 + "foregroundModeBytes = %d } \n", 3702 newForegroundModeBytes); 3703 } else { 3704 writer.println("Failed to set third-party I/O overuse foreground threshold."); 3705 } 3706 } catch (NumberFormatException e) { 3707 writer.println("The argument provided does not contain a parsable long."); 3708 writer.println("Failed to set third-party I/O overuse foreground threshold."); 3709 } catch (RemoteException e) { 3710 writer.printf("Failed to set third-party I/O overuse foreground threshold: %s", 3711 e.getMessage()); 3712 } 3713 } 3714 3715 private void getWatchdogIoThirdPartyForegroundBytes(IndentingPrintWriter writer) { 3716 ResourceOveruseConfiguration configuration = 3717 getThirdPartyResourceOveruseConfiguration( 3718 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 3719 try { 3720 IoOveruseConfiguration ioOveruseConfiguration = Objects.requireNonNull( 3721 configuration).getIoOveruseConfiguration(); 3722 PerStateBytes componentLevelThresholds = Objects.requireNonNull(ioOveruseConfiguration) 3723 .getComponentLevelThresholds(); 3724 long foregroundBytes = Objects.requireNonNull( 3725 componentLevelThresholds).getForegroundModeBytes(); 3726 writer.printf("foregroundModeBytes = %d \n", foregroundBytes); 3727 } catch (NullPointerException e) { 3728 writer.println("Failed to get third-party I/O overuse foreground threshold."); 3729 } 3730 } 3731 3732 private ResourceOveruseConfiguration getThirdPartyResourceOveruseConfiguration( 3733 int resourceOveruseFlag) { 3734 for (ResourceOveruseConfiguration configuration : 3735 mCarWatchdogService.getResourceOveruseConfigurations(resourceOveruseFlag)) { 3736 if (configuration.getComponentType() 3737 == ResourceOveruseConfiguration.COMPONENT_TYPE_THIRD_PARTY) { 3738 return configuration; 3739 } 3740 } 3741 return null; 3742 } 3743 3744 private ResourceOveruseConfiguration setComponentLevelForegroundIoBytes( 3745 ResourceOveruseConfiguration configuration, long foregroundModeBytes) { 3746 IoOveruseConfiguration ioOveruseConfiguration = configuration.getIoOveruseConfiguration(); 3747 PerStateBytes componentLevelThresholds = 3748 ioOveruseConfiguration.getComponentLevelThresholds(); 3749 return constructResourceOveruseConfigurationBuilder( 3750 configuration).setIoOveruseConfiguration( 3751 new IoOveruseConfiguration.Builder( 3752 new PerStateBytes(foregroundModeBytes, 3753 componentLevelThresholds.getBackgroundModeBytes(), 3754 componentLevelThresholds.getGarageModeBytes()), 3755 ioOveruseConfiguration.getPackageSpecificThresholds(), 3756 ioOveruseConfiguration.getAppCategorySpecificThresholds(), 3757 ioOveruseConfiguration.getSystemWideThresholds()) 3758 .build()) 3759 .build(); 3760 } 3761 3762 private ResourceOveruseConfiguration.Builder constructResourceOveruseConfigurationBuilder( 3763 ResourceOveruseConfiguration configuration) { 3764 return new ResourceOveruseConfiguration.Builder(configuration.getComponentType(), 3765 configuration.getSafeToKillPackages(), 3766 configuration.getVendorPackagePrefixes(), 3767 configuration.getPackagesToAppCategoryTypes()) 3768 .setIoOveruseConfiguration(configuration.getIoOveruseConfiguration()); 3769 } 3770 3771 private void controlWatchdogProcessHealthCheck(String[] args, IndentingPrintWriter writer) { 3772 if (args.length != 2) { 3773 showInvalidArguments(writer); 3774 return; 3775 } 3776 if (!Objects.equals(args[1], "enable") && !Objects.equals(args[1], "disable")) { 3777 writer.println("Failed to parse argument. Valid arguments: enable | disable"); 3778 return; 3779 } 3780 mCarWatchdogService.controlProcessHealthCheck(Objects.equals(args[1], "enable")); 3781 writer.printf("Watchdog health checking is now %sd \n", args[1]); 3782 } 3783 3784 private void setWatchdogPowerState(String[] args, IndentingPrintWriter writer) { 3785 if (args.length != 2) { 3786 showInvalidArguments(writer); 3787 return; 3788 } 3789 int powerState = getPowerStateFromString(args[1]); 3790 if (powerState == CarPowerManager.STATE_INVALID) { 3791 writer.printf("Invalid power state received (%s). Valid arguments: " 3792 + "\"shutdown-prepare\" | \"shutdown-enter\"\n", args[1]); 3793 return; 3794 } 3795 3796 mCarWatchdogService.injectPowerState(powerState); 3797 } 3798 3799 private int getPowerStateFromString(String powerState) { 3800 switch (powerState) { 3801 case "shutdown-prepare": 3802 return CarPowerManager.STATE_SHUTDOWN_PREPARE; 3803 case "shutdown-enter": 3804 return CarPowerManager.STATE_SHUTDOWN_ENTER; 3805 default: 3806 Slogf.e(TAG, "Invalid power state: %s", powerState); 3807 } 3808 return CarPowerManager.STATE_INVALID; 3809 } 3810 3811 private void performResourceOveruseKill(String[] args, IndentingPrintWriter writer) { 3812 if (args.length != 2 && args.length != 4) { 3813 showInvalidArguments(writer); 3814 return; 3815 } 3816 String packageName = args[1]; 3817 int userId; 3818 if (args.length > 2 && Objects.equals(args[2], "--user")) { 3819 try { 3820 userId = Integer.parseInt(args[3]); 3821 } catch (NumberFormatException e) { 3822 writer.printf("Invalid user id provided: %s\n", args[3]); 3823 return; 3824 } 3825 } else { 3826 userId = ActivityManager.getCurrentUser(); 3827 } 3828 3829 boolean isKilled = mCarWatchdogService.performResourceOveruseKill(packageName, userId); 3830 if (isKilled) { 3831 writer.printf("Successfully killed package '%s' for user %d\n", packageName, userId); 3832 } else { 3833 UserHandle userHandle = UserHandle.of(userId); 3834 List<PackageKillableState> packageKillableStates = 3835 mCarWatchdogService.getPackageKillableStatesAsUser(userHandle); 3836 3837 for (int i = 0; i < packageKillableStates.size(); i++) { 3838 PackageKillableState state = packageKillableStates.get(i); 3839 if (packageName.equals(state.getPackageName())) { 3840 int killableState = state.getKillableState(); 3841 if (killableState != PackageKillableState.KILLABLE_STATE_YES) { 3842 String stateName = 3843 PackageKillableState.killableStateToString(killableState); 3844 writer.printf("Failed to kill package '%s' for user %d because the " 3845 + "package has state '%s'\n", packageName, userId, stateName); 3846 return; 3847 } 3848 break; 3849 } 3850 } 3851 3852 writer.printf("Failed to kill package '%s' for user %d\n", packageName, userId); 3853 } 3854 } 3855 3856 private void printTelemetryHelp(IndentingPrintWriter writer) { 3857 writer.println("A CLI to interact with CarTelemetryService."); 3858 writer.println("\nUSAGE: adb shell cmd car_service telemetry <subcommand> [options]"); 3859 writer.println("\n\t-h"); 3860 writer.println("\t Print this help text."); 3861 writer.println("\tadd <name>"); 3862 writer.println("\t Adds MetricsConfig from STDIN. Only a binary proto is supported."); 3863 writer.println("\tremove <name>"); 3864 writer.println("\t Removes metrics config."); 3865 writer.println("\tremove-all"); 3866 writer.println("\t Removes all metrics configs."); 3867 writer.println("\tping-script-executor [published data filepath] [state filepath]"); 3868 writer.println("\t Runs a Lua script from stdin."); 3869 writer.println("\tlist"); 3870 writer.println("\t Lists the active config metrics."); 3871 writer.println("\tget-result --config <name> --result-count <num_reports> --timeout " 3872 + "<timeout_sec> --print-results"); 3873 writer.println("\t Blocks until an expected <num_reports> number of metrics reports"); 3874 writer.println("\t is available and returns them."); 3875 writer.println("\t <timeout_sec> specifies the maximum number of seconds that"); 3876 writer.println("\t CLI will block for the expected <num_reports>"); 3877 writer.println("\t number of reports to come in."); 3878 writer.println("\t Optionally prints contents of every report received"); 3879 writer.println("\t if --print-results option is chosen."); 3880 writer.println("\nEXAMPLES:"); 3881 writer.println("\t$ adb shell cmd car_service telemetry add name < config1.protobin"); 3882 writer.println("\t\tWhere config1.protobin is a serialized MetricsConfig proto."); 3883 writer.println("\n\t$ adb shell cmd car_service telemetry get-result --config name " 3884 + "--result-count 1 --timeout 10 --print-results"); 3885 writer.println("\t$ adb shell cmd car_service telemetry ping-script-executor " 3886 + "< example_script.lua"); 3887 writer.println("\t$ adb shell cmd car_service telemetry ping-script-executor " 3888 + "/data/local/tmp/published_data < example_script.lua"); 3889 writer.println("\t$ adb shell cmd car_service telemetry ping-script-executor " 3890 + "/data/local/tmp/bundle /data/local/tmp/bundle2 < example_script.lua"); 3891 } 3892 3893 private void handleTelemetryCommands(String[] args, IndentingPrintWriter writer) { 3894 if (args.length < 2) { 3895 printTelemetryHelp(writer); 3896 return; 3897 } 3898 Car car = Car.createCar(mContext); 3899 CarTelemetryManager carTelemetryManager = 3900 (CarTelemetryManager) car.getCarManager(Car.CAR_TELEMETRY_SERVICE); 3901 if (carTelemetryManager == null) { 3902 writer.println("telemetry service is not enabled, cannot use CLI"); 3903 return; 3904 } 3905 String cmd = args[1]; 3906 switch (cmd) { 3907 case "add": 3908 if (args.length != 3) { 3909 writer.println("Invalid number of arguments."); 3910 printTelemetryHelp(writer); 3911 return; 3912 } 3913 try (BufferedInputStream in = new BufferedInputStream( 3914 new FileInputStream(getInFileDescriptor())); 3915 ByteArrayOutputStream out = new ByteArrayOutputStream()) { 3916 FileUtils.copy(in, out); 3917 CountDownLatch latch = new CountDownLatch(1); 3918 carTelemetryManager.addMetricsConfig(args[2], out.toByteArray(), Runnable::run, 3919 (metricsConfigName, statusCode) -> { 3920 if (statusCode == STATUS_ADD_METRICS_CONFIG_SUCCEEDED) { 3921 writer.printf("MetricsConfig %s is added.\n", args[2]); 3922 } else { 3923 writer.printf( 3924 "Failed to add %s. Status is %d. " 3925 + "Please see logcat for details.\n", 3926 args[2], 3927 statusCode); 3928 } 3929 latch.countDown(); 3930 }); 3931 latch.await(TELEMETRY_RESULT_WAIT_TIMEOUT.toSeconds(), TimeUnit.SECONDS); 3932 } catch (IOException | InterruptedException | NumberFormatException e) { 3933 writer.println("Failed to read from stdin: " + e); 3934 } 3935 break; 3936 case "remove": 3937 if (args.length != 3) { 3938 writer.println("Invalid number of arguments."); 3939 printTelemetryHelp(writer); 3940 return; 3941 } 3942 carTelemetryManager.removeMetricsConfig(args[2]); 3943 writer.printf("Removing %s... Please see logcat for details.\n", args[2]); 3944 break; 3945 case "remove-all": 3946 if (args.length != 2) { 3947 writer.println("Invalid number of arguments."); 3948 printTelemetryHelp(writer); 3949 return; 3950 } 3951 carTelemetryManager.removeAllMetricsConfigs(); 3952 writer.printf("Removing all MetricsConfigs... Please see logcat for details.\n"); 3953 break; 3954 case "ping-script-executor": 3955 if (args.length < 2 || args.length > 4) { 3956 writer.println("Invalid number of arguments."); 3957 printTelemetryHelp(writer); 3958 return; 3959 } 3960 PersistableBundle publishedData = new PersistableBundle(); 3961 publishedData.putInt("age", 99); 3962 publishedData.putStringArray( 3963 "string_array", 3964 new String[]{"a", "b", "c", "a", "b", "c", "a", "b", "c"}); 3965 PersistableBundle nestedBundle = new PersistableBundle(); 3966 nestedBundle.putInt("age", 100); 3967 nestedBundle.putStringArray( 3968 "string_array", 3969 new String[]{"q", "w", "e", "r", "t", "y"}); 3970 publishedData.putPersistableBundle("pers_bundle", nestedBundle); 3971 PersistableBundle savedState = null; 3972 // Read published data 3973 if (args.length >= 3) { 3974 try { 3975 publishedData = IoUtils.readBundle(new File(args[2])); 3976 } catch (IOException e) { 3977 writer.println("Published data path is invalid: " + e); 3978 return; 3979 } 3980 } 3981 // Read saved state 3982 if (args.length == 4) { 3983 try { 3984 savedState = IoUtils.readBundle(new File(args[3])); 3985 } catch (IOException e) { 3986 writer.println("Saved data path is invalid: " + e); 3987 return; 3988 } 3989 } 3990 try { 3991 pingScriptExecutor(writer, publishedData, savedState); 3992 } catch (InterruptedException | RemoteException e) { 3993 throw new RuntimeException(e); 3994 } 3995 break; 3996 case "list": 3997 writer.println("Active metric configs:"); 3998 mCarTelemetryService.getActiveMetricsConfigDetails().forEach((configDetails) -> { 3999 writer.printf("- %s\n", configDetails); 4000 }); 4001 break; 4002 case "get-result": 4003 if (args.length < 8 || args.length > 9) { 4004 writer.println("Invalid number of arguments."); 4005 printTelemetryHelp(writer); 4006 return; 4007 } 4008 String configName = null; 4009 String expectedResultCount = null; 4010 String timeout = null; 4011 boolean printResults = false; 4012 for (int i = 2; i < args.length; i++) { 4013 switch (args[i]) { 4014 case "--config": 4015 configName = args[++i]; 4016 break; 4017 case "--result-count": 4018 expectedResultCount = args[++i]; 4019 break; 4020 case "--timeout": 4021 timeout = args[++i]; 4022 break; 4023 case "--print-results": 4024 printResults = true; 4025 break; 4026 default: 4027 writer.printf("%s is an invalid argument.\n", args[i]); 4028 printTelemetryHelp(writer); 4029 return; 4030 } 4031 } 4032 if (configName == null) { 4033 writer.printf("--config value was not provided.\n"); 4034 printTelemetryHelp(writer); 4035 return; 4036 } 4037 if (expectedResultCount == null) { 4038 writer.printf("--result_count value was not provided.\n"); 4039 printTelemetryHelp(writer); 4040 return; 4041 } 4042 if (timeout == null) { 4043 writer.printf("--timeout value was not provided.\n"); 4044 printTelemetryHelp(writer); 4045 return; 4046 } 4047 CountDownLatch latch = new CountDownLatch(Integer.parseInt(expectedResultCount)); 4048 AtomicLong firstReportReady = new AtomicLong(Long.MIN_VALUE); 4049 AtomicLong lastReportReady = new AtomicLong(Long.MIN_VALUE); 4050 AtomicInteger numResultsReceived = new AtomicInteger(0); 4051 4052 boolean shouldPrintResults = printResults; 4053 CarTelemetryManager.MetricsReportCallback callback = 4054 (metricsConfigName, report, telemetryError, status) -> { 4055 if (report != null) { 4056 // Captures the first time the callback is invoked. 4057 firstReportReady.compareAndSet(Long.MIN_VALUE, 4058 SystemClock.elapsedRealtime()); 4059 // The callback can be invoked many times. This variable stores 4060 // the time instant when the callback was called most recently. 4061 lastReportReady.set(SystemClock.elapsedRealtime()); 4062 report.size(); // unparcel()'s 4063 numResultsReceived.incrementAndGet(); 4064 if (shouldPrintResults) { 4065 writer.println("Report for " + metricsConfigName + ": " 4066 + report); 4067 } 4068 latch.countDown(); 4069 } else if (telemetryError != null) { 4070 parseTelemetryError(telemetryError, writer); 4071 } 4072 }; 4073 String parsedConfigName = configName; 4074 carTelemetryManager.clearReportReadyListener(); 4075 Executor executor = Executors.newSingleThreadExecutor(); 4076 carTelemetryManager.setReportReadyListener(executor, metricsConfigName -> { 4077 if (metricsConfigName.equals(parsedConfigName)) { 4078 carTelemetryManager.getFinishedReport(metricsConfigName, executor, 4079 callback); 4080 } 4081 }); 4082 try { 4083 writer.println("Waiting for the results..."); 4084 writer.flush(); 4085 latch.await(/* timeout =*/Integer.parseInt(timeout), TimeUnit.SECONDS); 4086 long delta = lastReportReady.get() - firstReportReady.get(); 4087 writer.println( 4088 "Took " + delta + " millis to produce " + numResultsReceived.get() 4089 + " reports"); 4090 writer.println("The first report produced at " + firstReportReady.get() 4091 + " millis since boot"); 4092 writer.println("The last report produced at " + lastReportReady.get() 4093 + " millis since boot"); 4094 writer.flush(); 4095 } catch (InterruptedException e) { 4096 writer.println("Result await error: " + e); 4097 } finally { 4098 carTelemetryManager.clearReportReadyListener(); 4099 } 4100 break; 4101 default: 4102 printTelemetryHelp(writer); 4103 } 4104 } 4105 4106 private void pingScriptExecutor( 4107 IndentingPrintWriter writer, 4108 PersistableBundle publishedData, 4109 PersistableBundle savedState) 4110 throws InterruptedException, RemoteException { 4111 writer.println("Sending data to script executor..."); 4112 if (mScriptExecutor == null) { 4113 writer.println("[I] No mScriptExecutor, creating a new one"); 4114 connectToScriptExecutor(writer); 4115 } 4116 String script; 4117 try ( 4118 BufferedInputStream in = new BufferedInputStream( 4119 new FileInputStream(getInFileDescriptor())); 4120 ByteArrayOutputStream out = new ByteArrayOutputStream()) { 4121 FileUtils.copy(in, out); 4122 script = out.toString(); 4123 } catch (IOException | NumberFormatException e) { 4124 writer.println("[E] Failed to read from stdin: " + e); 4125 return; 4126 } 4127 writer.println("[I] Running the script: "); 4128 writer.println(script); 4129 writer.flush(); 4130 4131 CountDownLatch resultLatch = new CountDownLatch(1); 4132 IScriptExecutorListener listener = 4133 new IScriptExecutorListener.Stub() { 4134 @Override 4135 public void onScriptFinished(PersistableBundle result) { 4136 writer.println("Script finished"); 4137 result.size(); // unparcel()'s 4138 writer.println("result: " + result); 4139 writer.flush(); 4140 resultLatch.countDown(); 4141 } 4142 4143 @Override 4144 public void onSuccess(PersistableBundle state) { 4145 writer.println("Script succeeded, saving inter result"); 4146 state.size(); // unparcel()'s 4147 writer.println("state: " + state); 4148 writer.flush(); 4149 resultLatch.countDown(); 4150 } 4151 4152 @Override 4153 public void onError(int errorType, String msg, String stack) { 4154 writer.println("Script error: " + errorType + ": " + msg); 4155 writer.println("Stack: " + stack); 4156 writer.flush(); 4157 resultLatch.countDown(); 4158 } 4159 4160 @Override 4161 public void onMetricsReport( 4162 @NonNull PersistableBundle report, 4163 @Nullable PersistableBundle stateToPersist) { 4164 writer.println("Script produced a report without finishing"); 4165 report.size(); // unparcel()'s 4166 writer.println("report: " + report); 4167 if (stateToPersist != null) { 4168 stateToPersist.size(); // unparcel()'s 4169 writer.println("state to persist: " + stateToPersist); 4170 } 4171 writer.flush(); 4172 resultLatch.countDown(); 4173 } 4174 }; 4175 mScriptExecutor.invokeScript( 4176 script, 4177 "foo", 4178 publishedData, 4179 savedState, 4180 listener); 4181 writer.println("[I] Waiting for the result"); 4182 writer.flush(); 4183 resultLatch.await(10, TimeUnit.SECONDS); // seconds 4184 mContext.unbindService(mScriptExecutorConn); 4185 } 4186 4187 private void connectToScriptExecutor(IndentingPrintWriter writer) throws InterruptedException { 4188 CountDownLatch connectionLatch = new CountDownLatch(1); 4189 mScriptExecutorConn = 4190 new ServiceConnection() { 4191 @Override 4192 public void onServiceConnected(ComponentName name, IBinder service) { 4193 writer.println("[I] Connected to ScriptExecutor Service"); 4194 writer.flush(); 4195 mScriptExecutor = IScriptExecutor.Stub.asInterface(service); 4196 connectionLatch.countDown(); 4197 } 4198 4199 @Override 4200 public void onServiceDisconnected(ComponentName name) { 4201 writer.println("[E] Failed to connect to ScriptExecutor Service"); 4202 writer.flush(); 4203 mScriptExecutor = null; 4204 connectionLatch.countDown(); 4205 } 4206 }; 4207 Intent intent = new Intent(); 4208 intent.setComponent( 4209 new ComponentName( 4210 "com.android.car.scriptexecutor", 4211 "com.android.car.scriptexecutor.ScriptExecutor")); 4212 writer.println("[I] Binding to the script executor"); 4213 boolean success = 4214 mContext.bindServiceAsUser( 4215 intent, 4216 mScriptExecutorConn, 4217 Context.BIND_AUTO_CREATE, 4218 UserHandle.SYSTEM); 4219 if (success) { 4220 writer.println("[I] Found ScriptExecutor package"); 4221 writer.flush(); 4222 } else { 4223 writer.println("[E] Failed to bind to ScriptExecutor"); 4224 writer.flush(); 4225 mScriptExecutor = null; 4226 if (mScriptExecutorConn != null) { 4227 mContext.unbindService(mScriptExecutorConn); 4228 } 4229 return; 4230 } 4231 writer.println("[I] Waiting for the connection"); 4232 connectionLatch.await(5, TimeUnit.SECONDS); // seconds 4233 } 4234 4235 private void parseTelemetryError(byte[] telemetryError, IndentingPrintWriter writer) { 4236 try { 4237 TelemetryError error = TelemetryError.parseFrom(telemetryError); 4238 writer.println("Error: " + error.getErrorType().name() + ": " 4239 + error.getMessage()); 4240 } catch (IOException e) { 4241 writer.println("Error is received, but parsing error failed: " + e); 4242 } 4243 } 4244 4245 private void controlComponentEnabledState(String[] args, IndentingPrintWriter writer) { 4246 if (args.length != 3) { 4247 showInvalidArguments(writer); 4248 return; 4249 } 4250 4251 String packageName = args[2]; 4252 int currentUserId = ActivityManager.getCurrentUser(); 4253 4254 if (Objects.equals(args[1], "get")) { 4255 try { 4256 int curState = PackageManagerHelper 4257 .getApplicationEnabledSettingForUser(packageName, currentUserId); 4258 writer.println("Current State: " + getAppEnabledStateName(curState)); 4259 } catch (Exception e) { 4260 writer.printf("%s: getting package enabled state failed with error: %s\n", 4261 TAG, e.toString()); 4262 } 4263 return; 4264 } 4265 4266 int newState = 0; 4267 switch (args[1]) { 4268 case "default": 4269 newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 4270 break; 4271 case "enable": 4272 newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 4273 break; 4274 case "disable_until_used": 4275 newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; 4276 break; 4277 default: 4278 writer.println("unsupported state action: " + args[1]); 4279 return; 4280 } 4281 4282 String callingPackageName = mContext.getPackageManager().getNameForUid(Process.myUid()); 4283 try { 4284 PackageManagerHelper.setApplicationEnabledSettingForUser(packageName, newState, 4285 /* EnabledFlag */ 0, currentUserId, callingPackageName); 4286 } catch (Exception e) { 4287 writer.printf("%s: setting package enabled state failed with error: %s\n", 4288 TAG, e.toString()); 4289 return; 4290 } 4291 writer.println("New State: " + getAppEnabledStateName(newState)); 4292 } 4293 4294 private String getAppEnabledStateName(int enabledState) { 4295 String stateName = "COMPONENT_ENABLED_STATE_"; 4296 switch (enabledState) { 4297 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: 4298 stateName += "DEFAULT"; 4299 break; 4300 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: 4301 stateName += "ENABLED"; 4302 break; 4303 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: 4304 stateName += "DISABLED"; 4305 break; 4306 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: 4307 stateName += "DISABLED_USER"; 4308 break; 4309 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: 4310 stateName += "DISABLED_UNTIL_USED"; 4311 break; 4312 default: 4313 stateName += "UNSUPPORTED"; 4314 break; 4315 } 4316 return stateName; 4317 } 4318 4319 private void checkLockIsSecure(String[] args, IndentingPrintWriter writer) { 4320 if ((args.length != 1) && (args.length != 2)) { 4321 showInvalidArguments(writer); 4322 } 4323 4324 int userId = UserHandle.myUserId(); 4325 if (args.length == 2) { 4326 userId = Integer.parseInt(args[1]); 4327 } 4328 writer.println(LockPatternHelper.isSecure(mContext, userId)); 4329 } 4330 4331 private void listVhalProps(IndentingPrintWriter writer) { 4332 // Note: The output here is used in AtsVehicleDeviceTest. DO NOT CHANGE the format without 4333 // updating AtsVehicleDeviceTest. 4334 writer.println("All supported property IDs from Vehicle HAL:"); 4335 List<Integer> propIds = new ArrayList<>(); 4336 try { 4337 HalPropConfig[] configs = mHal.getAllPropConfigs(); 4338 for (int i = 0; i < configs.length; i++) { 4339 propIds.add(configs[i].getPropId()); 4340 } 4341 writer.println(propIds.toString()); 4342 } catch (RemoteException | ServiceSpecificException e) { 4343 writer.println("Failed to call getAllPropConfigs, exception: " + e); 4344 } 4345 } 4346 4347 private void getVhalBackend(IndentingPrintWriter writer) { 4348 // Note: The output here is used in AtsVehicleDeviceTest. DO NOT CHANGE the format without 4349 // updating AtsVehicleDeviceTest. 4350 if (mHal.isAidlVhal()) { 4351 writer.println("Vehicle HAL backend: AIDL"); 4352 } else { 4353 writer.println("Vehicle HAL backend: HIDL"); 4354 } 4355 } 4356 4357 private void testEchoReverseBytes(String[] args, IndentingPrintWriter writer) { 4358 // Note: The output here is used in 4359 // AndroidCarApiTest:android.car.apitest.VehicleHalLargeParcelableTest. 4360 // Do not change the output format without updating the test. 4361 if (args.length != 3) { 4362 showInvalidArguments(writer); 4363 return; 4364 } 4365 4366 int propId = Integer.parseInt(args[1]); 4367 int requestSize = Integer.parseInt(args[2]); 4368 4369 byte[] byteValues = new byte[requestSize]; 4370 for (int i = 0; i < requestSize; i++) { 4371 byteValues[i] = (byte) (i); 4372 } 4373 4374 try { 4375 mHal.set(mHal.getHalPropValueBuilder().build(propId, /* areaId= */ 0, byteValues)); 4376 } catch (IllegalArgumentException e) { 4377 writer.println( 4378 "Test Skipped: The property: " + propId + " is not supported, error: " + e); 4379 return; 4380 } catch (ServiceSpecificException e) { 4381 writer.println( 4382 "Test Failed: Failed to set property: " + propId + ", error: " + e); 4383 return; 4384 } 4385 4386 HalPropValue result; 4387 try { 4388 result = mHal.get(mHal.getHalPropValueBuilder().build(propId, /* areaId= */ 0)); 4389 } catch (IllegalArgumentException | ServiceSpecificException e) { 4390 writer.println( 4391 "Test Failed: Failed to get property: " + propId + ", error: " + e); 4392 return; 4393 } 4394 4395 int resultSize = result.getByteValuesSize(); 4396 if (resultSize != requestSize) { 4397 writer.println("Test Failed: expect: " + requestSize + " bytes to be returned, got: " 4398 + resultSize); 4399 return; 4400 } 4401 4402 byte[] reverse = new byte[requestSize]; 4403 for (int i = 0; i < requestSize; i++) { 4404 reverse[i] = byteValues[requestSize - 1 - i]; 4405 } 4406 4407 byte[] resultValues = result.getByteArray(); 4408 if (!Arrays.equals(resultValues, reverse)) { 4409 writer.println("Test Failed: result mismatch, expect: " + Arrays.toString(reverse) 4410 + ", got: " + Arrays.toString(resultValues)); 4411 return; 4412 } 4413 4414 try { 4415 // Set the property to a single byte to free-up memory. Cannot use empty byte array 4416 // here which would cause IllegalArgumentException. 4417 mHal.set(mHal.getHalPropValueBuilder().build(propId, /* areaId= */ 0, 4418 new byte[]{ 0x00 })); 4419 } catch (IllegalArgumentException | ServiceSpecificException e) { 4420 writer.println( 4421 "Test Failed: Failed to clean up property value: failed to set property: " 4422 + propId + ", error: " + e); 4423 return; 4424 } 4425 4426 writer.println("Test Succeeded!"); 4427 } 4428 4429 private void getTargetCarVersion(String[] args, IndentingPrintWriter writer) { 4430 if (args.length < 2) { 4431 showInvalidArguments(writer); 4432 return; 4433 } 4434 4435 int firstAppArg = 1; 4436 4437 // TODO(b/234499460): move --user logic to private helper / support 'all' 4438 int userId = UserHandle.CURRENT.getIdentifier(); 4439 if (Objects.equals(args[1], "--user")) { 4440 if (args.length < 4) { 4441 showInvalidArguments(writer); 4442 return; 4443 } 4444 String userArg = args[2]; 4445 firstAppArg += 2; 4446 if (!Objects.equals(userArg, "current") && !Objects.equals(userArg, "cur")) { 4447 try { 4448 userId = Integer.parseInt(args[2]); 4449 } catch (NumberFormatException e) { 4450 showInvalidArguments(writer); 4451 return; 4452 } 4453 } 4454 } 4455 if (userId == UserHandle.CURRENT.getIdentifier()) { 4456 userId = ActivityManager.getCurrentUser(); 4457 } 4458 writer.printf("User %d:\n", userId); 4459 4460 Context userContext = getContextForUser(userId); 4461 for (int i = firstAppArg; i < args.length; i++) { 4462 String app = args[i]; 4463 try { 4464 CarVersion Version = CarPackageManagerService.getTargetCarVersion( 4465 userContext, app); 4466 writer.printf(" %s: major=%d, minor=%d\n", app, 4467 Version.getMajorVersion(), Version.getMinorVersion()); 4468 } catch (ServiceSpecificException e) { 4469 if (e.errorCode == CarPackageManager.ERROR_CODE_NO_PACKAGE) { 4470 writer.printf(" %s: not found\n", app); 4471 } else { 4472 writer.printf(" %s: unexpected exception: %s \n", app, e); 4473 } 4474 continue; 4475 } 4476 } 4477 } 4478 4479 private void setProcessGroup(String[] args, IndentingPrintWriter writer) { 4480 if (args.length != 3) { 4481 showInvalidArguments(writer); 4482 return; 4483 } 4484 4485 int pid = Integer.parseInt(args[1]); 4486 int group = Integer.parseInt(args[2]); 4487 Slogf.d(TAG, "Setting process group for pid %d, group %d", pid, group); 4488 4489 CarServiceHelperWrapper.getInstance().setProcessGroup(pid, group); 4490 4491 writer.printf(" Successfully set pid %s to group %s\n", args[1], args[2]); 4492 } 4493 4494 private void getProcessGroup(String[] args, IndentingPrintWriter writer) { 4495 if (args.length != 2) { 4496 showInvalidArguments(writer); 4497 return; 4498 } 4499 4500 int pid = Integer.parseInt(args[1]); 4501 int group = CarServiceHelperWrapper.getInstance().getProcessGroup(pid); 4502 4503 writer.printf("%d\n", group); 4504 } 4505 4506 private void setProcessProfile(String[] args, IndentingPrintWriter writer) { 4507 if (args.length != 4) { 4508 showInvalidArguments(writer); 4509 return; 4510 } 4511 4512 int pid = Integer.parseInt(args[1]); 4513 int uid = Integer.parseInt(args[2]); 4514 String profile = args[3]; 4515 4516 Slogf.d(TAG, "Setting process profile for pid %d, uid %d, profile %s", pid, uid, profile); 4517 4518 CarServiceHelperWrapper.getInstance().setProcessProfile(pid, uid, profile); 4519 4520 writer.printf(" Successfully set pid %d uid %d to profile %s\n", pid, uid, profile); 4521 } 4522 4523 private void getDisplayByUser(String[] args, IndentingPrintWriter writer) { 4524 if (args.length != 2) { 4525 showInvalidArguments(writer); 4526 return; 4527 } 4528 4529 // TODO(b/234499460): move --user logic to private helper / support 'all' and 'current' 4530 String userIdArg = args[1]; 4531 int userId; 4532 4533 if (Objects.equals(userIdArg, "current") || Objects.equals(userIdArg, "cur")) { 4534 userId = ActivityManager.getCurrentUser(); 4535 } else { 4536 try { 4537 userId = Integer.parseInt(userIdArg); 4538 } catch (NumberFormatException e) { 4539 writer.printf("Invalid user id: %s\n", userIdArg); 4540 return; 4541 } 4542 } 4543 4544 int displayId = CarServiceHelperWrapper.getInstance().getMainDisplayAssignedToUser(userId); 4545 if (displayId == Display.INVALID_DISPLAY) { 4546 writer.println("none"); 4547 } else { 4548 writer.println(displayId); 4549 } 4550 } 4551 4552 private void getUserByDisplay(String[] args, IndentingPrintWriter writer) { 4553 if (args.length != 2) { 4554 showInvalidArguments(writer); 4555 return; 4556 } 4557 4558 int displayId; 4559 String displayArg = args[1]; 4560 try { 4561 displayId = Integer.parseInt(displayArg); 4562 } catch (NumberFormatException e) { 4563 writer.printf("Invalid displayId id: %s\n", displayArg); 4564 return; 4565 } 4566 4567 int userId = CarServiceHelperWrapper.getInstance().getUserAssignedToDisplay(displayId); 4568 if (userId == UserManagerHelper.USER_NULL) { 4569 writer.println("none"); 4570 return; 4571 } 4572 writer.println(userId); 4573 } 4574 4575 private void assignExtraDisplay(String[] args, IndentingPrintWriter writer) { 4576 assignOrUnassignExtraDisplay(args, writer, true); 4577 } 4578 4579 private void unassignExtraDisplay(String[] args, IndentingPrintWriter writer) { 4580 assignOrUnassignExtraDisplay(args, writer, false); 4581 } 4582 4583 private void assignOrUnassignExtraDisplay( 4584 String[] args, IndentingPrintWriter writer, boolean assign) { 4585 if (args.length != 3) { 4586 showInvalidArguments(writer); 4587 return; 4588 } 4589 4590 int userId; 4591 if (Objects.equals(args[1], "current") || Objects.equals(args[1], "cur")) { 4592 userId = ActivityManager.getCurrentUser(); 4593 } else { 4594 try { 4595 userId = Integer.parseInt(args[1]); 4596 } catch (NumberFormatException e) { 4597 writer.printf("Invalid userId provided: %s\n", args[1]); 4598 return; 4599 } 4600 } 4601 int displayId; 4602 try { 4603 displayId = Integer.parseInt(args[2]); 4604 } catch (NumberFormatException e) { 4605 writer.printf("Invalid displayId provided: %s\n", args[2]); 4606 return; 4607 } 4608 4609 boolean success; 4610 if (assign) { 4611 success = CarServiceHelperWrapper.getInstance() 4612 .assignUserToExtraDisplay(userId, displayId); 4613 } else { 4614 success = CarServiceHelperWrapper.getInstance() 4615 .unassignUserFromExtraDisplay(userId, displayId); 4616 } 4617 if (success) { 4618 writer.printf("Successfully %sassigned user %d %s display %d.\n", 4619 (assign ? "" : "un"), userId, (assign ? "to" : "from"), displayId); 4620 } else { 4621 writer.printf("Failed to %sassign user %d %s display %d.\n", 4622 (assign ? "" : "un"), userId, (assign ? "to" : "from"), displayId); 4623 4624 } 4625 } 4626 4627 private static boolean isPropertyAreaTypeGlobal(int propertyId) { 4628 return (propertyId & VehicleArea.MASK) == VehicleArea.GLOBAL; 4629 } 4630 4631 private static String getSuspendCommandUsage(String command) { 4632 return command + " [" + PARAM_AUTO + "|" + PARAM_SIMULATE + "|" + PARAM_REAL + "] [" 4633 + PARAM_SKIP_GARAGEMODE + "] [" + PARAM_WAKEUP_AFTER + " RESUME_DELAY | " 4634 + PARAM_CANCEL_AFTER + " CANCEL_DELAY]" + "[" + PARAM_FREE_MEMORY + "]"; 4635 } 4636 4637 private static final class AudioZoneMirrorStatusCallbackImpl extends 4638 IAudioZonesMirrorStatusCallback.Stub { 4639 4640 private static final long TEST_CALLBACK_TIMEOUT_MS = 5_000; 4641 4642 private int[] mZoneIds; 4643 private int mStatus; 4644 private CountDownLatch mStatusLatch = new CountDownLatch(1); 4645 4646 @Override 4647 public void onAudioZonesMirrorStatusChanged(int[] zoneIds, int status) { 4648 mZoneIds = zoneIds; 4649 mStatus = status; 4650 mStatusLatch.countDown(); 4651 } 4652 4653 private boolean waitForCallback() throws Exception { 4654 return mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 4655 } 4656 4657 public void reset() { 4658 mZoneIds = null; 4659 mStatus = 0; 4660 mStatusLatch = new CountDownLatch(1); 4661 } 4662 } 4663 } 4664