车载技术开发—{Android CarFrameWork}

news2024/11/15 6:54:46

Android Automotive平台

Android Automotive是通过Android的通用框架,语言和API来实现的一个全栈,开源,高度可定制的平台。

Android Automotive与整个Android生态系统的关系

  • Android Automotive是Android的一部分。 Android Automotive不是Android的分支或并行开发,它与手机,平板电脑等安卓设备上的Android具有相同的代码库,并且位于相同的存储库中。它基于经过10多年开发的强大平台和功能集,可利用现有的安全模型,兼容性程序,开发人员工具和基础架构,同时继续具有高度可定制性和可移植性,完全免费和开源的特点。
  • Android Automotive扩展了Android 。在将Android打造为功能齐全的信息娱乐平台的过程中,我们添加了对汽车特定要求,功能和技术的支持。就像今天用于移动设备的Android一样,Android Automotive将是一个完整的汽车信息娱乐平台。

Android Automotive架构

Automotive

Android Automative是在原先Android的系统架构上增加了一些与车相关的(图中虚线框中绿色背景的)模块。

  • Car App :包括OEM和第三方开发的App
  • Car API :提供给汽车App特有的接口
  • Car Service :系统中与车相关的服务,主要是基于CarProperty实现Vechile相关的一些策略
  • Vehicle Network Service :汽车的网络服务
  • Vehicle HAL :汽车的硬件抽象层描述,定义 OEM 可以实现的车辆属性的接口

Android CarAPI

CarAPI

· annotation:包含了两个注解。 · app · menu:车辆应用菜单相关API。 · cluster:仪表盘相关API。 · render:渲染相关API。 · content · pm:应用包相关API。 · diagnostic:包含与汽车诊断相关的API。 · hardware:车辆硬件相关API。 · cabin:座舱相关API。 · hvac:通风空调相关API。 · property:属性相关API(实现定制的property)。 · radio:收音机相关API。 · input:输入相关API。 · media:多媒体相关API。 · navigation:导航相关API。 · settings:设置相关API。 · vms:汽车监测相关API

这些api集合中,我们可以通过CarpropertyManager去实现定制的property功能,简要类图:

CarpropertyManager内部方法

  • 通过registerListener注册自定义的propertyId以及property变更通知的callback

  • 解注册CarpropertyEventListener

  • 获取所有property, 返回一个元素类型是CarpropertyConfig的list

  • 获取property状态

  • 获取property value

  • 设置property value

CarpropertyManager与service层交互的AIDL接口

需要注意的是ICarProperty是同步接口,ICarPropertyEventListener是异步接口。

onEvent传上来的是参数是CarPropertyEvent的list,CarPropertyEvent中包含event type与CarPropertyValue; eventType包含PROPERTY_EVENT_PROPERTY_CHANGE与PROPERTY_EVENT_ERROR,分别对应listener中的onPropertyChanged和PROPERTY_EVENT_ERROR, CarPropertyValue则包含具体的propId、propValue等具体属性信息。

Android CarService

代码目录: packages/services/Car/service
  • CarService并非一个服务,而是一系列的服务。这些服务都在ICarImpl.java构造函数中列了出来

CarService启动流程

启动CarServiceHelperService

SystemServer启动过程中,在ActivityManagerService systemReady时,启动CarServiceHelperService。 代码:

android/frameworks/base/services/java/com/android/server/SystemServer.java
​
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    t.traceBegin("StartCarServiceHelperService");
    final SystemService cshs = mSystemServiceManager
            .startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
    if (cshs instanceof Dumpable) {
        mDumper.addDumpable((Dumpable) cshs);
    }
    if (cshs instanceof DevicePolicySafetyChecker) {
        dpms.setDevicePolicySafetyChecker((DevicePolicySafetyChecker) cshs);
    }
    t.traceEnd();
}
​
private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
        "com.android.internal.car.CarServiceHelperService";

