ICarImpl.java revision 3838830086d818960d556841427a2e415a7999c5
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 17package com.android.car; 18 19import android.annotation.MainThread; 20import android.app.UiModeManager; 21import android.car.Car; 22import android.car.ICar; 23import android.car.cluster.renderer.IInstrumentClusterNavigation; 24import android.content.Context; 25import android.content.pm.PackageManager; 26import android.hardware.automotive.vehicle.V2_0.IVehicle; 27import android.hardware.automotive.vehicle.V2_0.VehicleArea; 28import android.os.Binder; 29import android.os.IBinder; 30import android.os.Process; 31import android.os.Trace; 32import android.util.Log; 33import android.util.Slog; 34import android.util.TimingsTraceLog; 35import com.android.car.cluster.InstrumentClusterService; 36import com.android.car.hal.VehicleHal; 37import com.android.car.internal.FeatureConfiguration; 38import com.android.car.pm.CarPackageManagerService; 39import com.android.car.systeminterface.SystemInterface; 40import com.android.internal.annotations.GuardedBy; 41import com.android.internal.car.ICarServiceHelper; 42import java.io.PrintWriter; 43import java.util.ArrayList; 44import java.util.Arrays; 45import java.util.List; 46 47public class ICarImpl extends ICar.Stub { 48 49 public static final String INTERNAL_INPUT_SERVICE = "internal_input"; 50 public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE = 51 "system_activity_monitoring"; 52 53 private final Context mContext; 54 private final VehicleHal mHal; 55 56 private final SystemActivityMonitoringService mSystemActivityMonitoringService; 57 private final CarPowerManagementService mCarPowerManagementService; 58 private final CarPackageManagerService mCarPackageManagerService; 59 private final CarInputService mCarInputService; 60 private final CarSensorService mCarSensorService; 61 private final CarDrivingStateService mCarDrivingStateService; 62 private final CarUxRestrictionsManagerService mCarUXRestrictionsService; 63 private final CarInfoService mCarInfoService; 64 private final CarAudioService mCarAudioService; 65 private final CarProjectionService mCarProjectionService; 66 private final CarCabinService mCarCabinService; 67 private final CarHvacService mCarHvacService; 68 private final CarRadioService mCarRadioService; 69 private final CarNightService mCarNightService; 70 private final AppFocusService mAppFocusService; 71 private final GarageModeService mGarageModeService; 72 private final InstrumentClusterService mInstrumentClusterService; 73 private final CarLocationService mCarLocationService; 74 private final SystemStateControllerService mSystemStateControllerService; 75 private final CarVendorExtensionService mCarVendorExtensionService; 76 private final CarBluetoothService mCarBluetoothService; 77 private final PerUserCarServiceHelper mPerUserCarServiceHelper; 78 private final CarDiagnosticService mCarDiagnosticService; 79 private final CarStorageMonitoringService mCarStorageMonitoringService; 80 private final SystemInterface mSystemInterface; 81 private VmsSubscriberService mVmsSubscriberService; 82 private VmsPublisherService mVmsPublisherService; 83 84 private final CarServiceBase[] mAllServices; 85 86 private static final String TAG = "ICarImpl"; 87 private static final String VHAL_TIMING_TAG = "VehicleHalTiming"; 88 private static final TimingsTraceLog mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, 89 Trace.TRACE_TAG_HAL); 90 91 /** Test only service. Populate it only when necessary. */ 92 @GuardedBy("this") 93 private CarTestService mCarTestService; 94 95 @GuardedBy("this") 96 private ICarServiceHelper mICarServiceHelper; 97 98 public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, 99 CanBusErrorNotifier errorNotifier) { 100 mContext = serviceContext; 101 mSystemInterface = systemInterface; 102 mHal = new VehicleHal(vehicle); 103 mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext); 104 mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(), 105 systemInterface); 106 mCarSensorService = new CarSensorService(serviceContext, mHal.getSensorHal()); 107 mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarSensorService); 108 mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext, 109 mCarDrivingStateService); 110 mCarPackageManagerService = new CarPackageManagerService(serviceContext, 111 mCarUXRestrictionsService, 112 mSystemActivityMonitoringService); 113 mCarInputService = new CarInputService(serviceContext, mHal.getInputHal()); 114 mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService); 115 mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService); 116 mCarLocationService = new CarLocationService(mContext, mCarSensorService); 117 mCarInfoService = new CarInfoService(serviceContext, mHal.getInfoHal()); 118 mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService); 119 mCarAudioService = new CarAudioService(serviceContext); 120 mCarCabinService = new CarCabinService(serviceContext, mHal.getCabinHal()); 121 mCarHvacService = new CarHvacService(serviceContext, mHal.getHvacHal()); 122 mCarRadioService = new CarRadioService(serviceContext, mHal.getRadioHal()); 123 mCarNightService = new CarNightService(serviceContext, mCarSensorService); 124 mInstrumentClusterService = new InstrumentClusterService(serviceContext, 125 mAppFocusService, mCarInputService); 126 mSystemStateControllerService = new SystemStateControllerService(serviceContext, 127 mCarPowerManagementService, mCarAudioService, this); 128 mCarVendorExtensionService = new CarVendorExtensionService(serviceContext, 129 mHal.getVendorExtensionHal()); 130 mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext); 131 mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService, 132 mCarSensorService, mPerUserCarServiceHelper); 133 mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal()); 134 mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal()); 135 mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal()); 136 mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext, 137 systemInterface); 138 139 // Be careful with order. Service depending on other service should be inited later. 140 List<CarServiceBase> allServices = new ArrayList<>(Arrays.asList( 141 mSystemActivityMonitoringService, 142 mCarPowerManagementService, 143 mCarSensorService, 144 mCarDrivingStateService, 145 mCarUXRestrictionsService, 146 mCarPackageManagerService, 147 mCarInputService, 148 mCarLocationService, 149 mGarageModeService, 150 mCarInfoService, 151 mAppFocusService, 152 mCarAudioService, 153 mCarCabinService, 154 mCarHvacService, 155 mCarRadioService, 156 mCarNightService, 157 mInstrumentClusterService, 158 mCarProjectionService, 159 mSystemStateControllerService, 160 mCarVendorExtensionService, 161 mCarBluetoothService, 162 mCarDiagnosticService, 163 mPerUserCarServiceHelper, 164 mCarStorageMonitoringService, 165 mVmsSubscriberService, 166 mVmsPublisherService 167 )); 168 mAllServices = allServices.toArray(new CarServiceBase[0]); 169 } 170 171 @MainThread 172 void init() { 173 traceBegin("VehicleHal.init"); 174 mHal.init(); 175 traceEnd(); 176 traceBegin("CarService.initAllServices"); 177 for (CarServiceBase service : mAllServices) { 178 service.init(); 179 } 180 traceEnd(); 181 } 182 183 void release() { 184 // release done in opposite order from init 185 for (int i = mAllServices.length - 1; i >= 0; i--) { 186 mAllServices[i].release(); 187 } 188 mHal.release(); 189 } 190 191 void vehicleHalReconnected(IVehicle vehicle) { 192 mHal.vehicleHalReconnected(vehicle); 193 for (CarServiceBase service : mAllServices) { 194 service.vehicleHalReconnected(); 195 } 196 } 197 198 @Override 199 public void setCarServiceHelper(IBinder helper) { 200 int uid = Binder.getCallingUid(); 201 if (uid != Process.SYSTEM_UID) { 202 throw new SecurityException("Only allowed from system"); 203 } 204 synchronized (this) { 205 mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper); 206 mSystemInterface.setCarServiceHelper(mICarServiceHelper); 207 } 208 } 209 210 @Override 211 public IBinder getCarService(String serviceName) { 212 switch (serviceName) { 213 case Car.AUDIO_SERVICE: 214 return mCarAudioService; 215 case Car.SENSOR_SERVICE: 216 return mCarSensorService; 217 case Car.INFO_SERVICE: 218 return mCarInfoService; 219 case Car.APP_FOCUS_SERVICE: 220 return mAppFocusService; 221 case Car.PACKAGE_SERVICE: 222 return mCarPackageManagerService; 223 case Car.CABIN_SERVICE: 224 assertCabinPermission(mContext); 225 return mCarCabinService; 226 case Car.DIAGNOSTIC_SERVICE: 227 assertAnyDiagnosticPermission(mContext); 228 return mCarDiagnosticService; 229 case Car.HVAC_SERVICE: 230 assertHvacPermission(mContext); 231 return mCarHvacService; 232 case Car.POWER_SERVICE: 233 assertPowerPermission(mContext); 234 return mCarPowerManagementService; 235 case Car.RADIO_SERVICE: 236 assertRadioPermission(mContext); 237 return mCarRadioService; 238 case Car.CAR_NAVIGATION_SERVICE: 239 assertNavigationManagerPermission(mContext); 240 IInstrumentClusterNavigation navService = 241 mInstrumentClusterService.getNavigationService(); 242 return navService == null ? null : navService.asBinder(); 243 case Car.CAR_INSTRUMENT_CLUSTER_SERVICE: 244 assertClusterManagerPermission(mContext); 245 return mInstrumentClusterService.getManagerService(); 246 case Car.PROJECTION_SERVICE: 247 assertProjectionPermission(mContext); 248 return mCarProjectionService; 249 case Car.VENDOR_EXTENSION_SERVICE: 250 assertVendorExtensionPermission(mContext); 251 return mCarVendorExtensionService; 252 case Car.VMS_SUBSCRIBER_SERVICE: 253 assertVmsSubscriberPermission(mContext); 254 return mVmsSubscriberService; 255 case Car.TEST_SERVICE: { 256 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE); 257 synchronized (this) { 258 if (mCarTestService == null) { 259 mCarTestService = new CarTestService(mContext, this); 260 } 261 return mCarTestService; 262 } 263 } 264 case Car.BLUETOOTH_SERVICE: 265 return mCarBluetoothService; 266 case Car.STORAGE_MONITORING_SERVICE: 267 assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING); 268 return mCarStorageMonitoringService; 269 case Car.CAR_DRIVING_STATE_SERVICE: 270 assertDrivingStatePermission(mContext); 271 return mCarDrivingStateService; 272 case Car.CAR_UX_RESTRICTION_SERVICE: 273 return mCarUXRestrictionsService; 274 default: 275 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName); 276 return null; 277 } 278 } 279 280 @Override 281 public int getCarConnectionType() { 282 return Car.CONNECTION_TYPE_EMBEDDED; 283 } 284 285 public CarServiceBase getCarInternalService(String serviceName) { 286 switch (serviceName) { 287 case INTERNAL_INPUT_SERVICE: 288 return mCarInputService; 289 case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE: 290 return mSystemActivityMonitoringService; 291 default: 292 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" + 293 serviceName); 294 return null; 295 } 296 } 297 298 public static void assertVehicleHalMockPermission(Context context) { 299 assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL); 300 } 301 302 public static void assertCabinPermission(Context context) { 303 assertPermission(context, Car.PERMISSION_CAR_CABIN); 304 } 305 306 public static void assertNavigationManagerPermission(Context context) { 307 assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER); 308 } 309 310 public static void assertClusterManagerPermission(Context context) { 311 assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL); 312 } 313 314 public static void assertHvacPermission(Context context) { 315 assertPermission(context, Car.PERMISSION_CAR_HVAC); 316 } 317 318 public static void assertPowerPermission(Context context) { 319 assertPermission(context, Car.PERMISSION_CAR_POWER); 320 } 321 322 private static void assertRadioPermission(Context context) { 323 assertPermission(context, Car.PERMISSION_CAR_RADIO); 324 } 325 326 public static void assertProjectionPermission(Context context) { 327 assertPermission(context, Car.PERMISSION_CAR_PROJECTION); 328 } 329 330 public static void assertVendorExtensionPermission(Context context) { 331 assertPermission(context, Car.PERMISSION_VENDOR_EXTENSION); 332 } 333 334 public static void assertAnyDiagnosticPermission(Context context) { 335 assertAnyPermission(context, 336 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL, 337 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR); 338 } 339 340 public static void assertDrivingStatePermission(Context context) { 341 assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE); 342 } 343 344 public static void assertVmsPublisherPermission(Context context) { 345 assertPermission(context, Car.PERMISSION_VMS_PUBLISHER); 346 } 347 348 public static void assertVmsSubscriberPermission(Context context) { 349 assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER); 350 } 351 352 public static void assertPermission(Context context, String permission) { 353 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 354 throw new SecurityException("requires " + permission); 355 } 356 } 357 358 public static void assertAnyPermission(Context context, String... permissions) { 359 for (String permission : permissions) { 360 if (context.checkCallingOrSelfPermission(permission) == 361 PackageManager.PERMISSION_GRANTED) { 362 return; 363 } 364 } 365 throw new SecurityException("requires any of " + Arrays.toString(permissions)); 366 } 367 368 void dump(PrintWriter writer) { 369 writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT); 370 writer.println("*Dump all services*"); 371 for (CarServiceBase service : mAllServices) { 372 dumpService(service, writer); 373 } 374 if (mCarTestService != null) { 375 dumpService(mCarTestService, writer); 376 } 377 writer.println("*Dump Vehicle HAL*"); 378 try { 379 // TODO dump all feature flags by creating a dumpable interface 380 mHal.dump(writer); 381 } catch (Exception e) { 382 writer.println("Failed dumping: " + mHal.getClass().getName()); 383 e.printStackTrace(writer); 384 } 385 } 386 387 private void dumpService(CarServiceBase service, PrintWriter writer) { 388 try { 389 service.dump(writer); 390 } catch (Exception e) { 391 writer.println("Failed dumping: " + service.getClass().getName()); 392 e.printStackTrace(writer); 393 } 394 } 395 396 void execShellCmd(String[] args, PrintWriter writer) { 397 new CarShellCommand().exec(args, writer); 398 } 399 400 @MainThread 401 private static void traceBegin(String name) { 402 Slog.i(TAG, name); 403 mBootTiming.traceBegin(name); 404 } 405 406 @MainThread 407 private static void traceEnd() { 408 mBootTiming.traceEnd(); 409 } 410 411 private class CarShellCommand { 412 private static final String COMMAND_HELP = "-h"; 413 private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode"; 414 private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event"; 415 private static final String COMMAND_ENABLE_UXR = "enable-uxr"; 416 private static final String COMMAND_GARAGE_MODE = "garage-mode"; 417 private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities"; 418 419 private static final String PARAM_DAY_MODE = "day"; 420 private static final String PARAM_NIGHT_MODE = "night"; 421 private static final String PARAM_SENSOR_MODE = "sensor"; 422 private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0"; 423 private static final String PARAM_ON_MODE = "on"; 424 private static final String PARAM_OFF_MODE = "off"; 425 private static final String PARAM_QUERY_MODE = "query"; 426 427 428 private void dumpHelp(PrintWriter pw) { 429 pw.println("Car service commands:"); 430 pw.println("\t-h"); 431 pw.println("\t Print this help text."); 432 pw.println("\tday-night-mode [day|night|sensor]"); 433 pw.println("\t Force into day/night mode or restore to auto."); 434 pw.println("\tinject-vhal-event property [zone] data(can be comma separated list)"); 435 pw.println("\t Inject a vehicle property for testing"); 436 pw.println("\tdisable-uxr true|false"); 437 pw.println("\t Disable UX restrictions and App blocking."); 438 pw.println("\tgarage-mode [on|off|query]"); 439 pw.println("\t Force into garage mode or check status."); 440 pw.println("\tget-do-activities pkgname"); 441 pw.println("\t Get Distraction Optimized activities in given package"); 442 } 443 444 public void exec(String[] args, PrintWriter writer) { 445 String arg = args[0]; 446 switch (arg) { 447 case COMMAND_HELP: 448 dumpHelp(writer); 449 break; 450 case COMMAND_DAY_NIGHT_MODE: { 451 String value = args.length < 1 ? "" : args[1]; 452 forceDayNightMode(value, writer); 453 break; 454 } 455 case COMMAND_GARAGE_MODE: { 456 String value = args.length < 1 ? "" : args[1]; 457 forceGarageMode(value, writer); 458 break; 459 } 460 case COMMAND_INJECT_VHAL_EVENT: 461 String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL; 462 String data; 463 if (args.length < 3) { 464 writer.println("Incorrect number of arguments."); 465 dumpHelp(writer); 466 break; 467 } else if (args.length > 3) { 468 // Zoned 469 zone = args[2]; 470 data = args[3]; 471 } else { 472 // Global 473 data = args[2]; 474 } 475 injectVhalEvent(args[1], zone, data, writer); 476 break; 477 case COMMAND_ENABLE_UXR: 478 if (args.length < 2) { 479 writer.println("Incorrect number of arguments"); 480 dumpHelp(writer); 481 break; 482 } 483 boolean enableBlocking = Boolean.valueOf(args[1]); 484 if (mCarPackageManagerService != null) { 485 mCarPackageManagerService.setEnableActivityBlocking(enableBlocking); 486 } 487 break; 488 case COMMAND_GET_DO_ACTIVITIES: 489 if (args.length < 2) { 490 writer.println("Incorrect number of arguments"); 491 dumpHelp(writer); 492 break; 493 } 494 String pkgName = args[1].toLowerCase(); 495 if (mCarPackageManagerService != null) { 496 String[] doActivities = 497 mCarPackageManagerService.getDistractionOptimizedActivities( 498 pkgName); 499 if (doActivities != null) { 500 writer.println("DO Activities for " + pkgName); 501 for (String a : doActivities) { 502 writer.println(a); 503 } 504 } else { 505 writer.println("No DO Activities for " + pkgName); 506 } 507 } 508 break; 509 default: 510 writer.println("Unknown command."); 511 dumpHelp(writer); 512 } 513 } 514 515 private void forceDayNightMode(String arg, PrintWriter writer) { 516 int mode; 517 switch (arg) { 518 case PARAM_DAY_MODE: 519 mode = CarNightService.FORCED_DAY_MODE; 520 break; 521 case PARAM_NIGHT_MODE: 522 mode = CarNightService.FORCED_NIGHT_MODE; 523 break; 524 case PARAM_SENSOR_MODE: 525 mode = CarNightService.FORCED_SENSOR_MODE; 526 break; 527 default: 528 writer.println("Unknown value. Valid argument: " + PARAM_DAY_MODE + "|" 529 + PARAM_NIGHT_MODE + "|" + PARAM_SENSOR_MODE); 530 return; 531 } 532 int current = mCarNightService.forceDayNightMode(mode); 533 String currentMode = null; 534 switch (current) { 535 case UiModeManager.MODE_NIGHT_AUTO: 536 currentMode = PARAM_SENSOR_MODE; 537 break; 538 case UiModeManager.MODE_NIGHT_YES: 539 currentMode = PARAM_NIGHT_MODE; 540 break; 541 case UiModeManager.MODE_NIGHT_NO: 542 currentMode = PARAM_DAY_MODE; 543 break; 544 } 545 writer.println("DayNightMode changed to: " + currentMode); 546 } 547 548 private void forceGarageMode(String arg, PrintWriter writer) { 549 switch (arg) { 550 case PARAM_ON_MODE: 551 mGarageModeService.onPrepareShutdown(false); 552 break; 553 case PARAM_OFF_MODE: 554 mGarageModeService.onSleepEntry(); 555 break; 556 case PARAM_QUERY_MODE: 557 // Nothing to do. Always query at the end anyway. 558 break; 559 default: 560 writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|" 561 + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE); 562 return; 563 } 564 writer.println("Garage mode: " + mGarageModeService.isInGarageMode()); 565 } 566 567 /** 568 * Inject a fake VHAL event 569 * 570 * @param property the Vehicle property Id as defined in the HAL 571 * @param zone Zone that this event services 572 * @param value Data value of the event 573 * @param writer PrintWriter 574 */ 575 private void injectVhalEvent(String property, String zone, String value, 576 PrintWriter writer) { 577 if (zone != null && (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL))) { 578 if (!isPropertyAreaTypeGlobal(property)) { 579 writer.println("Property area type inconsistent with given zone"); 580 return; 581 } 582 } 583 try { 584 mHal.injectVhalEvent(property, zone, value); 585 } catch (NumberFormatException e) { 586 writer.println("Invalid property Id zone Id or value" + e); 587 dumpHelp(writer); 588 } 589 } 590 591 // Check if the given property is global 592 private boolean isPropertyAreaTypeGlobal(String property) { 593 if (property == null) { 594 return false; 595 } 596 return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL; 597 } 598 } 599} 600