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