启动CarService

CarServiceHelperService在onStart时拉起CarServcie,加载Native库car-framework-service-jni。

代码:

android/frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
​
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);
    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");
}
​

代码:

android/packages/services/Car/car-lib/src/com/android/car/internal/common/CommonConstants.java
​
public static final String CAR_SERVICE_INTERFACE = "android.car.ICar";

代码:

android/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="@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>

初始化ICarImpl

CarService在onCreate时先判断Vehicle HAL起来了,然后再初始化ICarImpl。 代码:

android/packages/services/Car/service/src/com/android/car/CarService.java
​
public void onCreate() {
    LimitedTimingsTraceLog initTiming = new LimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,
            Trace.TRACE_TAG_SYSTEM_SERVER, CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
    initTiming.traceBegin("CarService.onCreate");
​
    initTiming.traceBegin("getVehicle");
    mVehicle = getVehicle();
    initTiming.traceEnd();
    
    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);
    }
    
    Slog.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CONNECTED, mVehicleInterfaceName);
    
    mICarImpl = new ICarImpl(this,
            mVehicle,
            SystemInterface.Builder.defaultSystemInterface(this).build(),
            mVehicleInterfaceName);
    mICarImpl.init();
    
    linkToDeath(mVehicle, mVehicleDeathRecipient);
    
    ServiceManager.addService("car_service", mICarImpl);
    SystemProperties.set("boot.car_service_created", "1");
    
    super.onCreate();
    
    initTiming.traceEnd(); // "CarService.onCreate"
}
​
private 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) {
        Slog.e(CarLog.TAG_SERVICE, "Failed to get IVehicle/" + instanceName + " service", e);
    } catch (NoSuchElementException e) {
        Slog.e(CarLog.TAG_SERVICE, "IVehicle/" + instanceName + " service not registered yet");
    }
    return null;
}
​

代码:

android/packages/services/Car/car-lib/src/android/car/ICar.aidl
android/packages/services/Car/service/src/com/android/car/ICarImpl.java

初始化各个Car Services组件

ICarImpl构造函数中,构造了下面几个实现了CarServiceBase接口的Car Services组件,以及VehicleHal和CarStatsService;然后通过init函数进行初始化。

CarFeatureController
CarPropertyService
CarDrivingStateService
CarUxRestrictionsManagerService
CarUserService
CarOccupantZoneService
SystemActivityMonitoringService
CarPowerManagementService
CarUserNoticeService
CarPackageManagerService
PerUserCarServiceHelper
CarBluetoothService
CarInputService
CarProjectionService
GarageModeService
AppFocusService
CarAudioService
CarNightService
FixedActivityService
ClusterNavigationService
InstrumentClusterService
VmsBrokerService
CarDiagnosticService
CarStorageMonitoringService
CarLocationService
CarMediaService
CarBugreportManagerService
CarExperimentalFeatureServiceController
CarWatchdogService
CarDevicePolicyService
ClusterHomeService
CarEvsService
CarTelemetryService
CarActivityService

初始化各个Hal Services组件

VehicleHal构造函数中,构造了下面几个继承自HalServiceBase基类的Hal Services组件以及HalClient;然后通过init函数进行初始化。

PowerHalService
PropertyHalService
InputHalService
VmsHalService
UserHalService
DiagnosticHalService
ClusterHalService
EvsHalService
TimeHalService

代码:

android/packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

VehicleHAL目录结构

下面是vehicle 2.0参考实现的目录结构。

android/hardware/interfaces/automotive/vehicle/2.0/
|-- default // 默认实现
    |-- common
        |-- include
            |-- vhal_v2_0 // .h
        |-- src // .cpp
    |-- impl
        |-- vhal_v2_0 // impl代码
            |-- proto // proto协议
            |-- tests
    |-- tests
    |-- Android.bp // 编译文件
    |-- VehicleService.cpp // main函数
    |-- android.hardware.automotive.vehicle@2.0-service.rc // init rc
    |-- android.hardware.automotive.vehicle@2.0-service.xml // matrix xml
