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