车机开发—【CarService启动流程】

news/2024/4/26 1:05:12/文章来源:https://blog.csdn.net/m0_62167422/article/details/129170884

汽车架构:车载HAL是汽车与车辆网络服务之间的接口定义(同时保护传入的数据):

车载HAL与Android Automotive架构:

  • Car App:包括OEM和第三方开发的App
  • Car API:内有包含CarSensorManager在内的API。位于/platform/packages/services/Car/car-lib
  • CarService:系统中与车相关的服务,位于/platform/packages/services/Car/
  • Vehicle HAL:汽车的硬件抽象层描述。位于hardware/interfaces/automotive/vehicle/2.0/default/(接口属性:hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/)

Framework CarService

Android O/P为Automotive场景提供了一系列的服务,这些服务统被称为CarService。它们与HAL层的VehicleHAL通信,进而通过车载总线(例如CAN总线)与车身进行通讯,同时它们还为应用层的APP提供接口,从而让APP能够实现对车身的控制与状态的显示

  • Car***Manager:packages/services/Car/car-lib/src/android/car/hardware
  • Car***Service:packages/services/Car/service/src/com/android/car/

CarService启动流程

和汽车相关的服务的启动主要依靠一个系统服务CarServiceHelperService开机时在SystemServer中启动:

CarServiceHelperService启动

private static final String CAR_SERVICE_HELPER_SERVICE_CLASS ="com.android.internal.car.CarServiceHelperService";private void startOtherServices(@NonNull TimingsTraceAndSlog t) {......​if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {t.traceBegin("StartCarServiceHelperService");mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);t.traceEnd();}......}

CarServiceHelperService被定义在frameworks/opt/car/下,它和其他系统服务一样,属于SystemService的子类,通过SystemServiceManager.startService启动:

SystemServiceManager.startService