|-- utils
|-- vts
|-- Android.bp // 编译文件
|-- IVehicle.hal // interface
|-- IVehicleCallback.hal // callback
|-- types.hal // types

Hidl代码有个明显的namespace规则,如下。

namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
namespace V2_0 {
// ...
}  // namespace V2_0
}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android

VehicleHAL启动流程

rc

VehicleHAL由init rc启动。 代码:

android/hardware/interfaces/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
​
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
    class early_hal
    user vehicle_network
    group system inet

main

下面是VehicleHAL的main函数。 代码:

android/hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp
​
int main(int /* argc */, char* /* argv */ []) {
    auto store = std::make_unique<VehiclePropertyStore>();
    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
    auto userHal = connector->getEmulatedUserHal();
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    auto service = std::make_unique<VehicleHalManager>(hal.get());
    connector->setValuePool(hal->getValuePool());
​
    configureRpcThreadpool(4, true /* callerWillJoin */);
    
    ALOGI("Registering as service...");
    status_t status = service->registerAsService();
    
    if (status != OK) {
        ALOGE("Unable to register vehicle service (%d)", status);
        return 1;
    }
    
    ALOGI("Ready");
    joinRpcThreadpool();
    
    return 1;
}
  • VehiclePropertyStore:存储、访问和修改vehicle相关的配置及属性,VehiclePropertyValues存储在有序map中。使用了同步锁,线程安全。
  • EmulatedVehicleConnector:VehicleHalClient与VehicleHalServer通信的连接器。
  • EmulatedUserHal:User Hal。
  • EmulatedVehicleHal:Vehicle Hal。
  • VehicleEmulator:Vehicle Emulator。
  • VehicleHalManager:This class is a thick proxy between IVehicle HIDL interface and vendor’s implementation.

以上为车机开发技术中的CarFrameWork学习;启动流程及原理介绍,更多的车载技术可以前往《车机开发技术手册》查看更多车载技术。

交互

CarService向上与App通过CarLib(aidl)交互,向下与VehicleHAL通过hidl交互,其中包括了一个很重要的概念:Property。 Property可以是静态的,也可以是变化后向上通报的,还可以是以一定的频率实时上报的。 下面以HVAC为例,说明HVAC的控制过程。

  • 【App】调用CarLib中【CarHvacManager】的setBooleanProperty设置Property。
  • 【CarHvacManager】调用CarLib中【CarPropertyManager】的setBooleanProperty。
  • 【CarPropertyManager】将Property封装成CarPropertyValue后调用CarServcie中【ICarProperty-CarPropertyService】的setProperty。(aidl) 【CarPropertyService】调用CarServcie中【PropertyHalService】的setProperty。
  • 【PropertyHalService】将CarPropertyValue封装成VehiclePropValue后调用CarServcie中【VehicleHal】的set。
  • 【VehicleHal】调用CarServcie中【HalClient】的setValue。
  • 【HalClient】调用VehicleHAL中【IVehicle-VehicleHalManager】的set。(hidl)
  • 【VehicleHalManager】,首先,通过订阅这个Property的【Native HalClient】的callback即【IVehicleCallback-HalClient$VehicleCallback】的onPropertySet通知Property变更。(hidl callback)
  • 【VehicleHalManager】,然后,调用【EmulatedVehicleHal】的set。
  • 【EmulatedVehicleHal】检查Property后调用【VehicleHalClient】的setProperty。
  • 【VehicleHalClient】与EmulatedVehicleConnector有关,调用【EmulatedVehicleConnector】的onSetProperty。
  • 【EmulatedVehicleConnector】与VehicleHalServer有关,调用【VehicleHalServer】的onSetProperty。

最终,将Property或转换后的信号发到【Car ECU】。vehicle 2.0模拟实现是将Property存储到VehiclePropertyStore

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

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

