我的车载开发—{ carservice启动流程 }—

news2024/10/1 17:36:56

carservice启动流程

大致流程:

  1. SystemServer启动CarServiceHelperService服务
  2. 在调用startService后,CarServiceHelperService的onStart方法通过bindService的方式启动CarService(一个系统级别的APK,位于system/priv-app)
  3. 启动CarService后首先调用onCreate,创建ICarImpl对象并初始化,在此时创建了一系列car相关的核心服务,并遍历init初始化
  4. 然后调用onBind将该ICarImpl对象返回给CarServiceHelperService,CarServiceHelperService在内部的一个Binder对象ICarServiceHelperImpl传递给CarService,建立双向跨进程

2.6.1. 序列图

2.6.2. 启动CarServiceHelperService服务

frameworks/base/services/java/com/android/server/SystemServer.java - run() —-> startOtherServices()

    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);
                traceEnd();
            }

—–> frameworks/base/services/core/java/com/android/server/SystemServiceManager.java - startService

    @SuppressWarnings("unchecked")
    public SystemService startService(String className) {
        ....
        return startService(serviceClass);
    }
​
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        ...
        startService(service);
        ...
    }
​
    public void startService(@NonNull final SystemService service) {
        ......
        try {
            service.onStart();
            ...
        }

2.6.3. 绑定carservice服务

—–> frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java - onStart()

    //这就是系统中和汽车相关的核心服务CarService,相关源代码在packages/services/Car/service目录下
    private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
​
    @Override
    public void onStart() {
        Intent intent = new Intent();
        intent.setPackage("com.android.car");  //绑定包名,设置广播仅对该包有效
        //绑定action,表明想要启动能够响应设置的这个action的活动,并在清单文件AndroidManifest.xml中设置action属性
        intent.setAction(CAR_SERVICE_INTERFACE);
        //绑定后回调
        if (!getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
                UserHandle.SYSTEM)) {
            Slog.wtf(TAG, "cannot start car service");
        }
        System.loadLibrary("car-framework-service-jni");
    }
  • service源码路径:packages/services/Car/service/AndroidManifest.xml

sharedUserId是系统级别的,类似SystemUI,它编译出来同样是一个APK文件

设备文件路径在: /system/priv-app/CarService/CarService.apk

//packages/services/Car/service/AndroidManifest.xml
<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="Car service"
                 android:directBootAware="true"
                 android:allowBackup="false"
                 android:persistent="true">
        <service android:name=".CarService"
                android:singleUser="true">
            <intent-filter>
                <action android:name="android.car.ICar" />
            </intent-filter>
        </service>
        <service android:name=".PerUserCarService" android:exported="false" />
    </application>

2.6.4. bindService启动流程

context.bindService() ——> onCreate() ——> onBind() ——> Service running ——> onUnbind() ——> onDestroy() ——> Service stop

onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。

所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestroy

在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestroy在一个生命周期中只能被调用一次

2.7. Car Service启动

2.7.1. onCreate

——–> packages/services/Car/service/src/com/android/car/CarService.java - onCreate()

创建ICarImpl实例

    @Nullable
    private static IVehicle getVehicle() {
        try {
            //该service启动文件hardware/interfaces/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
            return android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
        } ....
        return null;
    }
​
    @Override
    public void onCreate() {
        Log.i(CarLog.TAG_SERVICE, "Service onCreate");
        //获取hal层的Vehicle service
        mVehicle = getVehicle();
​
        //创建ICarImpl实例
        mICarImpl = new ICarImpl(this,
                mVehicle,
                SystemInterface.Builder.defaultSystemInterface(this).build(),
                mCanBusErrorNotifier,
                mVehicleInterfaceName);
        //然后调用ICarImpl的init初始化方法
        mICarImpl.init();
        //设置boot.car_service_created属性
        SystemProperties.set("boot.car_service_created", "1");
​
        linkToDeath(mVehicle, mVehicleDeathRecipient);
        //最后将该service注册到ServiceManager
        ServiceManager.addService("car_service", mICarImpl);
        super.onCreate();
    }
//packages/services/Car/service/src/com/android/car/ICarImpl.java
    private final VehicleHal mHal;
    //构造函数启动一大堆服务
    public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
            CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
        mContext = serviceContext;
        mSystemInterface = systemInterface;
        //创建VehicleHal对象
        mHal = new VehicleHal(vehicle);
        mVehicleInterfaceName = vehicleInterfaceName;
        mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
        mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),
                systemInterface);
        mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
        .....
        //InstrumentClusterService service启动
        mInstrumentClusterService = new InstrumentClusterService(serviceContext,
                mAppFocusService, mCarInputService);
        mSystemStateControllerService = new SystemStateControllerService(serviceContext,
                mCarPowerManagementService, mCarAudioService, this);
        mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
        // mCarBluetoothService = new CarBluetoothService(serviceContext, mCarPropertyService,
        //        mPerUserCarServiceHelper, mCarUXRestrictionsService);
        mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
        mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
        mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
        mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
                systemInterface);
        mCarConfigurationService =
                new CarConfigurationService(serviceContext, new JsonReaderImpl());
        mUserManagerHelper = new CarUserManagerHelper(serviceContext);
