我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【Android车载系列】第2章 车载系统启动与CarService

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【Android车载系列】第2章 车载系统启动与CarService

1 车载启动流程

 

        车载Android启动流程基本是在Android系统的启动流程中,多了Car相关服务。其他流程基本一致,下面我们来看一下Android系统的启动流程。

1.1 Android系统启动流程

        Android系统的启动,从设备的开机键长按开始到Android桌面展示,这个完整流程就是Android系统启动的流程。从系统层次角度可分为Linux 系统层、Android 系统服务层、Zygote进程模型三个阶段;从开机到启动Android桌面完成具体细节可分为Android系统启动的七个步骤。下面我们来分析一下:

1.1.1 启动电源启动系统

        触当电源按下时引导芯片从预定义的地方(固化在ROM)开始执行。加载引导程序BootLoader到RAM中,然后执行。

1.1.2 启动BootLoader引导程序

        引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是将AndroidOS拉起来。

1.1.3 启动linux内核

         当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置后,它首先会在系统文件中寻找init.rc文件,并启动init.rc进程。

1.1.4 启动init进程

        init进程启动做了很多工作,但是总的来说主要就是做了一下三件事:

        (1)创建和挂载启动所需文件目录。 

        (2)初始化和启动系统属性服务。

        (3)解析init.rc配置文件并启动Zygote进程。

1.1.5 启动zygote进程孵化器

        程序上app_process进程启动zygote进程。zygote主要创建Java虚拟机并为Java虚拟机注册JNI方法;创建服务端Socket;预加载类和资源;启动SystemServer进程;等待AMS请求创建新的应用进程。

1.1.6 启动systemServer进程

        创建并启动Binder线程池,这样可以和其他进程进行通信。

        创建SystemServiceManager,其用于对系统的服务进行创建、启动和生命周期的管理。

        启动系统中的各种服务。包括我们熟悉的AMS、PMS、WMS。

1.1.7 启动Launcher

        被SystemServer启动的AMS会启动Launcher,Launcher启动后会将已安装应用的图标显示在桌面上。

1.2 车载Android启动的区别

        车载Android启动是在前面1.1Android系统启动流程中SystemServer开始,有区别。车载Android在SystemServer中启动独有的CarService。下图虚线部分:

2 车载CarService启动

         CarService是车载Android系统的核心服务之一,所有应用都需要通过CarService来查询、控制整车的状态。不仅仅是车辆控制,实际上CarService几乎就是整个车载Framework最核心的组件。提供了一系列的服务与HAL层的VehicleHAL通信,进而通过车载总线(例如CAN总线)与车身进行通讯,同时它们还为应用层的APP提供接口,从而让APP能够实现对车身的控制与状态的显示。

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

 2.1 CarServiceHelperService启动

         SystemServer进程启动后会调用main()->run()->startOtherService()方法,通过判断当前系统是否是车载分支的版本,是则创建CarServiceHelperService。

package com.android.server;// ...public final class SystemServer {// ...        private void startOtherServices() {    // ...        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {            traceBeginAndSlog("StartCarServiceHelperService");            mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);            traceEnd();        }    // ...    }// ...}

         SystemServer中使用Service管理代理SystemServiceManager的startService方法通过反射构建com.android.internal.car.CarServiceHelperService。CarServiceHelperService也是继承自SystemService,初始化成功后调用onStart()方法启动。

public class SystemServiceManager { // ...        @SuppressWarnings("unchecked")    public SystemService startService(String className) {        final Class serviceClass;        try {            serviceClass = (Class)Class.forName(className);        } catch (ClassNotFoundException ex) {            Slog.i(TAG, "Starting " + className);            throw new RuntimeException("Failed to create service " + className                    + ": service class not found, usually indicates that the caller should "                    + "have called PackageManager.hasSystemFeature() to check whether the "                    + "feature is available on this device before trying to start the "                    + "services that implement it", ex);        }        return startService(serviceClass);    }    public  T startService(Class serviceClass) {        try {            // ...            startService(service);            return service;        } finally {            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);        }    }    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");    }// ...}

2.2 车载CarService进程启动        

        onStart()方法中使用AIDL启动CarService(新的进程),并加载jni库为CarService提供必要的API。CarServiceHelperService重写后的onStart()需要重点看一下:

package com.android.internal.car;// ...public class CarServiceHelperService extends SystemService {// ...     private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";    @Override    public void onStart() {        Intent intent = new Intent();        intent.setPackage("com.android.car");        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");    }// ...}

2.3 CarServer启动图 

大致流程分为以下几步:

        1.SystemServer初始化时候调用startOtherService()。

        2.startOtherService()方法通过SystemServerManager对象的startService()启动CarServiceHelperService,并调用其onStart()方法。

        3.CarServiceHelperService通过bindServiceAsUser()方法启动CarService

        4.CarService被创建后,onCreate方法调用进行初始化当前对象。

 3 车载CarService内部实现

CarService进入启动时序后,onCreate()方法中进行一系列的自身的初始化操作,步骤如下:

