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