public SystemService startService(String className) {final Class<SystemService> serviceClass = loadClassFromLoader(className,this.getClass().getClassLoader());return startService(serviceClass);}private static Class<SystemService> loadClassFromLoader(String className,ClassLoader classLoader) {try {return (Class<SystemService>) Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {...}}

loadClassFromLoader通过类加载器直接获取CarServiceHelperService的class对象,拿到class对象进而再调用startService重载方法:

    public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();
​
​// Create the service.if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name+ ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {...} catch (IllegalAccessException ex) {...} catch (NoSuchMethodException ex) {...} catch (InvocationTargetException ex) {...}startService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}
​

接着通过反射构造CarServiceHelperService的实例对象,然后再调用startService重载方法:

 public void startService(@NonNull final SystemService service) {// Register it.mServices.add(service);// Start it.long time = SystemClock.elapsedRealtime();try {service.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");}

这里先将CarServiceHelperService保存到mServices这个list中,然后调用CarServiceHelperService的onStart方法正式启动此服务。

CarServiceHelperService.onStart

 @Overridepublic void onStart() {EventLog.writeEvent(EventLogTags.CAR_HELPER_START, mHalEnabled ? 1 : 0);
​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(ICarConstants.CAR_SERVICE_INTERFACE);if (!mContext.bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,UserHandle.SYSTEM)) {Slog.wtf(TAG, "cannot start car service");}loadNativeLibrary();}

这里首先注册了开关机广播,CarWatchdogDaemonHelper用于监控此服务,接着会绑定一个包名为"com.android.car",Action为"android.car.ICar"的服务,这就是系统中和汽车相关的核心服务CarService,相关源代码在packages/services/Car/service目录下,然后我们先去看看CarService,等下再回头来看绑定此服务之后的mCarServiceConnection回调部分。

如下是CarService的AndroidManifest部分截图,可以看到CarService的sharedUserId是系统级别的,这是一个系统级服务,类似SystemUI,它编译出来同样是一个APK文件。 来具体看CarService,它的onStartCommand没什么东西,主要来看onBind:

CarService.onBind

@Overridepublic IBinder onBind(Intent intent) {return mICarImpl;}

ICarImpl是一个Binder服务端,其顶级接口为ICar,在onCreate中初始化:

CarService.onCreate

 @Overridepublic void onCreate() {//通知用户有关 CAN 总线故障 mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);//获取Vehicle hal的client端mVehicle = getVehicle();if (mVehicle == null) {throw new IllegalStateException("Vehicle HAL service is not available.");}try {mVehicleInterfaceName = mVehicle.interfaceDescriptor();} catch (RemoteException e) {...}//实例化ICarImplmICarImpl = new ICarImpl(this,mVehicle,SystemInterface.Builder.defaultSystemInterface(this).build(),mCanBusErrorNotifier,mVehicleInterfaceName);//初始化mICarImpl.init();//Vehicle hal对端死亡回调linkToDeath(mVehicle, mVehicleDeathRecipient);//将mICarImpl注册到ServiceManagerServiceManager.addService("car_service", mICarImpl);//修改boot.car_service_created属性为1SystemProperties.set("boot.car_service_created", "1");super.onCreate();}

此方法中主要会对ICarImpl实例化,之后init进行初始化,最后将其注册到ServiceManager。

ICarImpl构造方法

ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,CanBusErrorNotifier errorNotifier, String vehicleInterfaceName,@Nullable CarUserService carUserService,@Nullable CarWatchdogService carWatchdogService) {......mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext, mCarUserService);mCarBluetoothService = new CarBluetoothService(serviceContext, mPerUserCarServiceHelper);mCarInputService = new CarInputService(serviceContext, mHal.getInputHal(), mCarUserService);mCarProjectionService = new CarProjectionService(serviceContext, null /* handler */, mCarInputService, mCarBluetoothService);mGarageModeService = new GarageModeService(mContext);mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);mCarAudioService = new CarAudioService(serviceContext);mCarNightService = new CarNightService(serviceContext, mCarPropertyService);mFixedActivityService = new FixedActivityService(serviceContext);mInstrumentClusterService = new InstrumentClusterService(serviceContext,mAppFocusService, mCarInputService);mSystemStateControllerService = new SystemStateControllerService(serviceContext, mCarAudioService, this);mCarStatsService = new CarStatsService(serviceContext);mCarStatsService.init();if (mFeatureController.isFeatureEnabled(Car.VEHICLE_MAP_SERVICE)) {mVmsBrokerService = new VmsBrokerService(mContext, mCarStatsService);} else {mVmsBrokerService = null;}if (mFeatureController.isFeatureEnabled(Car.DIAGNOSTIC_SERVICE)) {mCarDiagnosticService = new CarDiagnosticService(serviceContext,mHal.getDiagnosticHal());} else {mCarDiagnosticService = null;}if (mFeatureController.isFeatureEnabled(Car.STORAGE_MONITORING_SERVICE)) {mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,systemInterface);} else {mCarStorageMonitoringService = null;}mCarConfigurationService =new CarConfigurationService(serviceContext, new JsonReaderImpl());mCarLocationService = new CarLocationService(serviceContext);mCarTrustedDeviceService = new CarTrustedDeviceService(serviceContext);mCarMediaService = new CarMediaService(serviceContext, mCarUserService);mCarBugreportManagerService = new CarBugreportManagerService(serviceContext);......CarLocalServices.addService(CarPowerManagementService.class, mCarPowerManagementService);CarLocalServices.addService(CarPropertyService.class, mCarPropertyService);CarLocalServices.addService(CarUserService.class, mCarUserService);CarLocalServices.addService(CarTrustedDeviceService.class, mCarTrustedDeviceService);CarLocalServices.addService(CarUserNoticeService.class, mCarUserNoticeService);CarLocalServices.addService(SystemInterface.class, mSystemInterface);CarLocalServices.addService(CarDrivingStateService.class, mCarDrivingStateService);CarLocalServices.addService(PerUserCarServiceHelper.class, mPerUserCarServiceHelper);CarLocalServices.addService(FixedActivityService.class, mFixedActivityService);CarLocalServices.addService(VmsBrokerService.class, mVmsBrokerService);.....List<CarServiceBase> allServices = new ArrayList<>();allServices.add(mFeatureController);allServices.add(mCarUserService);allServices.add(mSystemActivityMonitoringService);allServices.add(mCarPowerManagementService);allServices.add(mCarPropertyService);allServices.add(mCarDrivingStateService);...mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}

这里省略了和Vehicle hal有关的初始化和分析,后续文章再看。

ICarImpl构造方法中创建了一系列CarService模块下的服务,这些服务有部分被添加到了CarLocalServices内部,其提供了getService静态方法用于直接获取这些服务,所有服务都被保存在ICarImpl内部的CarServiceBase类型数组mAllServices中(所有服务都是CarServiceBase的子类)。