        1)通过HIDL接口获取到HAL层的IHwBinder对象-IVehicle,与AIDL的用法类似,必须持有IHwBinder对象我们才可以与Vehicle HAL层进行通信。

        2)创建ICarImpl对象,并调用init方法,它就是ICar.aidl接口的实现类,我们需要通过它才能拿到其他的Service的IBinder对象。

        3)将ICar.aidl的实现类添加到ServiceManager中。

        4)设定SystemProperty,将CarService设定为创建完成状态,只有包含CarService在内的所有的核心Service都完成初始化,才能结束开机动画并发送开机广播。

@Overridepublic void onCreate() {    Log.i(CarLog.TAG_SERVICE, "Service onCreate");    mCanBusErrorNotifier = new CanBusErrorNotifier(this  );    mVehicle = getVehicle();    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CREATE, mVehicle == null ? 0 : 1);    if (mVehicle == null) {        throw new IllegalStateException("Vehicle HAL service is not available.");    }    try {        mVehicleInterfaceName = mVehicle.interfaceDescriptor();    } catch (RemoteException e) {        throw new IllegalStateException("Unable to get Vehicle HAL interface descriptor", e);    }    Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CONNECTED, mVehicleInterfaceName);    mICarImpl = new ICarImpl(this,            mVehicle,            SystemInterface.Builder.defaultSystemInterface(this).build(),            mCanBusErrorNotifier,            mVehicleInterfaceName);    mICarImpl.init();    // 处理 HIDL 连接linkToDeath(mVehicle, mVehicleDeathRecipient);    ServiceManager.addService("car_service", mICarImpl);    SystemProperties.set("boot.car_service_created", "1");    super.onCreate();}

3.1 IVehicle对象创建

        通过HIDL接口获取到HAL层的IHwBinder对象-IVehicle,与AIDL的用法类似,必须持有IHwBinder对象我们才可以与Vehicle HAL层进行通信。

@Nullableprivate static IVehicle getVehicle() {    final String instanceName = SystemProperties.get("ro.vehicle.hal", "default");    try {        return android.hardware.automotive.vehicle.V2_0.IVehicle.getService(instanceName);    } catch (RemoteException e) {        Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle/" + instanceName + " service", e);    } catch (NoSuchElementException e) {        Log.e(CarLog.TAG_SERVICE, "IVehicle/" + instanceName + " service not registered yet");    }    return null;}

3.2 实现Service服务,ICarImpl实现

接着我们再来看ICarImpl的实现,如下所示:

3.2.1 创建各个核心服务对象。

3.2.2 把服务对象缓存到CarLocalServices中,主要为了方便Service之间的相互访问。

ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,         CanBusErrorNotifier errorNotifier, String vehicleInterfaceName,         @Nullable CarUserService carUserService,         @Nullable CarWatchdogService carWatchdogService) {    ...    // 创建 核心服务对象mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),            systemInterface, mCarUserService);    ...    // 将重要的服务缓存到 CarLocalServicesCarLocalServices.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);    CarLocalServices.addService(CarOccupantZoneService.class, mCarOccupantZoneService);    CarLocalServices.addService(AppFocusService.class, mAppFocusService);    // 将创建的服务对象依次添加到一个list中保存起来List allServices = new ArrayList<>();    allServices.add(mFeatureController);    allServices.add(mCarUserService);    ...    allServices.add(mCarWatchdogService);    // Always put mCarExperimentalFeatureServiceController in last.addServiceIfNonNull(allServices, mCarExperimentalFeatureServiceController);    mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);}

3.2.3 将服务对象放置一个list中。这样init方法中就可以以循环的形式直接调用服务对象的init,而不需要一个个调用。VechicleHAL的程序也会在这里完成初始化。

@MainThreadvoid init() {    mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);    traceBegin("VehicleHal.init");    // 初始化 Vechicle HAL    mHal.init();        traceEnd();    traceBegin("CarService.initAllServices");    // 初始化所有服务    for (CarServiceBase service : mAllServices) {        service.init();    }    traceEnd();}

3.2.4 最后实现ICar.aidl中定义的各个接口就可以了

@Overridepublic IBinder getCarService(String serviceName) {    if (!mFeatureController.isFeatureEnabled(serviceName)) {        Log.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;       ...        default:            IBinder service = null;            if (mCarExperimentalFeatureServiceController != null) {                service = mCarExperimentalFeatureServiceController.getCarService(serviceName);            }            if (service == null) {                Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:"                        + serviceName);            }            return service;    }}

3.3 CarService运行图 

3.4 总结

     CarService实现的功能几乎就是覆盖整个车载Framework的核心。

     然而现实中为了保证各个核心服务的稳定性,同时降低CarService协同开发的难度,一般会选择将一些重要的服务拆分单独作为一个独立的Service运行在独立的进程中,导致有的车机系统中CarService只实现了CarPropertyService的功能。

     CarService实现流程可以这样理解:提供IVehicle对象与底层交互,提供ICarImpl初始化一系列服务交给ServiceManager管理,而这些服务可以通过IVehicle对象调用底层的API,CarService充当一个中介代理的角色存在。

来源地址:https://blog.csdn.net/u010687761/article/details/129628272

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【Android车载系列】第2章 车载系统启动与CarService

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录