​
        //注意排序,service存在依赖
        List<CarServiceBase> allServices = new ArrayList<>();
        allServices.add(mSystemActivityMonitoringService);
        allServices.add(mCarPowerManagementService);
        allServices.add(mCarPropertyService);
        allServices.add(mCarDrivingStateService);
        allServices.add(mCarUXRestrictionsService);
        allServices.add(mCarPackageManagerService);
        allServices.add(mCarInputService);
        allServices.add(mCarLocationService);
        allServices.add(mGarageModeService);
        allServices.add(mAppFocusService);
        allServices.add(mCarAudioService);
        allServices.add(mCarNightService);
        allServices.add(mInstrumentClusterService);
        allServices.add(mCarProjectionService);
        allServices.add(mSystemStateControllerService);
        // allServices.add(mCarBluetoothService);
        allServices.add(mCarDiagnosticService);
        allServices.add(mPerUserCarServiceHelper);
        allServices.add(mCarStorageMonitoringService);
        allServices.add(mCarConfigurationService);
        allServices.add(mVmsSubscriberService);
        allServices.add(mVmsPublisherService);
​
        if (mUserManagerHelper.isHeadlessSystemUser()) {
            mCarUserService = new CarUserService(serviceContext, mUserManagerHelper);
            allServices.add(mCarUserService);
        }
​
        mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
    }
​
    @MainThread
    void init() {
        traceBegin("VehicleHal.init");
        mHal.init();
        traceEnd();
        traceBegin("CarService.initAllServices");
        //启动的所有服务遍历调用init初始化(各个都继承了CarServiceBase)
        for (CarServiceBase service : mAllServices) {
            service.init();
        }
        traceEnd();
    }

2.7.2. onBind

将上面onCreate创建的mICarImpl对象返回:

  1. onBind()回调方法会继续传递通过bindService()传递来的intent对象(即上面的bindServiceAsUser方法)
  2. onUnbind()会处理传递给unbindService()的intent对象。如果service允许绑定,onBind()会返回客户端与服务互相联系的通信句柄
//packages/services/Car/service/src/com/android/car/CarService.java
    @Override
    public IBinder onBind(Intent intent) {
        return mICarImpl;
    }

所以此处的mICarImpl会作为IBinder返回给CarServiceHelperService.java - bindServiceAsUser方法中的参数mCarServiceConnection(回调)

2.7.3. onDestroy

释放mICarImpl创建的资源,包含一系列的服务:

    @Override
    public void onDestroy() {
        Log.i(CarLog.TAG_SERVICE, "Service onDestroy");
        mICarImpl.release();
        mCanBusErrorNotifier.removeFailureReport(this);
​
        if (mVehicle != null) {
            try {
                mVehicle.unlinkToDeath(mVehicleDeathRecipient);
                mVehicle = null;
            } catch (RemoteException e) {
                // Ignore errors on shutdown path.
            }
        }
​
        super.onDestroy();
    }

2.8. 回调ServiceConnection

ICarImpl初始化完毕,会作为IBinder返回给CarServiceHelperService.java - bindServiceAsUser方法中绑定此服务的mCarServiceConnection(回调)

mCarServiceConnection初始化如下:

  1. 其中返回的ICarImpl被保存在了CarServiceHelperService的mCarService
  2. mCarService.transact跨进程通信,调用ICar.aidl中定义的第一个方法setCarServiceHelper
//frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
private IBinder mCarService;
private final ICarServiceHelperImpl mHelper = new ICarServiceHelperImpl();
​
private final ServiceConnection mCarServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Slog.i(TAG, "**CarService connected**");
            //1. 返回的ICarImpl被保存在了CarServiceHelperService的mCarService
            mCarService = iBinder;
            // Cannot depend on ICar which is defined in CarService, so handle binder call directly
            // instead. 
            // void setCarServiceHelper(in IBinder helper)
            Parcel data = Parcel.obtain();
            data.writeInterfaceToken(CAR_SERVICE_INTERFACE);
            //将ICarServiceHelperImpl类型的对象作为数据跨进程传递
            data.writeStrongBinder(mHelper.asBinder());
            try {
                //2.跨进程传输
                //对端是mCarService即ICarImpl,调用binder的transact进行跨进程通信
                //其code代表需要调用的对端方法,data为携带的传输数据
                //FIRST_CALL_TRANSACTION  = 0x00000001,即调用对端ICar.aidl中定义的第一个方法setCarServiceHelper
                mCarService.transact(IBinder.FIRST_CALL_TRANSACTION, // setCarServiceHelper
                        data, null, Binder.FLAG_ONEWAY);
            } catch (RemoteException e) {
                Slog.w(TAG, "RemoteException from car service", e);
                handleCarServiceCrash();
            }
        }