ICarImpl构造方法完了之后会接着调用其init方法:

ICarImpl.init

 @MainThreadvoid init() {mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);traceBegin("VehicleHal.init");//hal初始化//...省略traceEnd();traceBegin("CarService.initAllServices");for (CarServiceBase service : mAllServices) {service.init();}traceEnd();}

此方法很简单,遍历mAllServices,分别执行所有服务的init,各自初始化,有兴趣的可以自己去研究各个服务。

到此ICarImpl初始化完毕,最后会作为binder返回给绑定此服务的mCarServiceConnection:

private final ServiceConnection mCarServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {if (DBG) {Slog.d(TAG, "onServiceConnected:" + iBinder);}handleCarServiceConnection(iBinder);}
​@Overridepublic void onServiceDisconnected(ComponentName componentName) {handleCarServiceCrash();}};

CarServiceHelperService.handleCarServiceConnection

   void handleCarServiceConnection(IBinder iBinder) {...synchronized (mLock) {if (mCarService == iBinder) {return; // already connected.}mCarService = iBinder;...sendSetCarServiceHelperBinderCall();......}}

这个方法我们主要关注上面部分,返回的ICarImpl被保存在了CarServiceHelperService的mCarService,后续可通过mCarService跨进程通信。

CarServiceHelperService.sendSetCarServiceHelperBinderCallprivate void sendSetCarServiceHelperBinderCall() {Parcel data = Parcel.obtain();data.writeInterfaceToken(ICarConstants.CAR_SERVICE_INTERFACE);data.writeStrongBinder(mHelper.asBinder());// void setCarServiceHelper(in IBinder helper)sendBinderCallToCarService(data, ICarConstants.ICAR_CALL_SET_CAR_SERVICE_HELPER);}

这里将会进行跨进程通信,首先构造传输数据,ICarConstants是定义在ExternalConstants的静态内部类:

     static final class ICarConstants {....static final String CAR_SERVICE_INTERFACE = "android.car.ICar";static final int ICAR_CALL_SET_CAR_SERVICE_HELPER = 0;....}

CAR_SERVICE_INTERFACE用来标识远程服务接口,其具体传输数据是一个Binder对象,我们来看看mHelper是什么?

​private final ICarServiceHelperImpl mHelper = new ICarServiceHelperImpl();

mHelper是定义在CarServiceHelperService的内部类,是一个Binder对象:

private class ICarServiceHelperImpl extends ICarServiceHelper.Stub {...........
}

CarServiceHelperService.sendBinderCallToCarService 再回到前面看sendBinderCallToCarService方法:

private void sendBinderCallToCarService(Parcel data, int callNumber) {// Cannot depend on ICar which is defined in CarService, so handle binder call directly// instead.IBinder carService;synchronized (mLock) {carService = mCarService;}if (carService == null) {Slog.w(TAG, "Not calling txn " + callNumber + " because service is not bound yet",new Exception());return;}int code = IBinder.FIRST_CALL_TRANSACTION + callNumber;try {carService.transact(code, data, null, Binder.FLAG_ONEWAY);} catch (RemoteException e) {handleCarServiceCrash();} catch (RuntimeException e) {throw e;} finally {data.recycle();}}

这个方法很明显就是跨进程传输的具体实现了,对端是mCarService即ICarImpl,调用binder的transact进行跨进程通信,其code代表需要调用的对端方法,data为携带的传输数据,ICAR_CALL_SET_CAR_SERVICE_HELPER等于0,这里调用的是对端的0号方法。

于是我们来看看ICar.aidl中定义的0号方法:

interface ICar {.....oneway void setCarServiceHelper(in IBinder helper) = 0;......}

ICarImpl.setCarServiceHelper

接着来看setCarServiceHelper具体实现:

 @Overridepublic void setCarServiceHelper(IBinder helper) {//权限检查assertCallingFromSystemProcess();ICarServiceHelper carServiceHelper = ICarServiceHelper.Stub.asInterface(helper);synchronized (mLock) {mICarServiceHelper = carServiceHelper;}mSystemInterface.setCarServiceHelper(carServiceHelper);mCarOccupantZoneService.setCarServiceHelper(carServiceHelper);}

这里将ICarServiceHelper的代理端保存在ICarImpl内部mICarServiceHelper,同时也传给了SystemInterface和CarOccupantZoneService,我们暂时不需要知道这三个类拿到ICarServiceHelper的代理端的具体用处,只需要知道他们有能力跨进程访问CarServiceHelperService就行了。

全文解析了车机开发中CarFramework框架的CarService启动流程;车机开发的知识点非常的多;总结如上图资料文档参考《车载技术手册》,里面内容包含以上进阶技术。

CarService启动流程总结

  • 首先CarService是一个系统级别的服务APK,类似SystemUI,其在开机时由SystemServer通过CarServiceHelperService启动。
  • CarServiceHelperService通过绑定服务的方式启动CarService,启动之后创建了一个Binder对象ICarImpl,并通过onBind返回给system_server进程。
  • ICarImpl构造方法中创建了一系列和汽车相关的核心服务,并依次启动这些服务即调用各自init方法。
  • ICarImpl返回给CarServiceHelperService之后,CarServiceHelperService也将其内部的一个Binder对象(ICarServiceHelperImpl)传递到了CarService进程,自此CarService和system_server两个进程建立了双向Binder通信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72698.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop集群模式安装(Cluster mode)

1、Hadoop源码编译 安装包、源码包下载地址 Index of /dist/hadoop/common/hadoop-3.3.0为什么要重新编译Hadoop源码? 匹配不同操作系统本地库环境&#xff0c;Hadoop某些操作比如压缩、IO需要调用系统本地库&#xff08;*.so|*.dll&#xff09; 修改源码、重构源码 如何…

H12-831题库(有详细的解析)

1.&#xff08;单选&#xff09;某工程师利用2台路由器进行IPv6业务测试,通过运行BGP4模拟总部与分支的互联互通。如图所示,某工程师抓包查看R1发出的update报文。关于该报文信息的描述,以下哪个说法是正确的? A.该报文描述的路由的下一跳地址为:2001:db8::2345:1::1 B.该报文…

自动增长配置不合理导致的性能抖动

背景客户收到了SQL专家云告警邮件&#xff0c;在凌晨2点到3点之间带有资源等待的会话数暴增&#xff0c;请我们协助分析。现象登录SQL专家云&#xff0c;进入活动会话的趋势分析页面&#xff0c;下钻到2点钟一个小时内的数据&#xff0c;看到每分钟的等待数都在100左右&#xf…

关于upstream的八种回调方法

1 creat_request调用背景&#xff1a;用于创建自己模板与第三方服务器的第一次连接步骤1&#xff09; 在Nginx主循环&#xff08;ngx_worker_process_cycle方法&#xff09; 中&#xff0c;会定期地调用事件模块&#xff0c; 以检查是否有网络事件发生。2&#xff09; 事件模块…

人员行为识别系统 TensorFlow

人员行为识别系统人员行为识别系统通过TensorFlow深度学习技术&#xff0c;人员行为识别算法对画面中区域人员不按要求穿戴、违规抽烟打电话、睡岗离岗以及作业流程不规范实时分析预警&#xff0c;发现违规行为立即抓拍告警。深度学习应用到实际问题中&#xff0c;一个非常棘手…

快速读懂网络拓扑图

快速读懂网络拓扑图几重常见的网络拓扑总线型拓扑简介优点缺点环型拓扑简介优点缺点星型拓扑简介优点缺点网络层级机构节点结点链路通路不同的连接线代表什么意思&#xff1f;不同颜色、粗细的直线代表什么意思&#xff1f;闪电线-串行链路几重常见的网络拓扑 总线型拓扑 简介…

浅谈volatile关键字

文章目录1.保证内存可见性2.可见性验证3.原子性验证4.原子性问题解决5.禁止指令重排序6.JMM谈谈你的理解6.1.基本概念6.2.JMM同步规定6.2.1.可见性6.2.2.原子性6.2.3.有序性6.3.Volatile针对指令重排做了啥7.你在哪些地方用过Volatile&#xff1f;volatile是Java提供的轻量级的…

【华为OD机试模拟题】用 C++ 实现 - 求字符串中所有整数的最小和

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【Git】Git的分支操作

目录 4、 Git 分支操作 4.1 什么是分支 4.2 分支的好处 4.3 分支的操作 4、 Git 分支操作 4.1 什么是分支 在版本控制过程中&#xff0c; 同时推进多个任务&#xff0c; 为每个任务&#xff0c; 我们就可以创建每个任务的单独分支。 使用分支意味着程序员可以把自己的工作…

postgres 源码解析50 LWLock轻量锁--1

简介 postgres LWLock&#xff08;轻量级锁&#xff09;是由SpinLock实现&#xff0c;主要提供对共享存储器的数据结构的互斥访问。LWLock有两种锁模式&#xff0c;一种为排他模式&#xff0c;另一种是共享模式&#xff0c;如果想要读取共享内存中的内容&#xff0c;需要在读取…

面试之设计模式(简单工厂模式)

案例 在面试时&#xff0c;面试官让你通过面对对象语言&#xff0c;用Java实现计算器控制台程序&#xff0c;要求输入两个数和运算符号&#xff0c;得出结果。大家可能想到是如下&#xff1a; public static void main(String[] args) {Scanner scanner new Scanner(System.…

BERT模型系列大全解读

前言 本文讲解的BERT系列模型主要是自编码语言模型-AE LM&#xff08;AutoEncoder Language Model&#xff09;&#xff1a;通过在输入X中随机掩码&#xff08;mask&#xff09;一部分单词&#xff0c;然后预训练的主要任务之一就是根据上下文单词来预测这些单词&#xff0c;从…

F.pad() 函数

F.pad() 对tensor 进行扩充的函数。 torch.nn.functional.pad (input, pad, mode‘constant’, value0) input&#xff1a;需要扩充的 tensor&#xff0c;可以是图像数据&#xff0c;亦或是特征矩阵数据&#xff1b;pad&#xff1a;扩充维度&#xff0c;预先定义某维度上的扩充…

到了35岁,软件测试职业发展之困惑如何解?

35岁&#xff0c;从工作时间看&#xff0c;工作超过10年&#xff0c;过了7年之痒&#xff0c;多数IT人都已经跳槽几次。 35岁&#xff0c;发展比较好的软件测试人&#xff0c;已经在管理岗位&#xff08;测试经理甚至测试总监&#xff09;或已经成为测试专家或测试架构师。发展…

Head First设计模式---4.工厂方法模式

2.1工厂方法模式 亦称&#xff1a; 虚拟构造函数、Virtual Constructor、Factory Method 工厂方法模式是一种创建型设计模式&#xff0c; 其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例化对象的类型。 [外链图片转存失败,源站可能有防盗链机制,建议将图片…

掌握MySQL分库分表(七)广播表、绑定表实战,水平分库+分表实现及之后的查询和删除操作

文章目录什么是广播表广播表实战数据库配置表Java配置实体类配置文件测试广播表水平分库分表配置文件运行测试什么是绑定表&#xff1f;绑定表实战配置数据库配置Java实体类配置文件运行测试水平分库分表后的查询和删除操作查询操作什么是广播表 指所有的分片数据源中都存在的…

2023该好好赚钱了,推荐三个下班就能做的副业

在过去的两年里&#xff0c;越来越多的同事选择辞职创业。许多人通过互联网红利赚到了他们的第一桶金。随着短视频的兴起&#xff0c;越来越多的人吹嘘自己年收入百万&#xff0c;导致很多刚进入职场的年轻人逐渐迷失自我&#xff0c;认为钱特别容易赚。但事实上&#xff0c;80…

Docker启动RabbitMQ,实现生产者与消费者

目录 一、Docker拉取镜像并启动RabbitMQ 二、Hello World &#xff08;一&#xff09;依赖导入 &#xff08;二&#xff09;消息生产者 &#xff08;三&#xff09;消息消费者 三、实现轮训分发消息 &#xff08;一&#xff09;抽取工具类 &#xff08;二&#xff09;启…

零基础机器学习做游戏辅助第十四课--原神自动钓鱼(四)yolov5目标检测

一、yolo介绍 目标检测有两种实现,一种是one-stage,另一种是two-stage,它们的区别如名称所体现的,two-stage有一个region proposal过程,可以理解为网络会先生成目标候选区域,然后把所有的区域放进分类器分类,而one-stage会先把图片分割成一个个的image patch,然后每个im…

【微信小程序】--JSON 配置文件作用(三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#…