相关文章

pbootcms被黑木马问题(3)

昨天经过同事告知发现了很早之间做的几个企业官方都中木马了,然后看了一下木马情况,跟之间的两次都有所不同,这里记录一下新的木马的清理过程,有遇到的朋友可以借鉴一下。&#xff08;之前有做过一些防止批量扫站的措施&#xff0c;因为嫌麻烦就没有给这些网站上进行修改&#…

【Spark分布式内存计算框架——Spark SQL】13. 自定义UDF函数

第七章 自定义UDF函数 无论Hive还是SparkSQL分析处理数据时&#xff0c;往往需要使用函数&#xff0c;SparkSQL模块本身自带很多实现公共功能的函数&#xff0c;在org.apache.spark.sql.functions中。SparkSQL与Hive一样支持定义函数&#xff1a;UDF和UDAF&#xff0c;尤其是U…

黑格尔的实践观探究

&#xff08;江苏大学马克思主义学院 212000&#xff09;一、引言人的独特性在于实践活动&#xff0c;以及由实践活动带来的人类社会的不断进化与发展。人类的实践史体现了人的全部本质。但是&#xff0c;人类从理论的高度反思自己的实践活动&#xff0c;尤其是在哲学的层面上进…

【基础算法】之 冒泡排序优化

冒泡排序思想基本思想: 冒泡排序&#xff0c;类似于水中冒泡&#xff0c;较大的数沉下去&#xff0c;较小的数慢慢冒起来&#xff08;假设从小到大&#xff09;&#xff0c;即为较大的数慢慢往后排&#xff0c;较小的数慢慢往前排。直观表达&#xff0c;每一趟遍历&#xff0c;…

大数据框架之Hadoop:MapReduce(三)MapReduce框架原理——shuffle机制

3.3.1Shuffle机制 Map方法之后&#xff0c;Reduce方法之前的数据处理过程称之为Shuffle。 3.3.2Partition分区 1、问题引出 要求将统计结果按照条件输出到不同文件中&#xff08;分区&#xff09;。比如&#xff1a;将统计结果按照手机归属地不同省份输出到不同文件中&#…

2023春季露营投影怎么选?轻薄投影极米Z6X Pro值得推荐

近年来&#xff0c;露营经济在多重因素的共同助推下快速发展&#xff0c;精致露营的攻略开始占据小红书、微博、朋友圈等各类社交平台&#xff0c;吸引着更多用户种草并加入到露营大军中&#xff0c;而露营经济的强势“破圈”给家用智能投影带来了更多的发展契机。凭借着小巧的…

探访上汽通用武汉奥特能超级工厂

上汽通用汽车在电动化和智能网联化新技术领域投入了700亿大洋&#xff0c;武汉奥特能超级工厂就是其中一个重点项目。这个工厂已经投产&#xff0c;将成为上汽通用汽车的新能源生产基地&#xff0c;加速奥特能平台车型的推出。 最近别克推出了Electra E5&#xff0c;它是别克第…

新品BCM6755A1KFEBG/MT7921LE/MT7921AU WiFi芯片

博通在WiFi市场具有相当的实力。在WiFi6上有下面这几个解决方案&#xff1a;型号&#xff1a;BCM6755 BCM6755A1KFEBG类型&#xff1a;四核1.5GHz CPU封装&#xff1a;BGA批次&#xff1a;新BCM6755和BCM6750还是A7架构&#xff0c;更多的用在中低端型号上。BCM6755和BCM6750 C…

Spark 广播变量累加器

广播变量 场景描述&#xff1a;一份数据存在Driver中&#xff0c;但是每个Executor都需要一份。 常规模式下&#xff0c;Driver会给每个分区都发送一份数据。如果在Executor中存在多个分区的情况&#xff0c;那么一个Executor会获得多份数据。 Executor是进程&#xff0c;task…