​
        @Override 
        public void onServiceDisconnected(ComponentName componentName) {
            handleCarServiceCrash();
        }
    };

2.9. 跨进程setCarServiceHelper

    @Override
    public void setCarServiceHelper(IBinder helper) {
        int uid = Binder.getCallingUid();
        if (uid != Process.SYSTEM_UID) {
            throw new SecurityException("Only allowed from system");
        }
        synchronized (this) {
            //将ICarServiceHelper的代理端保存在ICarImpl内部mICarServiceHelper
            mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper);
            //同时也传给了SystemInterface
            //此时他们有能力跨进程访问CarServiceHelperService
            mSystemInterface.setCarServiceHelper(mICarServiceHelper);
        }
    }

全文讲解了车载技术中的carservice启动流程;关于车载技术还有非常多的核心技术点;更多学习知识参考《0基础车机开发手册》,点击即可前往

最后

启动流程图

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

转转测试环境docker化实践

测试环境对于任何一个软件公司来讲&#xff0c;都是核心基础组件之一。转转的测试环境伴随着转转的发展也从单一的几套环境发展成现在的任意的docker动态环境docker稳定环境环境体系。期间环境系统不断的演进&#xff0c;去适应转转集群扩张、新业务的扩展&#xff0c;走了一些…

Linux系统基本设置:网络设置(三种界面网络地址配置)

网络地址配置&#xff1a;图形界面配置、命令行界面配置、文本图形界面配置 命令行界面配置 查看网络命令&#xff1a; 想要知道你有多少网卡&#xff0c;都可以通过这两个命令来查看 手动设置网络参数&#xff0c;我们可以使用nmcli这个命令来设置&#xff0c;我们需要知道…

【react实战小项目:笔记】用React 16写了个订单页面

视频地址 React 16 实现订单列表及评价功能 简介&#xff1a;React 以其组件化的思想在前端领域大放异彩&#xff0c;但其革命化的前端开发理念对很多 React 初学者来说&#xff0c; 却很难真正理解和应用到真实项目中。本课程面向掌握了 React 基础知识但缺乏实战经验的开发…

状态机分析

写在前面 状态机是指某事物具有有限状态&#xff0c;且在这些状态之间相互转换的抽象&#xff0c;比如门的开是一个状态&#xff0c;关又是一个状态。本文就一起来看下。 1&#xff1a;状态机的术语 1.1&#xff1a;state 状态&#xff0c;即当前所处的状态&#xff0c;如汽…

电子技术——内部电容效应以及MOS与BJT的高频响应模型

电子技术——内部电容效应以及MOS与BJT的高频响应模型 耦合和旁路电容决定了放大器的低频响应&#xff0c;同时内部电容效应决定了放大器的高频响应。本节&#xff0c;我们简单简单介绍一下内部电容效应&#xff0c;并且更重要的是如何在小信号模型中模型化内部电容效应。 MOS…

C语言操作符经典例题

一、选择题 1、下面哪个是位操作符&#xff1a;&#xff08; &#xff09; A.& B.&& C.|| D.! 答案解析&#xff1a; 答案&#xff1a;A A正确&#xff0c;&——按&#xff08;二进制&#xff09;位与&#xff0c;对应的二进制位&#xff1a;有0则0&#…

将python代码封装成c版本的dll动态链接库

前言 将python程序打包成DLL文件&#xff0c;然后用C调用生成的DLL文件&#xff0c;这是一种用C调用python的方法&#xff0c;这一块比较容易遇到坑。网上关于这一块的教程不是很多&#xff0c;而且大部分都不能完全解决问题。我在傻傻挣扎了几天之后&#xff0c;终于试出了一个…

第八章认识 Vue.js基础

vue.js 是一套用于构建用户界面的渐进式前端框架 vue.js 核心实现&#xff1a; 相应式的数据绑定&#xff1a;当数据发生改变&#xff0c;视图可以自动更新&#xff0c;不用关心DOM操作&#xff0c;而转型数据库操作 可组合的视图组件&#xff1a;把视图按照功能切分成若干的…

vr电力刀闸事故应急演练实训系统开发

