一、Android Car介绍
Android Automotive是Android的一部分。 Android Automotive不是Android的分支或并行开发,它与手机,平板电脑等安卓设备上的Android具有相同的代码库,并且位于相同的存储库中。 它基于经过10多年开发的强大平台和功能集,可利用现有的安全模型,兼容性程序,开发人员工具 和基础架构,同时继续具有高度可定制性和可移植性,完全免费和开源的特点。Android Automotive扩展了Android 。在将Android打造为功能齐全的信息娱乐平台的过程中,添加了对汽车特定要求,功能和技术的支持。
Android Automotive 是在原先Android的系统架构上增加了一些与车相关的模块:
1)Car App :包括OEM和第三方开发的App
2)Car API :提供给汽车App特有的接口
3)Car Service :系统中与车相关的服务,主要基于CarProperty实现Vechile相关的策略
4)Vehicle Network Service :汽车的网络服务
5)Vehicle HAL :汽车的硬件抽象层描述,定义 OEM 可以实现的车辆属性的接口
1、CarAPI
Car API是Android系统中使用Android Automotive特性的系统接口,Car API与CarService中的服务,名称上存在对应关系,所以很好理解。例如:CarWatchdogManager对应CarWatchdogService,CarMediaManager对应CarMediaService。不过也有例外:CarInfoManager、CarSensorManager、CarHvacManager、CarCabinManager、CarVendorExtensionManager都对应CarPropertyService。但是在Android 11中这些Manager都已经过时,Google建议统一使用CarPropertyManager。
2、CarService
车载Android 系统的核心服务之一,所有应用都需要通过 CarService 来查询、控制整车的状态。例如:车辆的速度、档位、点火状态等等,CarService有许多子服务,负责具体功能。
Service端 | 功能 | Client端 |
---|---|---|
AppFocusService | 应用程序焦点服务:确保一次只有一个应用程序类型的实例处于活动状态。 | CarAppFocusManager |
CarAudioService | 汽车音频服务:负责与汽车音响系统交互的服务。 | CarAudioManager |
CarPowerManagerService | 汽车电源管理服务:汽车电源管理服务。控制电源状态并与系统的其他部分交互以确保其自身状态。 | CarPowerManager |
CarPropertyService | 汽车属性服务:此类实现 ICarProperty 的binder接口。有助于更容易地创建处理车辆属性的多个Manager。 | CarPropertyManager |
CarProjectionService | 汽车投屏服务 | CarProjectionManager |
CarPackageManagerService | 汽车包管理服务 | CarPackageManager |
CarDiagnosticService | 汽车诊断服务 | CarDiagnosticManager |
CarProjecitonService | 汽车投屏服务 | CarProjecitonManager |
CarMediaService | 汽车媒体管理服务 | CarMediaManager |
CarConfigurationService | 汽车配置服务 | CarConfigurationManager |
CarBluetoothService | 汽车蓝牙服务 | CarBluetoothManager |
CarDrivingStateService | 汽车驾驶状态服务:推断车辆当前驾驶状态的服务。它通过侦听 CarPropertyService 的相关属性来计算驾驶状态。 | CarDrivingStateManager |
CarStorageMonitoringService | 汽车存储监控服务 | CarStorageMonitoringManager |
CarMediaService | 汽车媒体服务:管理汽车应用程序的当前活动媒体源。这与 MediaSessionManager 的活动会话不同,因为同一时间内车内只能有一个活动源。 | CarMediaManager |
CarInputService | 汽车输入服务:通过车辆HAL监控和处理输入事件。 | CarInputManager |
CarLocationService | 汽车定位服务:此服务在车辆停放时存储 LocationManager 中最后一个已知位置,并在车辆通电时恢复该位置。 | CarLocationManager |
CarEvsService | 汽车摄像头服务 | CarEvsManager |
CarTelemetryService | 汽车电话服务 | CarTelemetryManager |
CarDevicePolicyService | 汽车设备策略服务 | CarDevicePolicyManager |
CarActivityService | 汽车活动服务 | CarActivityManager |
CarPerformanceService | 汽车性能服务 | CarPerformanceManager |
CarWatchdogService | 汽车看门狗服务:实现 CarWatchdogManager API的服务。 CarWatchdogService 作为汽车监控中介运行,它检查客户端的健康状况,并将结果报告给汽车监控服务器。 | CarWatchdogManager |
CarTestService | 汽车测试服务:允许测试/模拟车辆HAL的服务。该服务直接使用车辆HAL API,因为车辆HAL模拟无论如何都需要直接访问该级别。 | CarTestManager |
CarUXRestrictionsService | 汽车用户体验限制服务 | CarUXRestrictionsManager |
CarOccupantZoneService | 汽车乘员区服务 | CarOccupantZoneManager |
CarBugreportManagerService | 汽车错误报告管理器服务 | CarBugreportManager |
CarUserService | 汽车用户服务 | CarUserManager |
CarUserNoticeService | 向用户显示初始通知UI的服务:它仅在启用设置时启动它,并根据用户的请求通知UI自行关闭。 | CarUserNoticeManager |
ClusterHomeService | 仪表Hoem服务 | ClusterHomeManager |
ClusterNavigationService | 仪表导航服务 | ClusterNavigationManager |
OccupantAwarenessService | 跨HAL边界侦听乘员感知检测系统的服务 | OccupantAwarenessManager |
VmsBrokerService | 消息代理服务,用于在客户端之间路由车辆映射服务消息, 地图导航相关 VMS客户端实现,使用HAL特定消息编码将VmsPublisher/VmsSubscriber API调用代理到车辆HAL。 | - |
3、Vehicle HAL
用于处理车辆相关数据,底层通过RPC通信接收MCU数据和发送数据给MCU,作为CarPropertyService和CarPowerManagerService的底层实现电源控制与车辆属性控制功能。
二、Android汽车子系统相关类
1、CarService
CarService是车载Android系统的核心服务之一,所有应用都需要通过CarService来查询、控制整车的状态。不仅仅是车辆控制,实际上CarService几乎就是整个车载Framework最核心的组件。提供了一系列的服务与HAL层的VehicleHAL通信,进而通过车载总线(例如CAN总线)与车身进行通讯,同时它们还为应用层的APP提供接口,从而让APP能够实现对车身的控制与状态的显示。
CarService代码位于:
packages/services/Car/car-lib/src/android/car/ICar.aidl
packages/services/Car/service/src/com/android/car/ICarImpl.java
packages/services/Car/service/src/com/android/car/CarServiceBase.java
packages/services/Car/service/src/com/android/car/CarServiceUtils.java
packages/services/Car/service/src/com/android/car/CarServiceImpl.java
packages/services/Car/service-builtin/src/com/android/car/CarService.java
frameworks/opt/car/services/builtInServices/src/com/android/internal/car/CarServiceHelperService .java
CarService的定义:
interface ICar {}
public interface CarServiceBase {}
public final class CarServiceUtils {}
public class ICarImpl extends ICar.Stub {}
public class CarService extends ServiceProxy {}
public class CarServiceImpl extends ProxiedService {}
public class CarServiceHelperService extends SystemService implements Dumpable, DevicePolicySafetyChecker, CarServiceHelperInterface {}
2、SystemInterface
此类包含对CarService 和 Android OS API。
SystemInterface代码位于:packages/services/Car/service/src/com/android/car/systeminterface/SystemInterface.java
SystemInterface的定义:
public class SystemInterface implements ActivityManagerInterface,
DisplayInterface, IOInterface, StorageMonitoringInterface,
SystemStateInterface, TimeInterface,
WakeLockInterface {}
三、CarService配置
需要根据OEM需要对CarService进行配置,配置文件路径为packages/services/Car/services/res/values/config.xml,配置内容如下:
audioUseDynamicRouting:Configuration to enable usage of dynamic audio routing.
audioUseCarVolumeGroupMuting:Configuration to enable muting of individual volume groups.
audioUseHalDuckingSignals:Configuration to enable IAudioControl#onDevicesToDuckChange API to inform HAL when to duck.
audioVolumeAdjustmentContextsVersion:Configuration to select version of volume adjustment context priority list.
audioPersistMasterMuteState:Configuration to persist global mute state.
audioVolumeKeyEventTimeoutMs:Configuration to indicate the timeout in milliseconds while a car volume group will be considered active for volume control changes during volume key events.
displayOffMuteLockAllAudio:Whether to block other audio while media audio is muted with display off. When set to true, other sounds cannot be played either while display is off.
useDefaultBluetoothConnectionPolicy:Configuration to enable or disable the default Bluetooth Device Connection Policy.
useDefaultBluetoothPowerPolicy:Configuration to enable or disable the default Bluetooth Power Policy.
instrumentClusterRendererService:Service responsible for displaying information on the car instrument cluster.
config_clusterHomeActivity:The name of Activity who is in charge of ClusterHome.
rotaryService:Service responsible for handling the rotary controller input.
enableActivityBlockingForSafety:Whether to enable Activity blocking for safety.
activityBlockingActivity:Activity to be presented when un-safe activity is launched.
continuousBlankActivity:
activityAllowlist:Comma separated list of activities that need to be exempted from getting blocked in a UX restricted state.
systemActivityAllowlist:Comma separated list of activities that need to be exempted from getting blocked in a UX restricted state.
activityDenylist:Comma separated list of activities that will be blocked during restricted state.
defaultHomeActivity:Default home activity
vmsHalClientMetricsProperty:The vendor-defined HAL property used to collect VMS client metrics. Disabled by default.
vmsPublisherSystemClients:The com.android.car.vms.VmsClientManager will bind to this list of clients running as system user
vmsPublisherUserClients:The com.android.car.vms.VmsClientManager will bind to this list of clients running as current user
millisecondsBeforeRebindToVmsPublisher:Number of milliseconds to wait before trying re-bind to a crashed publisher.
acceptableHoursPerOnePercentFlashWear:Hours of uptime (excluding sleep) after which a 1% increase in the wear of the flash storage in the head-unit is considered as acceptable level of wear.
uptimeHoursIntervalBetweenUptimeDataWrite:How often (in hours of uptime excluding sleep) CarService will flush to disk information about the total running time of the head-unit.
activityHandlerForFlashWearChanges:The name of an activity to be launched by CarService whenever it detects a change in the level of wear of the flash storage.
ioStatsRefreshRateSeconds:How often (in seconds) CarService will update I/O metrics from the kernel.
ioStatsNumSamplesToStore:The number of I/O metrics samples to keep in memory at one time.
acceptableWrittenKBytesPerSample:The maximum number of KB (1024 bytes) that can be written to storage in one sample before CarService deems I/O activity excessive.
acceptableFsyncCallsPerSample:The maximum number of fsync() system calls that can be made in one sample before CarService deems I/O activity excessive.
maxExcessiveIoSamplesInWindow:The maximum number of samples (within an I/O stats sample window) that CarService should consider exhibiting excessive I/O activity before broadcasting an intent to signal the potential for flash wear.
recurringResourceOverusePeriodInDays:The number of days past until the current day considered by car watchdog to attribute recurring overuse to a package.
recurringResourceOveruseTimes:The number of overuses a package has to exceed for car watchdog to attribute recurring overuse.
uidIoUsageSummaryTopCount:The number of top UID I/O usage summaries to report on car watchdog I/O usage summary atom pull.
ioUsageSummaryMinSystemTotalWrittenBytes:The minimum number of total bytes written to disk by the system required to report the stats on car watchdog I/O usage summary atom pull. Currently 500 MiB.
intentReceiverForUnacceptableIoMetrics:The name of an intent to be notified by CarService whenever it detects too many samples with excessive I/O activity.
eMmcLifetimeFilePath:The path to a file that contains lifetime estimation metrics for the eMMC storage on this system, in the lifetimeA lifetimeB format, as defined by the eMMC extended CSD register specification.
eMmcEolFilePath:The path to a file that contains end of life estimation metrics for the eMMC storage on this system, in the format defined by the eMMC extended CSD register specification.
fastPairModelId:The Model ID to advertise Bluetooth Fast Pair connections with.
fastPairAntiSpoofKey:The Anti Spoofing Public key associated with the advertised Fast Pair Model ID, base64 encoded.
fastPairAutomaticAcceptance:Enable to allow Fast Pair to automatically accept incoming pairing requests with matching Simple Secure Pairing codes without requiring further user input.
maxGarageModeRunningDurationInSecs:Maximum allowed time to run garage mode.
config_earlyStartupServices:The services that needs to be started earlier in the boot sequence and in particular order.
config_projectionConsentActivity:The consent activity that must be shown for every unknown mobile device before projection gets started.
config_projectionActivityDisplayId:Display Id where projection rendering activity needs to be shown, Specify -1 to use system defaults
config_projectionActivityLaunchBounds:Bounds of the projection activity on the screen. It should be in the pixels and screen coordinates in the following order: left, top, right, bottom.
config_projectionUiMode:UI mode for projection activity.
config_projectionAccessPointTethering:Configure whether access point created for wireless projection should be in tethered mode.
config_stableLocalOnlyHotspotConfig:If projection Access Point is configured to not provide Internet access (not tethered, see config_projectionAccessPointTethering) then this flag will be used to control whether Wi-Fi configuration will persist reboots.
serviceMediaConnection:The package name of a service to be launched by CarService to bind to an active media service on the current user.
config_car_bugreport_application:The package name of the default bugreport application that can use CarBugreportServiceManager.
config_occupant_zones:Lists all occupant (= driver + passenger) zones available in the car.
config_occupant_display_mapping:Specifies configuration of displays in system telling its usage / type and assigned occupant.
config_sourcePreferredComponents:Specifies whether CarLaunchParamControl prefers source.
config_userNoticeUiService:Specifies notice UI that will be launched when user starts a car or do user switching.
config_mediaSourceChangedAutoplay:Configuration to enable media center to autoplay when the media source is changed.
config_mediaBootAutoplay:Configuration to enable media center to autoplay on boot
config_mediaSourceIndependentPlayback:Setting this flag to true allows for browsing a different source than the one that is currently playing audio.
config_allowed_optional_car_features:Specifies optional features that can be enabled by this image.
enablePassengerSupport:Configuration to enable passenger support.
config_customCountryDetector:Class name of the custom country detector to be used.
enableLongPressBluetoothVoiceRecognition:Controls the use of bluetooth voice recognition when long pressing the voice assist button.
config_switchGuestUserBeforeGoingSleep:Switch guest user into new guest user before going to sleep.
enableProfileUserAssignmentForMultiDisplay:Enable profile user assignment per each CarOccupantZone for per display android user assignments.
config_defaultMediaSource:The ComponentName of the media source that will be selected as the default
config_callButtonEndsOngoingCall:A configuration flag to enable ending an ongoing call using the physical Call button.
config_maxSuspendWaitDuration:Number of milliseconds to wait before the system goes into Suspend-to-RAM.
config_preShutdownPrepareTimeout:Number of milliseconds to wait until all listeners complete when PRE_SHUTDOWN_PREPARE is notified
config_shutdownEnterTimeout:Number of milliseconds to wait until all listeners complete when SHUTDOWN_ENTER is notified
config_postShutdownEnterTimeout:Number of milliseconds to wait until all listeners complete when POST_SHUTDOWN_ENTER is notified
config_evsRearviewCameraId:A name of a camera device that provides the rearview through EVS service
config_evsCameraActivity:The camera Activity name for EVS, if defined, the Activity will be launched by CarEvsService.
config_wifiAdjustmentForSuspend:A configuration flag to adjust Wifi for suspend.
config_enableCarLocationServiceGnssControlsForPowerManagement:A configuration flag to adjust enabling and disabling the GNSS Location Provider for Power Management purposes such as Supsend to RAM.
config_preventTemplatedAppsFromShowingDialog:A configuration flag to prevent the templated apps from showing dialogs.
config_template_activity_class_name:The class name of the templated activities.
config_enableExternalCarTimeToExternalTimeSuggestion:A flag to configure whether the ExternalCarTime VHAL property should be used to send ExternalTimeSuggestions to the Android TimeManager service.
config_userPreCreationStage:Configuration to set when pre-created users should be managed by CarService.
config_userPreCreationDelay:How many milli-seconds CarService should wait before managing pre-created users after system start.
config_oemCarService:This is the component name for the OEM customization service.
config_oemCarService_connection_timeout_ms:Related to OEM customization service.
config_oemCarService_serviceReady_timeout_ms:Related to OEM customization service.
config_oemCarService_regularCall_timeout_ms:Related to OEM customization service.
config_oemCarService_crashCall_timeout_ms:Related to OEM customization service.
config_oemCarService_thread_pool_size:Related to OEM customization service.
四、CarService流程介绍
CarService的启动流程大致如下:
-
SystemServer启动CarServiceHelperService服务
-
在调用startService后,CarServiceHelperService的onStart方法通过bindService的方式启动CarService(一个系统级别的APK,位于system/priv-app)
-
启动CarService后首先调用onCreate,创建ICarImpl对象并初始化,在此时创建了一系列car相关的核心服务,并遍历init初始化
-
然后调用onBind将该ICarImpl对象返回给CarServiceHelperService,CarServiceHelperService在内部的一个Binder对象ICarServiceHelperImpl传递给CarService,建立双向跨进程
如下为流程图:
1、系统启动后在SystemServer进程中启动CarServiceHelperService
在SystemServer的startOtherServices()中会启动CarServiceHelperService服务:
//frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer implements Dumpable {
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
"com.android.internal.car.CarServiceHelperService";
......
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
traceBeginAndSlog("StartCarServiceHelperService");
mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS); 调用SystemServiceManager启动CarServiceHelperService服务
traceEnd();
}
}
}
因为前面我们传入的参数为com.android.internal.car.CarServiceHelperService,所以SystemServiceManager的startService方法首先会通过反射创建CarServiceHelperService对象实例,然后将其存储在类型ArrayList的mServices中,紧接着会调用CarServiceHelperService的onStart方法,CarServiceHelperService的onStart方法如下所示:
//frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
public class CarServiceHelperService extends SystemService
implements Dumpable, DevicePolicySafetyChecker {
@Override
public void onStart() {
EventLog.writeEvent(EventLogTags.CAR_HELPER_START);
IntentFilter filter = new IntentFilter(Intent.ACTION_REBOOT);
filter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiverForAllUsers(mShutdownEventReceiver, filter, null, null);
mCarWatchdogDaemonHelper.addOnConnectionChangeListener(mConnectionListener);
mCarWatchdogDaemonHelper.connect();
Intent intent = new Intent();
intent.setPackage("com.android.car");
intent.setAction(CAR_SERVICE_INTERFACE);
//通过bindService绑定车机服务CarService
if (!mContext.bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
mHandler, UserHandle.SYSTEM)) {
Slogf.wtf(TAG, "cannot start car service");
}
loadNativeLibrary();
}
void loadNativeLibrary() {
System.loadLibrary("car-framework-service-jni");
}
}
CarServiceHelperService的onStart方法首先创建一个Action为android.car.ICar,包名为com.android.car的Intent,然后通过bindService的方式启动该Intent对应的服务,而这个服务正是车机模块才有的CarService服务。
2、CarService启动
系统关于CarService服务的声明如下所示:
//packages/services/Car/service/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.car"
coreApp="true"
android:sharedUserId="android.uid.system">
<!--...代码省略...-->
<application android:label="@string/app_title"
android:directBootAware="true"
android:allowBackup="false"
android:persistent="true">
<service android:name=".CarService"
android:singleUser="true"
android:exported="true">
<intent-filter>
<action android:name="android.car.ICar"/>
</intent-filter>
</service>
<!--...代码省略...-->
</application>
</manifest>
结合这个配置文件我们可以知道CarServiceHelperService最终所启动的,就是CarService这个服务,CarService的代码如下所示:
//packages/services/Car/service-builtin/src/com/android/car/CarService.java
/** Proxy service for CarServciceImpl */
public class CarService extends ServiceProxy {
public CarService() {
super(UpdatablePackageDependency.CAR_SERVICE_IMPL_CLASS);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// keep it alive.
return START_STICKY;
}
}
CarService里面啥也没有,实际的处理都在CarServciceImpl里面:
//packages/services/Car/service/src/com/android/car/CarServiceImpl.java
/** Implementation of CarService */
public class CarServiceImpl extends ProxiedService {
public static final String CAR_SERVICE_INIT_TIMING_TAG = "CAR.InitTiming";
public static final int CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS = 5;
private ICarImpl mICarImpl;
private VehicleStub mVehicle;
private String mVehicleInterfaceName;
private final VehicleDeathRecipient mVehicleDeathRecipient = new VehicleDeathRecipient();
@Override
public void onCreate() {
LimitedTimingsTraceLog initTiming = new LimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,
TraceHelper.TRACE_TAG_CAR_SERVICE, CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
initTiming.traceBegin("CarService.onCreate");
initTiming.traceBegin("getVehicle");
mVehicle = VehicleStub.newVehicleStub();
initTiming.traceEnd(); // "getVehicle"
EventLogHelper.writeCarServiceCreate(/* hasVhal= */ mVehicle.isValid());
mVehicleInterfaceName = mVehicle.getInterfaceDescriptor();
Slogf.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
EventLogHelper.writeCarServiceConnected(mVehicleInterfaceName);
mICarImpl = new ICarImpl(this,
getBuiltinPackageContext(),
mVehicle,
SystemInterface.Builder.defaultSystemInterface(this).build(),
mVehicleInterfaceName); // 创建ICarImpl 对象
mICarImpl.init(); //调用mICarImpl的初始化方法
mVehicle.linkToDeath(mVehicleDeathRecipient);
//将ICarImpl存储到系统服务管理者ServiceManager中
ServiceManagerHelper.addService("car_service", mICarImpl);
SystemPropertiesHelper.set("boot.car_service_created", "1");
super.onCreate();
initTiming.traceEnd(); // "CarService.onCreate"
}
// onDestroy is best-effort and might not get called on shutdown/reboot. As such it is not
// suitable for permanently saving state or other need-to-happen operation. If you have a
// cleanup task that you want to make sure happens on shutdown/reboot, see OnShutdownReboot.
@Override
public void onDestroy() {
EventLogHelper.writeCarServiceDestroy(/* hasVhal= */ mVehicle.isValid());
Slogf.i(CarLog.TAG_SERVICE, "Service onDestroy");
mICarImpl.release();
mVehicle.unlinkToDeath(mVehicleDeathRecipient);
mVehicle = null;
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// keep it alive.
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mICarImpl;
}
@Override
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
// historically, the way to get a dumpsys from CarService has been to use
// "dumpsys activity service com.android.car/.CarService" - leaving this
// as a forward to car_service makes the previously well-known command still work
mICarImpl.dump(fd, writer, args);
}
private static class VehicleDeathRecipient implements IVehicleDeathRecipient {
@Override
public void serviceDied(long cookie) {
EventLogHelper.writeCarServiceVhalDied(cookie);
Slogf.wtf(CarLog.TAG_SERVICE, "***Vehicle HAL died. Car service will restart***");
Process.killProcess(Process.myPid());
}
@Override
public void binderDied() {
EventLogHelper.writeCarServiceVhalDied(/*cookie=*/ 0);
Slogf.wtf(CarLog.TAG_SERVICE, "***Vehicle HAL died. Car service will restart***");
Process.killProcess(Process.myPid());
}
}
}
CarService的onCreate方法会创建一个关键对象ICarImpl的实例,并将该实例赋值给mICarImpl属性变量,然后会调用该对象的init方法,之后还会将mICarImpl存储到ServiceManager中。另外结合CarService的onBind方法我们可以知道,CarServiceHelperService通过bindService方式开启CarService,CarService会返回mICarImpl对象,通过该Binder对象使二者建立双向跨进程通信。
//packages/services/Car/service/src/com/android/car/ICarImpl.java
public class ICarImpl extends ICar.Stub {
private final VehicleHal mHal;
private final CarServiceBase[] mAllServices;
public ICarImpl(Context serviceContext, Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName) {
this(serviceContext, builtinContext, vehicle, systemInterface, vehicleInterfaceName,
/* carUserService= */ null, /* carWatchdogService= */ null,
/* carPerformanceService= */ null, /* garageModeService= */ null,
/* powerPolicyDaemon= */ null, /*carTelemetryService= */ null);
}
ICarImpl(Context serviceContext, @Nullable Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName,
@Nullable CarUserService carUserService,
@Nullable CarWatchdogService carWatchdogService,
@Nullable CarPerformanceService carPerformanceService,
@Nullable GarageModeService garageModeService,
@Nullable ICarPowerPolicySystemNotification powerPolicyDaemon,
@Nullable CarTelemetryService carTelemetryService) {
LimitedTimingsTraceLog t = new LimitedTimingsTraceLog(
CAR_SERVICE_INIT_TIMING_TAG, TraceHelper.TRACE_TAG_CAR_SERVICE,
CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
t.traceBegin("ICarImpl.constructor");
mContext = serviceContext;
if (builtinContext == null) {
mCarServiceBuiltinPackageContext = serviceContext;
} else {
mCarServiceBuiltinPackageContext = builtinContext;
}
mSystemInterface = systemInterface;
//创建VehicleHal
CarLocalServices.addService(SystemInterface.class, mSystemInterface);
mHal = constructWithTrace(t, VehicleHal.class,
() -> new VehicleHal(serviceContext, vehicle));
t.traceBegin("VHAL.earlyInit");
// Do this before any other service components to allow feature check. It should work
// even without init. For that, vhal get is retried as it can be too early.
HalPropValue disabledOptionalFeatureValue = mHal.getIfAvailableOrFailForEarlyStage(
VehicleProperty.DISABLED_OPTIONAL_FEATURES, INITIAL_VHAL_GET_RETRY);
t.traceEnd();
String[] disabledFeaturesFromVhal = null;
if (disabledOptionalFeatureValue != null) {
String disabledFeatures = disabledOptionalFeatureValue.getStringValue();
if (disabledFeatures != null && !disabledFeatures.isEmpty()) {
disabledFeaturesFromVhal = disabledFeatures.split(",");
}
}
if (disabledFeaturesFromVhal == null) {
disabledFeaturesFromVhal = new String[0];
}
Resources res = mContext.getResources();
String[] defaultEnabledFeatures = res.getStringArray(
R.array.config_allowed_optional_car_features);
final String[] disabledFromVhal = disabledFeaturesFromVhal;
mFeatureController = constructWithTrace(t, CarFeatureController.class,
() -> new CarFeatureController(serviceContext, defaultEnabledFeatures,
disabledFromVhal, mSystemInterface.getSystemCarDir()));
mVehicleInterfaceName = vehicleInterfaceName;
//创建各种子服务对象
mCarPropertyService = constructWithTrace(
t, CarPropertyService.class,
() -> new CarPropertyService(serviceContext, mHal.getPropertyHal()));
mCarDrivingStateService = constructWithTrace(
t, CarDrivingStateService.class,
() -> new CarDrivingStateService(serviceContext, mCarPropertyService));
mCarOccupantZoneService = constructWithTrace(t, CarOccupantZoneService.class,
() -> new CarOccupantZoneService(serviceContext));
mCarUXRestrictionsService = constructWithTrace(t, CarUxRestrictionsManagerService.class,
() -> new CarUxRestrictionsManagerService(serviceContext, mCarDrivingStateService,
mCarPropertyService, mCarOccupantZoneService));
if (carUserService != null) {
mCarUserService = carUserService;
CarLocalServices.addService(CarUserService.class, carUserService);
} else {
UserManager userManager = serviceContext.getSystemService(UserManager.class);
int maxRunningUsers = UserManagerHelper.getMaxRunningUsers(serviceContext);
mCarUserService = constructWithTrace(t, CarUserService.class,
() -> new CarUserService(serviceContext, mHal.getUserHal(), userManager,
maxRunningUsers, mCarUXRestrictionsService));
}
if (mFeatureController.isFeatureEnabled(Car.EXPERIMENTAL_CAR_USER_SERVICE)) {
mExperimentalCarUserService = constructWithTrace(t, ExperimentalCarUserService.class,
() -> new ExperimentalCarUserService(serviceContext, mCarUserService,
serviceContext.getSystemService(UserManager.class)));
} else {
mExperimentalCarUserService = null;
}
mSystemActivityMonitoringService = constructWithTrace(
t, SystemActivityMonitoringService.class,
() -> new SystemActivityMonitoringService(serviceContext));
mCarPowerManagementService = constructWithTrace(
t, CarPowerManagementService.class,
() -> new CarPowerManagementService(mContext, mHal.getPowerHal(),
systemInterface, mCarUserService, powerPolicyDaemon));
if (mFeatureController.isFeatureEnabled(CarFeatures.FEATURE_CAR_USER_NOTICE_SERVICE)) {
mCarUserNoticeService = constructWithTrace(
t, CarUserNoticeService.class, () -> new CarUserNoticeService(serviceContext));
} else {
mCarUserNoticeService = null;
}
if (mFeatureController.isFeatureEnabled(Car.OCCUPANT_AWARENESS_SERVICE)) {
mOccupantAwarenessService = constructWithTrace(t, OccupantAwarenessService.class,
() -> new OccupantAwarenessService(serviceContext));
} else {
mOccupantAwarenessService = null;
}
mCarActivityService = constructWithTrace(t, CarActivityService.class,
() -> new CarActivityService(serviceContext));
mCarPackageManagerService = constructWithTrace(t, CarPackageManagerService.class,
() -> new CarPackageManagerService(serviceContext, mCarUXRestrictionsService,
mCarActivityService, mCarOccupantZoneService));
mPerUserCarServiceHelper = constructWithTrace(
t, PerUserCarServiceHelper.class,
() -> new PerUserCarServiceHelper(serviceContext, mCarUserService));
mCarBluetoothService = constructWithTrace(t, CarBluetoothService.class,
() -> new CarBluetoothService(serviceContext, mPerUserCarServiceHelper));
mCarInputService = constructWithTrace(t, CarInputService.class,
() -> new CarInputService(serviceContext, mHal.getInputHal(), mCarUserService,
mCarOccupantZoneService, mCarBluetoothService));
mCarProjectionService = constructWithTrace(t, CarProjectionService.class,
() -> new CarProjectionService(serviceContext, null /* handler */, mCarInputService,
mCarBluetoothService));
if (garageModeService == null) {
mGarageModeService = constructWithTrace(t, GarageModeService.class,
() -> new GarageModeService(mContext));
} else {
mGarageModeService = garageModeService;
}
mAppFocusService = constructWithTrace(t, AppFocusService.class,
() -> new AppFocusService(serviceContext, mSystemActivityMonitoringService));
mCarAudioService = constructWithTrace(t, CarAudioService.class,
() -> new CarAudioService(serviceContext));
mCarNightService = constructWithTrace(t, CarNightService.class,
() -> new CarNightService(serviceContext, mCarPropertyService));
mFixedActivityService = constructWithTrace(t, FixedActivityService.class,
() -> new FixedActivityService(serviceContext, mCarActivityService));
mClusterNavigationService = constructWithTrace(
t, ClusterNavigationService.class,
() -> new ClusterNavigationService(serviceContext, mAppFocusService));
if (mFeatureController.isFeatureEnabled(Car.CAR_INSTRUMENT_CLUSTER_SERVICE)) {
mInstrumentClusterService = constructWithTrace(t, InstrumentClusterService.class,
() -> new InstrumentClusterService(serviceContext,
mClusterNavigationService, mCarInputService));
} else {
mInstrumentClusterService = null;
}
mCarStatsService = constructWithTrace(t, CarStatsService.class, () -> {
// This service should be initialized here.
CarStatsService service = new CarStatsService(serviceContext);
service.init();
return service;
});
if (mFeatureController.isFeatureEnabled(Car.VEHICLE_MAP_SERVICE)) {
mVmsBrokerService = constructWithTrace(t, VmsBrokerService.class,
() -> new VmsBrokerService(mContext, mCarStatsService));
} else {
mVmsBrokerService = null;
}
if (mFeatureController.isFeatureEnabled(Car.DIAGNOSTIC_SERVICE)) {
mCarDiagnosticService = constructWithTrace(t, CarDiagnosticService.class,
() -> new CarDiagnosticService(serviceContext,
mHal.getDiagnosticHal()));
} else {
mCarDiagnosticService = null;
}
if (mFeatureController.isFeatureEnabled(Car.STORAGE_MONITORING_SERVICE)) {
mCarStorageMonitoringService = constructWithTrace(
t, CarStorageMonitoringService.class,
() -> new CarStorageMonitoringService(serviceContext,
systemInterface));
} else {
mCarStorageMonitoringService = null;
}
mCarLocationService = constructWithTrace(t, CarLocationService.class,
() -> new CarLocationService(serviceContext));
mCarMediaService = constructWithTrace(t, CarMediaService.class,
() -> new CarMediaService(serviceContext, mCarUserService));
mCarBugreportManagerService = constructWithTrace(t, CarBugreportManagerService.class,
() -> new CarBugreportManagerService(serviceContext));
if (!BuildHelper.isUserBuild()) {
mCarExperimentalFeatureServiceController = constructWithTrace(
t, CarExperimentalFeatureServiceController.class,
() -> new CarExperimentalFeatureServiceController(serviceContext));
} else {
mCarExperimentalFeatureServiceController = null;
}
if (carWatchdogService == null) {
mCarWatchdogService = constructWithTrace(t, CarWatchdogService.class,
() -> new CarWatchdogService(serviceContext, mCarServiceBuiltinPackageContext));
} else {
mCarWatchdogService = carWatchdogService;
}
if (carPerformanceService == null) {
mCarPerformanceService = constructWithTrace(t, CarPerformanceService.class,
() -> new CarPerformanceService(serviceContext));
} else {
mCarPerformanceService = carPerformanceService;
}
mCarDevicePolicyService = constructWithTrace(
t, CarDevicePolicyService.class, () -> new CarDevicePolicyService(mContext,
mCarServiceBuiltinPackageContext, mCarUserService));
if (mFeatureController.isFeatureEnabled(Car.CLUSTER_HOME_SERVICE)) {
if (!mFeatureController.isFeatureEnabled(Car.CAR_INSTRUMENT_CLUSTER_SERVICE)) {
mClusterHomeService = constructWithTrace(
t, ClusterHomeService.class,
() -> new ClusterHomeService(serviceContext, mHal.getClusterHal(),
mClusterNavigationService, mCarOccupantZoneService,
mFixedActivityService));
} else {
Slogf.w(TAG, "Can't init ClusterHomeService, since Old cluster service is running");
mClusterHomeService = null;
}
} else {
mClusterHomeService = null;
}
if (mFeatureController.isFeatureEnabled(Car.CAR_EVS_SERVICE)) {
mCarEvsService = constructWithTrace(t, CarEvsService.class,
() -> new CarEvsService(serviceContext, mCarServiceBuiltinPackageContext,
mHal.getEvsHal(), mCarPropertyService));
} else {
mCarEvsService = null;
}
if (mFeatureController.isFeatureEnabled(Car.CAR_TELEMETRY_SERVICE)) {
if (carTelemetryService == null) {
mCarTelemetryService = constructWithTrace(t, CarTelemetryService.class,
() -> new CarTelemetryService(serviceContext, mCarPropertyService));
} else {
mCarTelemetryService = carTelemetryService;
}
} else {
mCarTelemetryService = null;
}
//将服务对象放置一个list中。这样在init方法中就可以以循环的形式直接调用服务对象的init,而不需要一个个调用。
// Be careful with order. Service depending on other service should be inited later.
List<CarServiceBase> allServices = new ArrayList<>();
allServices.add(mFeatureController);
allServices.add(mCarPropertyService); // mCarUXRestrictionsService depends on it
allServices.add(mCarOccupantZoneService); // mCarUXRestrictionsService depends on it
allServices.add(mCarUXRestrictionsService); // mCarUserService depends on it
allServices.add(mCarUserService);
addServiceIfNonNull(allServices, mExperimentalCarUserService);
allServices.add(mSystemActivityMonitoringService);
allServices.add(mCarPowerManagementService);
allServices.add(mCarDrivingStateService);
addServiceIfNonNull(allServices, mOccupantAwarenessService);
allServices.add(mCarPackageManagerService);
allServices.add(mCarInputService);
allServices.add(mGarageModeService);
addServiceIfNonNull(allServices, mCarUserNoticeService);
allServices.add(mAppFocusService);
allServices.add(mCarAudioService);
allServices.add(mCarNightService);
allServices.add(mFixedActivityService);
allServices.add(mClusterNavigationService);
addServiceIfNonNull(allServices, mInstrumentClusterService);
allServices.add(mPerUserCarServiceHelper);
allServices.add(mCarBluetoothService);
allServices.add(mCarProjectionService);
addServiceIfNonNull(allServices, mCarDiagnosticService);
addServiceIfNonNull(allServices, mCarStorageMonitoringService);
addServiceIfNonNull(allServices, mVmsBrokerService);
allServices.add(mCarMediaService);
allServices.add(mCarLocationService);
allServices.add(mCarBugreportManagerService);
allServices.add(mCarWatchdogService);
allServices.add(mCarPerformanceService);
allServices.add(mCarDevicePolicyService);
addServiceIfNonNull(allServices, mClusterHomeService);
addServiceIfNonNull(allServices, mCarEvsService);
addServiceIfNonNull(allServices, mCarTelemetryService);
allServices.add(mCarActivityService);
// Always put mCarExperimentalFeatureServiceController in last.
addServiceIfNonNull(allServices, mCarExperimentalFeatureServiceController);
mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
mICarSystemServerClientImpl = new ICarSystemServerClientImpl();
t.traceEnd(); // "ICarImpl.constructor"
}
private void addServiceIfNonNull(List<CarServiceBase> services, CarServiceBase service) {
if (service != null) {
services.add(service);
}
}
void init() {
LimitedTimingsTraceLog t = new LimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,
TraceHelper.TRACE_TAG_CAR_SERVICE, CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
t.traceBegin("ICarImpl.init");
t.traceBegin("VHAL.init");
mHal.init(); //调用VehicleHal 初始化方法
t.traceEnd();
t.traceBegin("CarService.initAllServices");
for (CarServiceBase service : mAllServices) {
t.traceBegin(service.getClass().getSimpleName());
service.init(); //初始所有子服务
t.traceEnd();
}
t.traceEnd(); // "CarService.initAllServices"
t.traceEnd(); // "ICarImpl.init"
}
void release() {
// release done in opposite order from init
for (int i = mAllServices.length - 1; i >= 0; i--) {
mAllServices[i].release(); //释放所有子服务
}
mHal.release(); //释放VehicleHal
}
}
在ICarImpl的构造函数中会创建VehicleHal 和各种Car子服务,并把这些服务添加到List中,然后在init方法中调用这些服务的初始化方法,完成服务的初始化。
3、取得CarService子服务
CarService启动和初始化完成后,可以通过CarService的getCarService获取子服务了,实际调用的是ICarImpl的getCarService,它继承与ICar.aidl接口,实现了ICar.aidl接口的方法:
//packages/services/Car/car-lib/src/android/car/ICar.aidl
interface ICar {
/**
* Helper binder is for ICarServiceHelper. It is for the communication from CarService ->
* CarServiceHelperService.
* Receiver binder would set ICarSystemServerClient binder for CarServiceHelperService.
*/
oneway void setSystemServerConnections(in ICarServiceHelper helper,
in ICarResultReceiver receiver) = 0;
// Rest of the calls are used for Apps to CarService communication
@nullable IBinder getCarService(in String serviceName) = 11;
int getCarConnectionType() = 12;
boolean isFeatureEnabled(in String featureName) = 13;
int enableFeature(in String featureName) = 14;
int disableFeature(in String featureName) = 15;
List<String> getAllEnabledFeatures() = 16;
List<String> getAllPendingDisabledFeatures() = 17;
List<String> getAllPendingEnabledFeatures() = 18;
/**
* Get class name for experimental feature. Class should have constructor taking (Car, IBinder)
* and should inherit CarManagerBase.
*/
@nullable String getCarManagerClassForFeature(in String featureName) = 19;
}
ICarImpl的getCarService方法如下:
//packages/services/Car/service/src/com/android/car/ICarImpl.java
public class ICarImpl extends ICar.Stub {
@Override
@Nullable
public IBinder getCarService(String serviceName) {
if (!mFeatureController.isFeatureEnabled(serviceName)) {
Slogf.w(CarLog.TAG_SERVICE, "getCarService for disabled service:" + serviceName);
return null;
}
switch (serviceName) {
case Car.AUDIO_SERVICE:
return mCarAudioService;
case Car.APP_FOCUS_SERVICE:
return mAppFocusService;
case Car.PACKAGE_SERVICE:
return mCarPackageManagerService;
case Car.DIAGNOSTIC_SERVICE:
CarServiceUtils.assertAnyDiagnosticPermission(mContext);
return mCarDiagnosticService;
case Car.POWER_SERVICE:
return mCarPowerManagementService;
case Car.CABIN_SERVICE:
case Car.HVAC_SERVICE:
case Car.INFO_SERVICE:
case Car.PROPERTY_SERVICE:
case Car.SENSOR_SERVICE:
case Car.VENDOR_EXTENSION_SERVICE:
return mCarPropertyService;
case Car.CAR_NAVIGATION_SERVICE:
CarServiceUtils.assertNavigationManagerPermission(mContext);
return mClusterNavigationService;
case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
CarServiceUtils.assertClusterManagerPermission(mContext);
return mInstrumentClusterService.getManagerService();
case Car.PROJECTION_SERVICE:
return mCarProjectionService;
case Car.VEHICLE_MAP_SERVICE:
CarServiceUtils.assertAnyVmsPermission(mContext);
return mVmsBrokerService;
case Car.VMS_SUBSCRIBER_SERVICE:
CarServiceUtils.assertVmsSubscriberPermission(mContext);
return mVmsBrokerService;
case Car.TEST_SERVICE: {
CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
synchronized (mLock) {
if (mCarTestService == null) {
mCarTestService = new CarTestService(mContext, this);
}
return mCarTestService;
}
}
case Car.STORAGE_MONITORING_SERVICE:
CarServiceUtils.assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
return mCarStorageMonitoringService;
case Car.CAR_DRIVING_STATE_SERVICE:
CarServiceUtils.assertDrivingStatePermission(mContext);
return mCarDrivingStateService;
case Car.CAR_UX_RESTRICTION_SERVICE:
return mCarUXRestrictionsService;
case Car.OCCUPANT_AWARENESS_SERVICE:
return mOccupantAwarenessService;
case Car.CAR_MEDIA_SERVICE:
return mCarMediaService;
case Car.CAR_OCCUPANT_ZONE_SERVICE:
return mCarOccupantZoneService;
case Car.CAR_BUGREPORT_SERVICE:
return mCarBugreportManagerService;
case Car.CAR_USER_SERVICE:
return mCarUserService;
case Car.EXPERIMENTAL_CAR_USER_SERVICE:
return mExperimentalCarUserService;
case Car.CAR_WATCHDOG_SERVICE:
return mCarWatchdogService;
case Car.CAR_PERFORMANCE_SERVICE:
return mCarPerformanceService;
case Car.CAR_INPUT_SERVICE:
return mCarInputService;
case Car.CAR_DEVICE_POLICY_SERVICE:
return mCarDevicePolicyService;
case Car.CLUSTER_HOME_SERVICE:
return mClusterHomeService;
case Car.CAR_EVS_SERVICE:
return mCarEvsService;
case Car.CAR_TELEMETRY_SERVICE:
return mCarTelemetryService;
case Car.CAR_ACTIVITY_SERVICE:
return mCarActivityService;
default:
IBinder service = null;
if (mCarExperimentalFeatureServiceController != null) {
service = mCarExperimentalFeatureServiceController.getCarService(serviceName);
}
if (service == null) {
Slogf.w(CarLog.TAG_SERVICE, "getCarService for unknown service:"
+ serviceName);
}
return service;
}
}
}