ICarImpl.java revision a048c0a3b653982a8a5560f9202f71cfc4d338e8
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.app.UiModeManager; 20import android.car.Car; 21import android.car.ICar; 22import android.car.annotation.FutureFeature; 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.VehicleAreaDoor; 28import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 29import android.os.IBinder; 30import android.util.Log; 31 32import com.android.car.cluster.InstrumentClusterService; 33import com.android.car.hal.VehicleHal; 34import com.android.car.internal.FeatureConfiguration; 35import com.android.car.internal.FeatureUtil; 36import com.android.car.pm.CarPackageManagerService; 37import com.android.internal.annotations.GuardedBy; 38 39import java.io.PrintWriter; 40import java.util.ArrayList; 41import java.util.Arrays; 42import java.util.List; 43 44public class ICarImpl extends ICar.Stub { 45 46 public static final String INTERNAL_INPUT_SERVICE = "internal_input"; 47 public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE = 48 "system_activity_monitoring"; 49 50 private final Context mContext; 51 private final VehicleHal mHal; 52 53 private final SystemActivityMonitoringService mSystemActivityMonitoringService; 54 private final CarPowerManagementService mCarPowerManagementService; 55 private final CarPackageManagerService mCarPackageManagerService; 56 private final CarInputService mCarInputService; 57 private final CarSensorService mCarSensorService; 58 private final CarInfoService mCarInfoService; 59 private final CarAudioService mCarAudioService; 60 private final CarProjectionService mCarProjectionService; 61 private final CarCabinService mCarCabinService; 62 private final CarHvacService mCarHvacService; 63 private final CarRadioService mCarRadioService; 64 private final CarNightService mCarNightService; 65 private final AppFocusService mAppFocusService; 66 private final GarageModeService mGarageModeService; 67 private final InstrumentClusterService mInstrumentClusterService; 68 private final SystemStateControllerService mSystemStateControllerService; 69 private final CarVendorExtensionService mCarVendorExtensionService; 70 private final CarBluetoothService mCarBluetoothService; 71 private final PerUserCarServiceHelper mPerUserCarServiceHelper; 72 @FutureFeature 73 private CarDiagnosticService mCarDiagnosticService; 74 @FutureFeature 75 private VmsSubscriberService mVmsSubscriberService; 76 @FutureFeature 77 private VmsPublisherService mVmsPublisherService; 78 79 private final CarServiceBase[] mAllServices; 80 81 /** Test only service. Populate it only when necessary. */ 82 @GuardedBy("this") 83 private CarTestService mCarTestService; 84 85 public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, 86 CanBusErrorNotifier errorNotifier) { 87 mContext = serviceContext; 88 mHal = new VehicleHal(vehicle); 89 mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext); 90 mCarPowerManagementService = new CarPowerManagementService( 91 mHal.getPowerHal(), systemInterface); 92 mCarSensorService = new CarSensorService(serviceContext, mHal.getSensorHal()); 93 mCarPackageManagerService = new CarPackageManagerService(serviceContext, mCarSensorService, 94 mSystemActivityMonitoringService); 95 mCarInputService = new CarInputService(serviceContext, mHal.getInputHal()); 96 mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService); 97 mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService); 98 mCarInfoService = new CarInfoService(serviceContext, mHal.getInfoHal()); 99 mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService); 100 mCarAudioService = new CarAudioService(serviceContext, mHal.getAudioHal(), 101 mCarInputService, errorNotifier); 102 mCarCabinService = new CarCabinService(serviceContext, mHal.getCabinHal()); 103 mCarHvacService = new CarHvacService(serviceContext, mHal.getHvacHal()); 104 mCarRadioService = new CarRadioService(serviceContext, mHal.getRadioHal()); 105 mCarNightService = new CarNightService(serviceContext, mCarSensorService); 106 mInstrumentClusterService = new InstrumentClusterService(serviceContext, 107 mAppFocusService, mCarInputService); 108 mSystemStateControllerService = new SystemStateControllerService(serviceContext, 109 mCarPowerManagementService, mCarAudioService, this); 110 mCarVendorExtensionService = new CarVendorExtensionService(serviceContext, 111 mHal.getVendorExtensionHal()); 112 mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext); 113 mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService, 114 mCarSensorService, mPerUserCarServiceHelper); 115 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) { 116 mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal()); 117 mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal()); 118 } 119 mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal()); 120 121 // Be careful with order. Service depending on other service should be inited later. 122 List<CarServiceBase> allServices = new ArrayList<>(Arrays.asList( 123 mSystemActivityMonitoringService, 124 mCarPowerManagementService, 125 mCarSensorService, 126 mCarPackageManagerService, 127 mCarInputService, 128 mGarageModeService, 129 mCarInfoService, 130 mAppFocusService, 131 mCarAudioService, 132 mCarCabinService, 133 mCarHvacService, 134 mCarRadioService, 135 mCarNightService, 136 mInstrumentClusterService, 137 mCarProjectionService, 138 mSystemStateControllerService, 139 mCarVendorExtensionService, 140 mCarBluetoothService, 141 mCarDiagnosticService, 142 mPerUserCarServiceHelper 143 )); 144 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) { 145 allServices.add(mVmsSubscriberService); 146 allServices.add(mVmsPublisherService); 147 } 148 mAllServices = allServices.toArray(new CarServiceBase[0]); 149 } 150 151 public void init() { 152 mHal.init(); 153 for (CarServiceBase service : mAllServices) { 154 service.init(); 155 } 156 } 157 158 public void release() { 159 // release done in opposite order from init 160 for (int i = mAllServices.length - 1; i >= 0; i--) { 161 mAllServices[i].release(); 162 } 163 mHal.release(); 164 } 165 166 public void vehicleHalReconnected(IVehicle vehicle) { 167 mHal.vehicleHalReconnected(vehicle); 168 for (CarServiceBase service : mAllServices) { 169 service.vehicleHalReconnected(); 170 } 171 } 172 173 @Override 174 public IBinder getCarService(String serviceName) { 175 switch (serviceName) { 176 case Car.AUDIO_SERVICE: 177 return mCarAudioService; 178 case Car.SENSOR_SERVICE: 179 return mCarSensorService; 180 case Car.INFO_SERVICE: 181 return mCarInfoService; 182 case Car.APP_FOCUS_SERVICE: 183 return mAppFocusService; 184 case Car.PACKAGE_SERVICE: 185 return mCarPackageManagerService; 186 case Car.CABIN_SERVICE: 187 assertCabinPermission(mContext); 188 return mCarCabinService; 189 case Car.DIAGNOSTIC_SERVICE: 190 assertAnyDiagnosticPermission(mContext); 191 return mCarDiagnosticService; 192 case Car.HVAC_SERVICE: 193 assertHvacPermission(mContext); 194 return mCarHvacService; 195 case Car.RADIO_SERVICE: 196 assertRadioPermission(mContext); 197 return mCarRadioService; 198 case Car.CAR_NAVIGATION_SERVICE: 199 assertNavigationManagerPermission(mContext); 200 IInstrumentClusterNavigation navService = 201 mInstrumentClusterService.getNavigationService(); 202 return navService == null ? null : navService.asBinder(); 203 case Car.PROJECTION_SERVICE: 204 assertProjectionPermission(mContext); 205 return mCarProjectionService; 206 case Car.VENDOR_EXTENSION_SERVICE: 207 assertVendorExtensionPermission(mContext); 208 return mCarVendorExtensionService; 209 case Car.VMS_SUBSCRIBER_SERVICE: 210 FeatureUtil.assertFeature(FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE); 211 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) { 212 assertVmsSubscriberPermission(mContext); 213 return mVmsSubscriberService; 214 } 215 case Car.TEST_SERVICE: { 216 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE); 217 synchronized (this) { 218 if (mCarTestService == null) { 219 mCarTestService = new CarTestService(mContext, this); 220 } 221 return mCarTestService; 222 } 223 } 224 default: 225 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName); 226 return null; 227 } 228 } 229 230 @Override 231 public int getCarConnectionType() { 232 return Car.CONNECTION_TYPE_EMBEDDED; 233 } 234 235 public CarServiceBase getCarInternalService(String serviceName) { 236 switch (serviceName) { 237 case INTERNAL_INPUT_SERVICE: 238 return mCarInputService; 239 case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE: 240 return mSystemActivityMonitoringService; 241 default: 242 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" + 243 serviceName); 244 return null; 245 } 246 } 247 248 public static void assertVehicleHalMockPermission(Context context) { 249 assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL); 250 } 251 252 public static void assertCabinPermission(Context context) { 253 assertPermission(context, Car.PERMISSION_CAR_CABIN); 254 } 255 256 public static void assertNavigationManagerPermission(Context context) { 257 assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER); 258 } 259 260 public static void assertHvacPermission(Context context) { 261 assertPermission(context, Car.PERMISSION_CAR_HVAC); 262 } 263 264 private static void assertRadioPermission(Context context) { 265 assertPermission(context, Car.PERMISSION_CAR_RADIO); 266 } 267 268 public static void assertProjectionPermission(Context context) { 269 assertPermission(context, Car.PERMISSION_CAR_PROJECTION); 270 } 271 272 public static void assertVendorExtensionPermission(Context context) { 273 assertPermission(context, Car.PERMISSION_VENDOR_EXTENSION); 274 } 275 276 @FutureFeature 277 public static void assertAnyDiagnosticPermission(Context context) { 278 assertAnyPermission(context, 279 Car.PERMISSION_CAR_DIAGNOSTIC_READ, 280 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR); 281 } 282 283 @FutureFeature 284 public static void assertVmsPublisherPermission(Context context) { 285 assertPermission(context, Car.PERMISSION_VMS_PUBLISHER); 286 } 287 288 @FutureFeature 289 public static void assertVmsSubscriberPermission(Context context) { 290 assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER); 291 } 292 293 public static void assertPermission(Context context, String permission) { 294 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 295 throw new SecurityException("requires " + permission); 296 } 297 } 298 299 public static void assertAnyPermission(Context context, String... permissions) { 300 for (String permission : permissions) { 301 if (context.checkCallingOrSelfPermission(permission) == 302 PackageManager.PERMISSION_GRANTED) { 303 return; 304 } 305 } 306 throw new SecurityException("requires any of " + Arrays.toString(permissions)); 307 } 308 309 void dump(PrintWriter writer) { 310 writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT); 311 //TODO dump all feature flags by reflection 312 writer.println("*Dump all services*"); 313 for (CarServiceBase service : mAllServices) { 314 service.dump(writer); 315 } 316 if (mCarTestService != null) { 317 mCarTestService.dump(writer); 318 } 319 writer.println("*Dump Vehicle HAL*"); 320 mHal.dump(writer); 321 } 322 323 void execShellCmd(String[] args, PrintWriter writer) { 324 new CarShellCommand().exec(args, writer); 325 } 326 327 private class CarShellCommand { 328 private static final String COMMAND_HELP = "-h"; 329 private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode"; 330 private static final String COMMAND_INJECT_EVENT = "inject-event"; 331 332 private static final String PARAM_DAY_MODE = "day"; 333 private static final String PARAM_NIGHT_MODE = "night"; 334 private static final String PARAM_SENSOR_MODE = "sensor"; 335 private static final String PARAM_ZONED_BOOLEAN = "zoned-boolean"; 336 private static final String PARAM_GLOBAL_INT = "global-integer"; 337 338 private void dumpHelp(PrintWriter pw) { 339 pw.println("Car service commands:"); 340 pw.println("\t-h"); 341 pw.println("\t Print this help text."); 342 pw.println("\tday-night-mode [day|night|sensor]"); 343 pw.println("\t Force into day/night mode or restore to auto."); 344 pw.println("\tinject-event zoned-boolean propertyType zone [true|false]"); 345 pw.println("\t Inject a Boolean HAL Event. "); 346 } 347 348 public void exec(String[] args, PrintWriter writer) { 349 String arg = args[0]; 350 switch (arg) { 351 case COMMAND_HELP: 352 dumpHelp(writer); 353 break; 354 case COMMAND_DAY_NIGHT_MODE: 355 String value = args.length < 1 ? "" : args[1]; 356 forceDayNightMode(value, writer); 357 break; 358 case COMMAND_INJECT_EVENT: 359 String eventType; 360 if (args.length > 1) { 361 eventType = args[1].toLowerCase(); 362 switch (eventType) { 363 case PARAM_ZONED_BOOLEAN: 364 if (args.length < 5) { 365 writer.println("Incorrect number of arguments."); 366 dumpHelp(writer); 367 break; 368 } 369 inject_zoned_boolean_event(args[2], args[3], args[4], writer); 370 break; 371 372 case PARAM_GLOBAL_INT: 373 if (args.length < 4) { 374 writer.println("Incorrect number of Arguments"); 375 dumpHelp(writer); 376 break; 377 } 378 inject_global_integer_event(args[2], args[3], writer); 379 break; 380 381 default: 382 writer.println("Unsupported event type"); 383 dumpHelp(writer); 384 break; 385 } 386 } 387 break; 388 default: 389 writer.println("Unknown command."); 390 dumpHelp(writer); 391 } 392 } 393 394 private void forceDayNightMode(String arg, PrintWriter writer) { 395 int mode; 396 switch (arg) { 397 case PARAM_DAY_MODE: 398 mode = CarNightService.FORCED_DAY_MODE; 399 break; 400 case PARAM_NIGHT_MODE: 401 mode = CarNightService.FORCED_NIGHT_MODE; 402 break; 403 case PARAM_SENSOR_MODE: 404 mode = CarNightService.FORCED_SENSOR_MODE; 405 break; 406 default: 407 writer.println("Unknown value. Valid argument: " + PARAM_DAY_MODE + "|" 408 + PARAM_NIGHT_MODE + "|" + PARAM_SENSOR_MODE); 409 return; 410 } 411 int current = mCarNightService.forceDayNightMode(mode); 412 String currentMode = null; 413 switch (current) { 414 case UiModeManager.MODE_NIGHT_AUTO: 415 currentMode = PARAM_SENSOR_MODE; 416 break; 417 case UiModeManager.MODE_NIGHT_YES: 418 currentMode = PARAM_NIGHT_MODE; 419 break; 420 case UiModeManager.MODE_NIGHT_NO: 421 currentMode = PARAM_DAY_MODE; 422 break; 423 } 424 writer.println("DayNightMode changed to: " + currentMode); 425 } 426 427 /** 428 * Inject a fake boolean HAL event to help testing. 429 * 430 * @param property - Vehicle Property 431 * @param value - boolean value for the property 432 * @param writer - Printwriter 433 */ 434 private void inject_zoned_boolean_event(String property, String zone, String value, 435 PrintWriter writer) { 436 Log.d(CarLog.TAG_SERVICE, "Injecting Boolean event"); 437 boolean event; 438 int propId; 439 int zoneId; 440 if (value.equalsIgnoreCase("true")) { 441 event = true; 442 } else { 443 event = false; 444 } 445 try { 446 propId = Integer.decode(property); 447 zoneId = Integer.decode(zone); 448 } catch (NumberFormatException e) { 449 writer.println("Invalid property Id or Zone Id. Prefix hex values with 0x"); 450 return; 451 } 452 mHal.injectBooleanEvent(propId, zoneId, event); 453 } 454 455 /** 456 * Inject a fake Integer HAL event to help testing. 457 * 458 * @param property - Vehicle Property 459 * @param value - Integer value to inject 460 * @param writer - PrintWriter 461 */ 462 private void inject_global_integer_event(String property, String value, 463 PrintWriter writer) { 464 Log.d(CarLog.TAG_SERVICE, "Injecting integer event"); 465 int propId; 466 int eventValue; 467 try { 468 propId = Integer.decode(property); 469 eventValue = Integer.decode(value); 470 } catch (NumberFormatException e) { 471 writer.println("Invalid property Id or event value. Prefix hex values with 0x"); 472 return; 473 } 474 mHal.injectIntegerEvent(propId, eventValue); 475 } 476 477 } 478}