微信小程序阻止页面返回(包滑动、自动返回键)

这个场景还是挺有意思的&#xff0c;比如某多多&#xff0c;只要你点左上角的返回 好家伙&#xff0c;满满又 花不了 的优惠券就来了&#xff0c;让你拥有一种消费最划算的感觉。 如果你的场景比较简单&#xff0c;只是对左上角的返回进行监听&#xff0c;只需要关闭自带的导航…

16_FreeRTOS队列集

目录 队列集 队列集相关API函数介绍 队列集使用流程 实验源码 队列集 一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集! 作用:用于对多个队列或信号量进行“监听”其中不管哪一个消息到来&#xff0c;都…

JVM学习笔记四:运行时数据区之虚拟机栈

目录 概述 StackOverflowError测试案例 栈运行原理 栈帧的内部结构 改变栈帧大小的StackOverflowError测试案例 局部变量表 局部变量槽 操作数栈 动态链接 静态链接 动态链接 早期绑定 晚期绑定 方法返回地址 概述 与程序计数器一样&#xff0c;Java虚拟机栈也是…

4665: 求前n项和

描述给定序列&#xff1a;求前n项之和。输入输入数据有多组&#xff0c;第一行为数据的组数t&#xff08;1<t<15&#xff09;。每组数据有一行&#xff0c;每行为一个正整数n&#xff08;n<1000000&#xff09;。输出每组输出前n项的和&#xff0c;保留4位小数。样例输…

【编程入门】应用市场(安卓版)

背景 前面已输出多个系列&#xff1a; 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目&#xff0c;使…

Jmeter常用断言之BeanShell断言详解

BeanShell断言可以使用beanshell脚本来执行断言检查&#xff0c;可以用于更复杂的个性化需求&#xff0c;使用更灵活&#xff0c;功能更强大&#xff0c;但是要能够熟练使用beanshell脚本 在这里除了可以使用beanshell的内置变量外&#xff0c;主要通过 Failure 和 FailureMess…

es 7.8.0 linux 集群

1. 下载es linux版本的数据包 地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch 解压: 解压 tar -xzvf xxx 2. 我是在一个服务器上测试的,实际上是不同的服务器 所以复制了三份,模拟多节点 进去之后主要是修改elasticsearch.yml 内容如下 节点一…

关于在VM上的windows server 2022系统安装

目录 1、windows serer 2022安装的准备工作 1&#xff09;下载系统 2&#xff09;寻找对应系统密钥 3&#xff09;配置server系统开机配置项&#xff08;可能会出现sconfig配置界面&#xff09; 2、开始安装server系统 1、windows serer 2022安装的准备工作 1&#xff09;…

Dropout

目录一、Dropout出现的原因二、什么是Dropout&#xff1f;三、为什么Dropout解决过拟合?3.1 取平均的作用3.2 减少神经元间复杂的共适应关系四、实现Dropout—— pytorchexample 1example 2example 3设置dropout参数技巧一、Dropout出现的原因 在机器学习的模型中 如果模型的…

处理窗口的常用API函数及窗口处理经验总结(附源码)

目录 1、检测窗口状态 2、将窗口前置显示 2.1、将窗口拉到最前面显示 2.2、将窗口置顶显示 2.3、将窗口设置到指定窗口的上面 3、将不显示的窗口强行显示出来 4、获取窗口的信息 5、通过窗口信息去查找窗口 5.1、调用GetClassName接口去比对窗口的类名 5.2、调用Find…

清理bib文件(删除重复项,仅保留tex中引用的条目)

在写latex文件的过程中&#xff0c;经常会遇到添加了一堆文献的bibtex到bib文件中&#xff0c;有时候文章一长同一篇文献用不同的cite-key引用了多次&#xff0c;同时也会有一些文献最后并没被正文引用&#xff0c;这就需要对bib文件进行清理。 删除重复项 可以用JabRef 在J…