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