1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car; 18 19 import android.annotation.MainThread; 20 import android.app.ActivityManager; 21 import android.app.ActivityOptions; 22 import android.app.UiModeManager; 23 import android.car.Car; 24 import android.car.ICar; 25 import android.car.cluster.renderer.IInstrumentClusterNavigation; 26 import android.car.userlib.CarUserManagerHelper; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.PackageManager; 31 import android.content.res.Resources; 32 import android.hardware.automotive.vehicle.V2_0.IVehicle; 33 import android.hardware.automotive.vehicle.V2_0.VehicleArea; 34 import android.os.Binder; 35 import android.os.Build; 36 import android.os.IBinder; 37 import android.os.Process; 38 import android.os.SystemClock; 39 import android.os.Trace; 40 import android.util.Log; 41 import android.util.Slog; 42 import android.util.TimingsTraceLog; 43 import android.view.KeyEvent; 44 45 import com.android.car.am.FixedActivityService; 46 import com.android.car.audio.CarAudioService; 47 import com.android.car.cluster.InstrumentClusterService; 48 import com.android.car.garagemode.GarageModeService; 49 import com.android.car.hal.InputHalService; 50 import com.android.car.hal.VehicleHal; 51 import com.android.car.internal.FeatureConfiguration; 52 import com.android.car.pm.CarPackageManagerService; 53 import com.android.car.stats.CarStatsService; 54 import com.android.car.systeminterface.SystemInterface; 55 import com.android.car.trust.CarTrustedDeviceService; 56 import com.android.car.user.CarUserNoticeService; 57 import com.android.car.user.CarUserService; 58 import com.android.car.vms.VmsBrokerService; 59 import com.android.car.vms.VmsClientManager; 60 import com.android.internal.annotations.GuardedBy; 61 import com.android.internal.car.ICarServiceHelper; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.util.ArrayList; 66 import java.util.Arrays; 67 import java.util.List; 68 69 public class ICarImpl extends ICar.Stub { 70 71 public static final String INTERNAL_INPUT_SERVICE = "internal_input"; 72 public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE = 73 "system_activity_monitoring"; 74 public static final String INTERNAL_VMS_MANAGER = "vms_manager"; 75 76 private final Context mContext; 77 private final VehicleHal mHal; 78 79 private final SystemInterface mSystemInterface; 80 81 private final SystemActivityMonitoringService mSystemActivityMonitoringService; 82 private final CarPowerManagementService mCarPowerManagementService; 83 private final CarPackageManagerService mCarPackageManagerService; 84 private final CarInputService mCarInputService; 85 private final CarDrivingStateService mCarDrivingStateService; 86 private final CarUxRestrictionsManagerService mCarUXRestrictionsService; 87 private final CarAudioService mCarAudioService; 88 private final CarProjectionService mCarProjectionService; 89 private final CarPropertyService mCarPropertyService; 90 private final CarNightService mCarNightService; 91 private final AppFocusService mAppFocusService; 92 private final FixedActivityService mFixedActivityService; 93 private final GarageModeService mGarageModeService; 94 private final InstrumentClusterService mInstrumentClusterService; 95 private final CarLocationService mCarLocationService; 96 private final SystemStateControllerService mSystemStateControllerService; 97 private final CarBluetoothService mCarBluetoothService; 98 private final PerUserCarServiceHelper mPerUserCarServiceHelper; 99 private final CarDiagnosticService mCarDiagnosticService; 100 private final CarStorageMonitoringService mCarStorageMonitoringService; 101 private final CarConfigurationService mCarConfigurationService; 102 private final CarTrustedDeviceService mCarTrustedDeviceService; 103 private final CarMediaService mCarMediaService; 104 private final CarUserManagerHelper mUserManagerHelper; 105 private final CarUserService mCarUserService; 106 private final CarUserNoticeService mCarUserNoticeService; 107 private final VmsClientManager mVmsClientManager; 108 private final VmsBrokerService mVmsBrokerService; 109 private final VmsSubscriberService mVmsSubscriberService; 110 private final VmsPublisherService mVmsPublisherService; 111 private final CarBugreportManagerService mCarBugreportManagerService; 112 private final CarStatsService mCarStatsService; 113 114 private final CarServiceBase[] mAllServices; 115 116 private static final String TAG = "ICarImpl"; 117 private static final String VHAL_TIMING_TAG = "VehicleHalTiming"; 118 119 private TimingsTraceLog mBootTiming; 120 121 /** Test only service. Populate it only when necessary. */ 122 @GuardedBy("this") 123 private CarTestService mCarTestService; 124 125 @GuardedBy("this") 126 private ICarServiceHelper mICarServiceHelper; 127 128 private final String mVehicleInterfaceName; 129 ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, CanBusErrorNotifier errorNotifier, String vehicleInterfaceName)130 public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, 131 CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) { 132 mContext = serviceContext; 133 mSystemInterface = systemInterface; 134 mHal = new VehicleHal(serviceContext, vehicle); 135 mVehicleInterfaceName = vehicleInterfaceName; 136 mUserManagerHelper = new CarUserManagerHelper(serviceContext); 137 final Resources res = mContext.getResources(); 138 final int maxRunningUsers = res.getInteger( 139 com.android.internal.R.integer.config_multiuserMaxRunningUsers); 140 mCarUserService = new CarUserService(serviceContext, mUserManagerHelper, 141 ActivityManager.getService(), maxRunningUsers); 142 mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext); 143 mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(), 144 systemInterface, mUserManagerHelper); 145 mCarUserNoticeService = new CarUserNoticeService(serviceContext); 146 mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal()); 147 mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService); 148 mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext, 149 mCarDrivingStateService, mCarPropertyService); 150 mCarPackageManagerService = new CarPackageManagerService(serviceContext, 151 mCarUXRestrictionsService, 152 mSystemActivityMonitoringService, 153 mUserManagerHelper); 154 mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext); 155 mCarBluetoothService = new CarBluetoothService(serviceContext, mPerUserCarServiceHelper); 156 mCarInputService = new CarInputService(serviceContext, mHal.getInputHal()); 157 mCarProjectionService = new CarProjectionService( 158 serviceContext, null /* handler */, mCarInputService, mCarBluetoothService); 159 mGarageModeService = new GarageModeService(mContext); 160 mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService); 161 mCarAudioService = new CarAudioService(serviceContext); 162 mCarNightService = new CarNightService(serviceContext, mCarPropertyService); 163 mFixedActivityService = new FixedActivityService(serviceContext); 164 mInstrumentClusterService = new InstrumentClusterService(serviceContext, 165 mAppFocusService, mCarInputService); 166 mSystemStateControllerService = new SystemStateControllerService( 167 serviceContext, mCarAudioService, this); 168 mCarStatsService = new CarStatsService(serviceContext); 169 mVmsBrokerService = new VmsBrokerService(); 170 mVmsClientManager = new VmsClientManager( 171 // CarStatsService needs to be passed to the constructor due to HAL init order 172 serviceContext, mCarStatsService, mCarUserService, mVmsBrokerService, 173 mHal.getVmsHal()); 174 mVmsSubscriberService = new VmsSubscriberService( 175 serviceContext, mVmsBrokerService, mVmsClientManager, mHal.getVmsHal()); 176 mVmsPublisherService = new VmsPublisherService( 177 serviceContext, mCarStatsService, mVmsBrokerService, mVmsClientManager); 178 mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal()); 179 mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext, 180 systemInterface); 181 mCarConfigurationService = 182 new CarConfigurationService(serviceContext, new JsonReaderImpl()); 183 mCarLocationService = new CarLocationService(mContext, mUserManagerHelper); 184 mCarTrustedDeviceService = new CarTrustedDeviceService(serviceContext); 185 mCarMediaService = new CarMediaService(serviceContext); 186 mCarBugreportManagerService = new CarBugreportManagerService(serviceContext); 187 188 CarLocalServices.addService(CarPowerManagementService.class, mCarPowerManagementService); 189 CarLocalServices.addService(CarUserService.class, mCarUserService); 190 CarLocalServices.addService(CarTrustedDeviceService.class, mCarTrustedDeviceService); 191 CarLocalServices.addService(CarUserNoticeService.class, mCarUserNoticeService); 192 CarLocalServices.addService(SystemInterface.class, mSystemInterface); 193 CarLocalServices.addService(CarDrivingStateService.class, mCarDrivingStateService); 194 CarLocalServices.addService(PerUserCarServiceHelper.class, mPerUserCarServiceHelper); 195 CarLocalServices.addService(FixedActivityService.class, mFixedActivityService); 196 197 // Be careful with order. Service depending on other service should be inited later. 198 List<CarServiceBase> allServices = new ArrayList<>(); 199 allServices.add(mCarUserService); 200 allServices.add(mSystemActivityMonitoringService); 201 allServices.add(mCarPowerManagementService); 202 allServices.add(mCarPropertyService); 203 allServices.add(mCarDrivingStateService); 204 allServices.add(mCarUXRestrictionsService); 205 allServices.add(mCarPackageManagerService); 206 allServices.add(mCarInputService); 207 allServices.add(mGarageModeService); 208 allServices.add(mCarUserNoticeService); 209 allServices.add(mAppFocusService); 210 allServices.add(mCarAudioService); 211 allServices.add(mCarNightService); 212 allServices.add(mFixedActivityService); 213 allServices.add(mInstrumentClusterService); 214 allServices.add(mSystemStateControllerService); 215 allServices.add(mPerUserCarServiceHelper); 216 allServices.add(mCarBluetoothService); 217 allServices.add(mCarProjectionService); 218 allServices.add(mCarDiagnosticService); 219 allServices.add(mCarStorageMonitoringService); 220 allServices.add(mCarConfigurationService); 221 allServices.add(mVmsClientManager); 222 allServices.add(mVmsSubscriberService); 223 allServices.add(mVmsPublisherService); 224 allServices.add(mCarTrustedDeviceService); 225 allServices.add(mCarMediaService); 226 allServices.add(mCarLocationService); 227 allServices.add(mCarBugreportManagerService); 228 mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]); 229 } 230 231 @MainThread init()232 void init() { 233 mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL); 234 traceBegin("VehicleHal.init"); 235 mHal.init(); 236 traceEnd(); 237 traceBegin("CarService.initAllServices"); 238 for (CarServiceBase service : mAllServices) { 239 service.init(); 240 } 241 traceEnd(); 242 mSystemInterface.reconfigureSecondaryDisplays(); 243 } 244 release()245 void release() { 246 // release done in opposite order from init 247 for (int i = mAllServices.length - 1; i >= 0; i--) { 248 mAllServices[i].release(); 249 } 250 mHal.release(); 251 } 252 vehicleHalReconnected(IVehicle vehicle)253 void vehicleHalReconnected(IVehicle vehicle) { 254 mHal.vehicleHalReconnected(vehicle); 255 for (CarServiceBase service : mAllServices) { 256 service.vehicleHalReconnected(); 257 } 258 } 259 260 @Override setCarServiceHelper(IBinder helper)261 public void setCarServiceHelper(IBinder helper) { 262 assertCallingFromSystemProcess(); 263 synchronized (this) { 264 mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper); 265 mSystemInterface.setCarServiceHelper(mICarServiceHelper); 266 } 267 } 268 269 @Override setUserLockStatus(int userHandle, int unlocked)270 public void setUserLockStatus(int userHandle, int unlocked) { 271 assertCallingFromSystemProcess(); 272 mCarUserService.setUserLockStatus(userHandle, unlocked == 1); 273 mCarMediaService.setUserLockStatus(userHandle, unlocked == 1); 274 } 275 276 @Override onSwitchUser(int userHandle)277 public void onSwitchUser(int userHandle) { 278 assertCallingFromSystemProcess(); 279 280 Log.i(TAG, "Foreground user switched to " + userHandle); 281 mCarUserService.onSwitchUser(userHandle); 282 } 283 assertCallingFromSystemProcess()284 static void assertCallingFromSystemProcess() { 285 int uid = Binder.getCallingUid(); 286 if (uid != Process.SYSTEM_UID) { 287 throw new SecurityException("Only allowed from system"); 288 } 289 } 290 291 /** 292 * Assert if binder call is coming from system process like system server or if it is called 293 * from its own process even if it is not system. The latter can happen in test environment. 294 * Note that car service runs as system user but test like car service test will not. 295 */ assertCallingFromSystemProcessOrSelf()296 static void assertCallingFromSystemProcessOrSelf() { 297 int uid = Binder.getCallingUid(); 298 int pid = Binder.getCallingPid(); 299 if (uid != Process.SYSTEM_UID && pid != Process.myPid()) { 300 throw new SecurityException("Only allowed from system or self"); 301 } 302 } 303 304 @Override getCarService(String serviceName)305 public IBinder getCarService(String serviceName) { 306 switch (serviceName) { 307 case Car.AUDIO_SERVICE: 308 return mCarAudioService; 309 case Car.APP_FOCUS_SERVICE: 310 return mAppFocusService; 311 case Car.PACKAGE_SERVICE: 312 return mCarPackageManagerService; 313 case Car.DIAGNOSTIC_SERVICE: 314 assertAnyDiagnosticPermission(mContext); 315 return mCarDiagnosticService; 316 case Car.POWER_SERVICE: 317 assertPowerPermission(mContext); 318 return mCarPowerManagementService; 319 case Car.CABIN_SERVICE: 320 case Car.HVAC_SERVICE: 321 case Car.INFO_SERVICE: 322 case Car.PROPERTY_SERVICE: 323 case Car.SENSOR_SERVICE: 324 case Car.VENDOR_EXTENSION_SERVICE: 325 return mCarPropertyService; 326 case Car.CAR_NAVIGATION_SERVICE: 327 assertNavigationManagerPermission(mContext); 328 IInstrumentClusterNavigation navService = 329 mInstrumentClusterService.getNavigationService(); 330 return navService == null ? null : navService.asBinder(); 331 case Car.CAR_INSTRUMENT_CLUSTER_SERVICE: 332 assertClusterManagerPermission(mContext); 333 return mInstrumentClusterService.getManagerService(); 334 case Car.PROJECTION_SERVICE: 335 return mCarProjectionService; 336 case Car.VMS_SUBSCRIBER_SERVICE: 337 assertVmsSubscriberPermission(mContext); 338 return mVmsSubscriberService; 339 case Car.TEST_SERVICE: { 340 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE); 341 synchronized (this) { 342 if (mCarTestService == null) { 343 mCarTestService = new CarTestService(mContext, this); 344 } 345 return mCarTestService; 346 } 347 } 348 case Car.BLUETOOTH_SERVICE: 349 return mCarBluetoothService; 350 case Car.STORAGE_MONITORING_SERVICE: 351 assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING); 352 return mCarStorageMonitoringService; 353 case Car.CAR_DRIVING_STATE_SERVICE: 354 assertDrivingStatePermission(mContext); 355 return mCarDrivingStateService; 356 case Car.CAR_UX_RESTRICTION_SERVICE: 357 return mCarUXRestrictionsService; 358 case Car.CAR_CONFIGURATION_SERVICE: 359 return mCarConfigurationService; 360 case Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE: 361 assertTrustAgentEnrollmentPermission(mContext); 362 return mCarTrustedDeviceService.getCarTrustAgentEnrollmentService(); 363 case Car.CAR_MEDIA_SERVICE: 364 return mCarMediaService; 365 case Car.CAR_BUGREPORT_SERVICE: 366 return mCarBugreportManagerService; 367 default: 368 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName); 369 return null; 370 } 371 } 372 373 @Override getCarConnectionType()374 public int getCarConnectionType() { 375 return Car.CONNECTION_TYPE_EMBEDDED; 376 } 377 getCarInternalService(String serviceName)378 public CarServiceBase getCarInternalService(String serviceName) { 379 switch (serviceName) { 380 case INTERNAL_INPUT_SERVICE: 381 return mCarInputService; 382 case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE: 383 return mSystemActivityMonitoringService; 384 case INTERNAL_VMS_MANAGER: 385 return mVmsClientManager; 386 default: 387 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" + 388 serviceName); 389 return null; 390 } 391 } 392 getStatsService()393 CarStatsService getStatsService() { 394 return mCarStatsService; 395 } 396 assertVehicleHalMockPermission(Context context)397 public static void assertVehicleHalMockPermission(Context context) { 398 assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL); 399 } 400 assertNavigationManagerPermission(Context context)401 public static void assertNavigationManagerPermission(Context context) { 402 assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER); 403 } 404 assertClusterManagerPermission(Context context)405 public static void assertClusterManagerPermission(Context context) { 406 assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL); 407 } 408 assertPowerPermission(Context context)409 public static void assertPowerPermission(Context context) { 410 assertPermission(context, Car.PERMISSION_CAR_POWER); 411 } 412 assertProjectionPermission(Context context)413 public static void assertProjectionPermission(Context context) { 414 assertPermission(context, Car.PERMISSION_CAR_PROJECTION); 415 } 416 417 /** Verify the calling context has the {@link Car#PERMISSION_CAR_PROJECTION_STATUS} */ assertProjectionStatusPermission(Context context)418 public static void assertProjectionStatusPermission(Context context) { 419 assertPermission(context, Car.PERMISSION_CAR_PROJECTION_STATUS); 420 } 421 assertAnyDiagnosticPermission(Context context)422 public static void assertAnyDiagnosticPermission(Context context) { 423 assertAnyPermission(context, 424 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL, 425 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR); 426 } 427 assertDrivingStatePermission(Context context)428 public static void assertDrivingStatePermission(Context context) { 429 assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE); 430 } 431 assertVmsPublisherPermission(Context context)432 public static void assertVmsPublisherPermission(Context context) { 433 assertPermission(context, Car.PERMISSION_VMS_PUBLISHER); 434 } 435 assertVmsSubscriberPermission(Context context)436 public static void assertVmsSubscriberPermission(Context context) { 437 assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER); 438 } 439 440 /** 441 * Ensures the caller has the permission to enroll a Trust Agent. 442 */ assertTrustAgentEnrollmentPermission(Context context)443 public static void assertTrustAgentEnrollmentPermission(Context context) { 444 assertPermission(context, Car.PERMISSION_CAR_ENROLL_TRUST); 445 } 446 assertPermission(Context context, String permission)447 public static void assertPermission(Context context, String permission) { 448 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 449 throw new SecurityException("requires " + permission); 450 } 451 } 452 453 /** 454 * Checks to see if the caller has a permission. 455 * 456 * @return boolean TRUE if caller has the permission. 457 */ hasPermission(Context context, String permission)458 public static boolean hasPermission(Context context, String permission) { 459 return context.checkCallingOrSelfPermission(permission) 460 == PackageManager.PERMISSION_GRANTED; 461 } 462 assertAnyPermission(Context context, String... permissions)463 public static void assertAnyPermission(Context context, String... permissions) { 464 for (String permission : permissions) { 465 if (context.checkCallingOrSelfPermission(permission) == 466 PackageManager.PERMISSION_GRANTED) { 467 return; 468 } 469 } 470 throw new SecurityException("requires any of " + Arrays.toString(permissions)); 471 } 472 473 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)474 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 475 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 476 != PackageManager.PERMISSION_GRANTED) { 477 writer.println("Permission Denial: can't dump CarService from from pid=" 478 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 479 + " without permission " + android.Manifest.permission.DUMP); 480 return; 481 } 482 483 if (args == null || args.length == 0 || (args.length > 0 && "-a".equals(args[0]))) { 484 writer.println("*Dump car service*"); 485 writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT); 486 writer.println("*Dump all services*"); 487 488 dumpAllServices(writer); 489 490 writer.println("*Dump Vehicle HAL*"); 491 writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName); 492 try { 493 // TODO dump all feature flags by creating a dumpable interface 494 mHal.dump(writer); 495 } catch (Exception e) { 496 writer.println("Failed dumping: " + mHal.getClass().getName()); 497 e.printStackTrace(writer); 498 } 499 } else if ("--metrics".equals(args[0])) { 500 // Strip the --metrics flag when passing dumpsys arguments to CarStatsService 501 // allowing for nested flag selection 502 mCarStatsService.dump(fd, writer, Arrays.copyOfRange(args, 1, args.length)); 503 } else if ("--vms-hal".equals(args[0])) { 504 mHal.getVmsHal().dumpMetrics(fd); 505 } else if (Build.IS_USERDEBUG || Build.IS_ENG) { 506 execShellCmd(args, writer); 507 } else { 508 writer.println("Commands not supported in " + Build.TYPE); 509 } 510 } 511 dumpAllServices(PrintWriter writer)512 private void dumpAllServices(PrintWriter writer) { 513 for (CarServiceBase service : mAllServices) { 514 dumpService(service, writer); 515 } 516 if (mCarTestService != null) { 517 dumpService(mCarTestService, writer); 518 } 519 } 520 dumpService(CarServiceBase service, PrintWriter writer)521 private void dumpService(CarServiceBase service, PrintWriter writer) { 522 try { 523 service.dump(writer); 524 } catch (Exception e) { 525 writer.println("Failed dumping: " + service.getClass().getName()); 526 e.printStackTrace(writer); 527 } 528 } 529 execShellCmd(String[] args, PrintWriter writer)530 void execShellCmd(String[] args, PrintWriter writer) { 531 new CarShellCommand().exec(args, writer); 532 } 533 534 @MainThread traceBegin(String name)535 private void traceBegin(String name) { 536 Slog.i(TAG, name); 537 mBootTiming.traceBegin(name); 538 } 539 540 @MainThread traceEnd()541 private void traceEnd() { 542 mBootTiming.traceEnd(); 543 } 544 545 private class CarShellCommand { 546 private static final String COMMAND_HELP = "-h"; 547 private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode"; 548 private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event"; 549 private static final String COMMAND_INJECT_ERROR_EVENT = "inject-error-event"; 550 private static final String COMMAND_ENABLE_UXR = "enable-uxr"; 551 private static final String COMMAND_GARAGE_MODE = "garage-mode"; 552 private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities"; 553 private static final String COMMAND_GET_CARPROPERTYCONFIG = "get-carpropertyconfig"; 554 private static final String COMMAND_GET_PROPERTY_VALUE = "get-property-value"; 555 private static final String COMMAND_PROJECTION_AP_TETHERING = "projection-tethering"; 556 private static final String COMMAND_PROJECTION_UI_MODE = "projection-ui-mode"; 557 private static final String COMMAND_RESUME = "resume"; 558 private static final String COMMAND_SUSPEND = "suspend"; 559 private static final String COMMAND_ENABLE_TRUSTED_DEVICE = "enable-trusted-device"; 560 private static final String COMMAND_REMOVE_TRUSTED_DEVICES = "remove-trusted-devices"; 561 private static final String COMMAND_START_FIXED_ACTIVITY_MODE = "start-fixed-activity-mode"; 562 private static final String COMMAND_STOP_FIXED_ACTIVITY_MODE = "stop-fixed-activity-mode"; 563 private static final String COMMAND_INJECT_KEY = "inject-key"; 564 565 private static final String PARAM_DAY_MODE = "day"; 566 private static final String PARAM_NIGHT_MODE = "night"; 567 private static final String PARAM_SENSOR_MODE = "sensor"; 568 private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0"; 569 private static final String PARAM_ON_MODE = "on"; 570 private static final String PARAM_OFF_MODE = "off"; 571 private static final String PARAM_QUERY_MODE = "query"; 572 private static final String PARAM_REBOOT = "reboot"; 573 574 dumpHelp(PrintWriter pw)575 private void dumpHelp(PrintWriter pw) { 576 pw.println("Car service commands:"); 577 pw.println("\t-h"); 578 pw.println("\t Print this help text."); 579 pw.println("\tday-night-mode [day|night|sensor]"); 580 pw.println("\t Force into day/night mode or restore to auto."); 581 pw.println("\tinject-vhal-event property [zone] data(can be comma separated list)"); 582 pw.println("\t Inject a vehicle property for testing."); 583 pw.println("\tinject-error-event property zone errorCode"); 584 pw.println("\t Inject an error event from VHAL for testing."); 585 pw.println("\tenable-uxr true|false"); 586 pw.println("\t Enable/Disable UX restrictions and App blocking."); 587 pw.println("\tgarage-mode [on|off|query|reboot]"); 588 pw.println("\t Force into or out of garage mode, or check status."); 589 pw.println("\t With 'reboot', enter garage mode, then reboot when it completes."); 590 pw.println("\tget-do-activities pkgname"); 591 pw.println("\t Get Distraction Optimized activities in given package."); 592 pw.println("\tget-carpropertyconfig [propertyId]"); 593 pw.println("\t Get a CarPropertyConfig by Id in Hex or list all CarPropertyConfigs"); 594 pw.println("\tget-property-value [propertyId] [areaId]"); 595 pw.println("\t Get a vehicle property value by property id in Hex and areaId"); 596 pw.println("\t or list all property values for all areaId"); 597 pw.println("\tsuspend"); 598 pw.println("\t Suspend the system to Deep Sleep."); 599 pw.println("\tresume"); 600 pw.println("\t Wake the system up after a 'suspend.'"); 601 pw.println("\tenable-trusted-device true|false"); 602 pw.println("\t Enable/Disable Trusted device feature."); 603 pw.println("\tremove-trusted-devices"); 604 pw.println("\t Remove all trusted devices for the current foreground user."); 605 pw.println("\tprojection-tethering [true|false]"); 606 pw.println("\t Whether tethering should be used when creating access point for" 607 + " wireless projection"); 608 pw.println("\t--metrics"); 609 pw.println("\t When used with dumpsys, only metrics will be in the dumpsys output."); 610 pw.println("\tstart-fixed-activity displayId packageName activityName"); 611 pw.println("\t Start an Activity the specified display as fixed mode"); 612 pw.println("\tstop-fixed-mode displayId"); 613 pw.println("\t Stop fixed Activity mode for the given display. " 614 + "The Activity will not be restarted upon crash."); 615 pw.println("\tinject-key [-d display] [-t down_delay_ms] key_code"); 616 pw.println("\t inject key down / up event to car service"); 617 pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0."); 618 pw.println("\t down_delay_ms: delay from down to up key event. If not specified,"); 619 pw.println("\t it will be 0"); 620 pw.println("\t key_code: int key code defined in android KeyEvent"); 621 } 622 exec(String[] args, PrintWriter writer)623 public void exec(String[] args, PrintWriter writer) { 624 String arg = args[0]; 625 switch (arg) { 626 case COMMAND_HELP: 627 dumpHelp(writer); 628 break; 629 case COMMAND_DAY_NIGHT_MODE: { 630 String value = args.length < 2 ? "" : args[1]; 631 forceDayNightMode(value, writer); 632 break; 633 } 634 case COMMAND_GARAGE_MODE: { 635 String value = args.length < 2 ? "" : args[1]; 636 forceGarageMode(value, writer); 637 break; 638 } 639 case COMMAND_INJECT_VHAL_EVENT: 640 String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL; 641 String data; 642 if (args.length != 3 && args.length != 4) { 643 writer.println("Incorrect number of arguments."); 644 dumpHelp(writer); 645 break; 646 } else if (args.length == 4) { 647 // Zoned 648 zone = args[2]; 649 data = args[3]; 650 } else { 651 // Global 652 data = args[2]; 653 } 654 injectVhalEvent(args[1], zone, data, false, writer); 655 break; 656 case COMMAND_INJECT_ERROR_EVENT: 657 if (args.length != 4) { 658 writer.println("Incorrect number of arguments"); 659 dumpHelp(writer); 660 break; 661 } 662 String errorAreaId = args[2]; 663 String errorCode = args[3]; 664 injectVhalEvent(args[1], errorAreaId, errorCode, true, writer); 665 break; 666 case COMMAND_ENABLE_UXR: 667 if (args.length != 2) { 668 writer.println("Incorrect number of arguments"); 669 dumpHelp(writer); 670 break; 671 } 672 boolean enableBlocking = Boolean.valueOf(args[1]); 673 if (mCarPackageManagerService != null) { 674 mCarPackageManagerService.setEnableActivityBlocking(enableBlocking); 675 } 676 break; 677 case COMMAND_GET_DO_ACTIVITIES: 678 if (args.length != 2) { 679 writer.println("Incorrect number of arguments"); 680 dumpHelp(writer); 681 break; 682 } 683 String pkgName = args[1].toLowerCase(); 684 if (mCarPackageManagerService != null) { 685 String[] doActivities = 686 mCarPackageManagerService.getDistractionOptimizedActivities( 687 pkgName); 688 if (doActivities != null) { 689 writer.println("DO Activities for " + pkgName); 690 for (String a : doActivities) { 691 writer.println(a); 692 } 693 } else { 694 writer.println("No DO Activities for " + pkgName); 695 } 696 } 697 break; 698 case COMMAND_GET_CARPROPERTYCONFIG: 699 String propertyId = args.length < 2 ? "" : args[1]; 700 mHal.dumpPropertyConfigs(writer, propertyId); 701 break; 702 case COMMAND_GET_PROPERTY_VALUE: 703 String propId = args.length < 2 ? "" : args[1]; 704 String areaId = args.length < 3 ? "" : args[2]; 705 mHal.dumpPropertyValueByCommend(writer, propId, areaId); 706 break; 707 case COMMAND_PROJECTION_UI_MODE: 708 if (args.length != 2) { 709 writer.println("Incorrect number of arguments"); 710 dumpHelp(writer); 711 break; 712 } 713 mCarProjectionService.setUiMode(Integer.valueOf(args[1])); 714 break; 715 case COMMAND_PROJECTION_AP_TETHERING: 716 if (args.length != 2) { 717 writer.println("Incorrect number of arguments"); 718 dumpHelp(writer); 719 break; 720 } 721 mCarProjectionService.setAccessPointTethering(Boolean.valueOf(args[1])); 722 break; 723 case COMMAND_RESUME: 724 mCarPowerManagementService.forceSimulatedResume(); 725 writer.println("Resume: Simulating resuming from Deep Sleep"); 726 break; 727 case COMMAND_SUSPEND: 728 mCarPowerManagementService.forceSuspendAndMaybeReboot(false); 729 writer.println("Resume: Simulating powering down to Deep Sleep"); 730 break; 731 case COMMAND_ENABLE_TRUSTED_DEVICE: 732 if (args.length != 2) { 733 writer.println("Incorrect number of arguments"); 734 dumpHelp(writer); 735 break; 736 } 737 mCarTrustedDeviceService.getCarTrustAgentEnrollmentService() 738 .setTrustedDeviceEnrollmentEnabled(Boolean.valueOf(args[1])); 739 mCarTrustedDeviceService.getCarTrustAgentUnlockService() 740 .setTrustedDeviceUnlockEnabled(Boolean.valueOf(args[1])); 741 break; 742 case COMMAND_REMOVE_TRUSTED_DEVICES: 743 mCarTrustedDeviceService.getCarTrustAgentEnrollmentService() 744 .removeAllTrustedDevices( 745 mUserManagerHelper.getCurrentForegroundUserId()); 746 break; 747 case COMMAND_START_FIXED_ACTIVITY_MODE: 748 handleStartFixedActivity(args, writer); 749 break; 750 case COMMAND_STOP_FIXED_ACTIVITY_MODE: 751 handleStopFixedMode(args, writer); 752 break; 753 754 case COMMAND_INJECT_KEY: 755 if (args.length < 2) { 756 writer.println("Incorrect number of arguments"); 757 dumpHelp(writer); 758 break; 759 } 760 handleInjectKey(args, writer); 761 break; 762 default: 763 writer.println("Unknown command: \"" + arg + "\""); 764 dumpHelp(writer); 765 } 766 } 767 768 private void handleStartFixedActivity(String[] args, PrintWriter writer) { 769 if (args.length != 4) { 770 writer.println("Incorrect number of arguments"); 771 dumpHelp(writer); 772 return; 773 } 774 int displayId; 775 try { 776 displayId = Integer.parseInt(args[1]); 777 } catch (NumberFormatException e) { 778 writer.println("Wrong display id:" + args[1]); 779 return; 780 } 781 String packageName = args[2]; 782 String activityName = args[3]; 783 Intent intent = new Intent(); 784 intent.setComponent(new ComponentName(packageName, activityName)); 785 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 786 ActivityOptions options = ActivityOptions.makeBasic(); 787 options.setLaunchDisplayId(displayId); 788 if (!mFixedActivityService.startFixedActivityModeForDisplayAndUser(intent, options, 789 displayId, ActivityManager.getCurrentUser())) { 790 writer.println("Failed to start"); 791 return; 792 } 793 writer.println("Succeeded"); 794 } 795 796 private void handleStopFixedMode(String[] args, PrintWriter writer) { 797 if (args.length != 2) { 798 writer.println("Incorrect number of arguments"); 799 dumpHelp(writer); 800 return; 801 } 802 int displayId; 803 try { 804 displayId = Integer.parseInt(args[1]); 805 } catch (NumberFormatException e) { 806 writer.println("Wrong display id:" + args[1]); 807 return; 808 } 809 mFixedActivityService.stopFixedActivityMode(displayId); 810 } 811 812 private void handleInjectKey(String[] args, PrintWriter writer) { 813 int i = 1; // 0 is command itself 814 int display = InputHalService.DISPLAY_MAIN; 815 int delayMs = 0; 816 int keyCode = KeyEvent.KEYCODE_UNKNOWN; 817 try { 818 while (i < args.length) { 819 switch (args[i]) { 820 case "-d": 821 i++; 822 display = Integer.parseInt(args[i]); 823 break; 824 case "-t": 825 i++; 826 delayMs = Integer.parseInt(args[i]); 827 break; 828 default: 829 if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { 830 throw new IllegalArgumentException("key_code already set:" 831 + keyCode); 832 } 833 keyCode = Integer.parseInt(args[i]); 834 } 835 i++; 836 } 837 } catch (Exception e) { 838 writer.println("Invalid args:" + e); 839 dumpHelp(writer); 840 return; 841 } 842 if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { 843 writer.println("Missing key code or invalid keycode"); 844 dumpHelp(writer); 845 return; 846 } 847 if (display != InputHalService.DISPLAY_MAIN 848 && display != InputHalService.DISPLAY_INSTRUMENT_CLUSTER) { 849 writer.println("Invalid display:" + display); 850 dumpHelp(writer); 851 return; 852 } 853 if (delayMs < 0) { 854 writer.println("Invalid delay:" + delayMs); 855 dumpHelp(writer); 856 return; 857 } 858 KeyEvent keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); 859 mCarInputService.onKeyEvent(keyDown, display); 860 SystemClock.sleep(delayMs); 861 KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, keyCode); 862 mCarInputService.onKeyEvent(keyUp, display); 863 writer.println("Succeeded"); 864 } 865 866 private void forceDayNightMode(String arg, PrintWriter writer) { 867 int mode; 868 switch (arg) { 869 case PARAM_DAY_MODE: 870 mode = CarNightService.FORCED_DAY_MODE; 871 break; 872 case PARAM_NIGHT_MODE: 873 mode = CarNightService.FORCED_NIGHT_MODE; 874 break; 875 case PARAM_SENSOR_MODE: 876 mode = CarNightService.FORCED_SENSOR_MODE; 877 break; 878 default: 879 writer.println("Unknown value. Valid argument: " + PARAM_DAY_MODE + "|" 880 + PARAM_NIGHT_MODE + "|" + PARAM_SENSOR_MODE); 881 return; 882 } 883 int current = mCarNightService.forceDayNightMode(mode); 884 String currentMode = null; 885 switch (current) { 886 case UiModeManager.MODE_NIGHT_AUTO: 887 currentMode = PARAM_SENSOR_MODE; 888 break; 889 case UiModeManager.MODE_NIGHT_YES: 890 currentMode = PARAM_NIGHT_MODE; 891 break; 892 case UiModeManager.MODE_NIGHT_NO: 893 currentMode = PARAM_DAY_MODE; 894 break; 895 } 896 writer.println("DayNightMode changed to: " + currentMode); 897 } 898 899 private void forceGarageMode(String arg, PrintWriter writer) { 900 switch (arg) { 901 case PARAM_ON_MODE: 902 mGarageModeService.forceStartGarageMode(); 903 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 904 break; 905 case PARAM_OFF_MODE: 906 mGarageModeService.stopAndResetGarageMode(); 907 writer.println("Garage mode: " + mGarageModeService.isGarageModeActive()); 908 break; 909 case PARAM_QUERY_MODE: 910 mGarageModeService.dump(writer); 911 break; 912 case PARAM_REBOOT: 913 mCarPowerManagementService.forceSuspendAndMaybeReboot(true); 914 writer.println("Entering Garage Mode. Will reboot when it completes."); 915 break; 916 default: 917 writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|" 918 + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE + "|" + PARAM_REBOOT); 919 } 920 } 921 922 /** 923 * Inject a fake VHAL event 924 * 925 * @param property the Vehicle property Id as defined in the HAL 926 * @param zone Zone that this event services 927 * @param isErrorEvent indicates the type of event 928 * @param value Data value of the event 929 * @param writer PrintWriter 930 */ 931 private void injectVhalEvent(String property, String zone, String value, 932 boolean isErrorEvent, PrintWriter writer) { 933 if (zone != null && (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL))) { 934 if (!isPropertyAreaTypeGlobal(property)) { 935 writer.println("Property area type inconsistent with given zone"); 936 return; 937 } 938 } 939 try { 940 if (isErrorEvent) { 941 mHal.injectOnPropertySetError(property, zone, value); 942 } else { 943 mHal.injectVhalEvent(property, zone, value); 944 } 945 } catch (NumberFormatException e) { 946 writer.println("Invalid property Id zone Id or value" + e); 947 dumpHelp(writer); 948 } 949 } 950 951 // Check if the given property is global 952 private boolean isPropertyAreaTypeGlobal(String property) { 953 if (property == null) { 954 return false; 955 } 956 return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL; 957 } 958 } 959 } 960