电力事故是在电力生产和输电过程中可能发生的意外事件&#xff0c;它们可能会对人们的生命财产安全造成严重的威胁。因此&#xff0c;电力事故应急演练显得尤为重要。而VR技术则可以为电力事故应急演练提供一种全新的解决方案。 在虚拟环境中&#xff0c;元宇宙VR会模拟各种触电…

07 react+echart+大屏

reactechart大屏大屏ECharts 图表实际步骤React Typescript搭建大屏项目&#xff0c;并实现屏幕适配flexible rem实现适配1. 安装插件对echarts进行的React封装&#xff0c;可以用于React项目中&#xff0c;支持JS、TS如何使用完整例子官网参考大屏 ECharts 图表 ECharts 图…

【Java基础】泛型(二)-泛型的难点:通配符

本文将尝试将通配符和泛型中的继承&#xff0c;多态一并讲解 关于泛型中继承的注意事项 因为Integer、Double继承了Number&#xff0c;根据多态性&#xff0c;以下语句是合法的 Number n new Integer(10); // OK, 父类引用变量可以指向子类对象 n 2.9 // OK&#xff0c;n实…

Mac-Charles

Charles是什么 HTTP代理服务器&#xff0c;HTTP监视器 Charles可以当作一个代理服务器 当浏览器链接这个代理服务器的时候 Charles会监控浏览器发出和接收的所有数据(reques,response,HTTP Headers(cookies和cash)) 反转代理器 Charles主要功能、 1.SSL代理 2.模拟慢速网络…

双目立体视觉:SAD算法

算法原理SAD(Sum of absolute differences)是一种图像匹配算法。基本思想&#xff1a;差的绝对值之和。此算法常用于图像块匹配&#xff0c;将每个像素对应数值之差的绝对值求和&#xff0c;据此评估两个图像块的相似度。该算法快速、但并不精确&#xff0c;通常用于多级处理的…

如何在Power Virtual Agents中实现身份验证

今天我们介绍一下如何通过身份验证的方式来使用Power Virtual Agents。首先进入“Microsoft 365-管理-Azure Active Directory管理中心”。 进入“Azure Active Directory管理中心”后选择“Azure Active Directory”中的“应用注册”-“新注册”。 输入新创建的应用程序名称后…

XXL-JOB分布式任务调度框架(一)-基础入门

文章目录1.什么是任务调度2.常见定时任务方案2.1. 传统定时任务方案示例2.2. 缺点分析3.什么是分布式任务调度&#xff1f;3.1. 并行任务调度3.2. 高可用3.3. 弹性扩容3.4. 任务管理与监测4.市面上常见的分布式任务调度产品5.初识xxl-job6.xxl-job架构设计6.1.设计思想6.2.架构…

程序人生 - 学习和分享

文章目录记于 230217学习安排泛学AI 和 未来记于 230217 刚入行时&#xff0c;经常看到技术博客中&#xff0c;博主们分享生活&#xff0c;比如相亲、上班生活&#xff0c;甚至还有人发结婚照。这个栏目通常被称为&#xff1a;程序人生。 这个现象已经很久没看到了&#xff0c…

BFC 是什么

在页面布局的时候&#xff0c;经常出现以下情况&#xff1a; 这个元素高度怎么没了&#xff1f;这两栏布局怎么没法自适应&#xff1f;这两个元素的间距怎么有点奇怪的样子&#xff1f;...... 原因是元素之间相互的影响&#xff0c;导致了意料之外的情况&#xff0c;这里就涉及…

吴恩达深度学习笔记(八)——卷积神经网络(上)

一、卷积相关 用一个ff的过滤器卷积一个nn的图像&#xff0c;假如padding为p&#xff0c;步幅为s&#xff0c;输出大小则为&#xff1a; [n2p−fs1][n2p−fs1][\frac{n2p-f}{s}1][\frac{n2p-f}{s}1][sn2p−f​1][sn2p−f​1] []表示向下取整&#xff08;floor) 大部分深度学习…

Unreal Engine04:Visual Studio和Editor的协同开发

写在前面 这里主要是记录一下Visual Studio和Editor之间的关系和如何使用它们进行UE4协同开发。 一、启动 1. 先启动Visual Studio再启动Editor (1) 打开项目根目录下的xxx.sln解决方案&#xff0c;即可启动Visual Studio&#xff0c;这个是和普通的C项目打开方式相同的&…

2023美国大学生数学建模竞赛C题思路解析(含代码+数据可视化)

以下为2023美国大学生数学建模竞赛C题思路解析&#xff08;含代码数据可视化&#xff09;规则&#xff1a;猜词&#xff0c;字母猜对&#xff0c;位置不对为黄色&#xff0c;位置对为绿色&#xff0c;两者皆不对为灰色。困难模式下的要求&#xff1a;对于猜对的字母&#xff08…