车载 Android之 核心服务 - CarPropertyService 解析

重要类的源码文件名及位置:

  • CarPropertyManager.java

packages/services/Car/car-lib/src/android/car/hardware/property/

  • CarPropertyService.java

packages/services/Car/service/src/com/android/car/

类的介绍:

CarPropertyManager:是CarPropertyService在客户端的代理,通过 CarPropertyManager中 提供的 API,可以设置和获取车辆各个属性的状态。但在实际使用时,CarPropertyManager 却未必是开发者使用最频繁的对象。尤其是在 Android9平台上开发时,当开发者想控制 空调相关的功能的时候,也许会使用 CarHvacManager;当想获取车辆信息的时候,也许会 使用 CarInfoManager;当想获取车辆传感器数据的时候,会使用 CarSensorManager。但其 实无论是 CarHvacManager还是 CarInfoManager或是 CarSensorManager,它们最后都会 通过 CarPropertyManager来获取设置属性,在服务端对应的都是 CarPropertyService。通 过ICarImpl中getCarService方法也可以很清楚地发现这一点,在Android 10中,谷歌官方直接推荐使用CarPropertyManager;

CarPropertyService:绝大部分与车辆硬件相关联的属性,如空调、车舱功能、车辆传感器等都是通过CarPropertyService来读取或者设置的。

类的使用:

CarPropertyManager:在安卓9中CarPropertyManger还是隐藏(hide)接口,所以不会在公开的SDK中出现,但是它十分重要。而在Android 10中,CarPropertyManger变成了车辆属性的主要API,并允许任何运行在Android Automotive OS上的应用进行调用。初看CarPropertyManger会觉得很熟悉,它的方法包括(但不限于)以下这些:

boolean registerListener(CarPropertyEventCallback callback, int prop, float rate)
boolean isPropertyAvailable(int propId, int area) 
boolean getBooleanProperty(int prop, int area)
float getFloatProperty(int prop, int area)
int getIntProperty(int prop, int area)
int[] getIntArrayProperty(int prop, int area)
<E> CarPropertyValue <E> getProperty(Class <E> clazz, int propId, int area) 
<E> CarPropertyValue <E> getProperty(int prop, int area)
<E> void setProperty()(Class <E> clazz, int propId, int area,E val) 
void setBooleanProperty(int prop, int area, boolean val)
void setFloatProperty (int prop int area, float val)
void setIntProperty (int prop, int area, int val) 

看到这些方法,就会发现和 CarHvacManager、CarVendorExtensionManager等服务中 的方法定 义 很 类 似。在 使 用 方 法 上 和 之 前 提 到 的 几 个 服 务 也 是 一 样 的。其 实,无 论 是 CarInfoManager,还是 CarSensorManager或 CarHvacManager,它们的功能都可以直接通 过 CarPropertyManager来完成。

1.CarPropertyManager的用法

熟悉了 CarHvacManager、CarVendorExtensionManager等几个相关服务的用法之后, 在 CarPropertyManager的使用上,相信读者对相关方法已经很了解了。这里再做一些简单 的补充。 关于属 性 的 获 取,在 CarPropertyManager 中 除 了 getProperty 方 法 之 外,还 有 像 getBooleanProperty、getIntProperty这样明确属性类型的获取方法。其实这些方法只是对 于getProperty方法的封装,以getIntProperty为例,它的实现是这样的:

看上去在明确知道属性类型的情况下,getBooleanProperty、getIntProperty等方法在 使用上更加简洁。但是在这里,依然推荐开发者们使用getProperty来获取相应的属性值, 因为getProperty方法返回的是 CarPropertyValue对象,其不仅包含属性值,还包含属性的 状态,而getIntProperty等方法在属性不可用的情况下,返回的是默认值,这在有的时候会 导致读取的数据不正确。 下面以 NIGHT_MODE(昼夜模式)属性为例,说明使用getProperty方法的好处。

从这段源码中,可以很直观地看到使用getProperty方法,与getBooleanProperty方法 获取昼夜状态相比,可以更准确地判断当前属性的状态,并在属性不支持或不可用时,使用 更合理的处理逻辑。因此,虽然 getProperty方法会增加源码的数量,但在大部分情况下, 依然推荐大家使用该方式获取属性。

        在注册 监 听 属 性 变 化 方 面,CarPropertyManager 提 供 更 细 颗 粒 度 的 监 听 方 法, registerListener① 方法可以监听单个属性值的变化,开发者可以通过在注册监听器时传入 属性ID指定监听器所对应的属性。同时,可以指定数据上报的频率,与5.2节介绍的一样, 该频率与属性类型和其他监听器的频率有关,并不能保证数据会以传入的期望频率进行上 报。监听属性的方式,可参考以下源码:

CarPropertyManager.CarPropertyEventListener mCarPropertyEventListener = new CarPropertyManager.CarPropertyEventListener() {
        @Override
        public void onChangeEvent(CarPropertyValue value) {

        }

        @Override
        public void onErrorEvent(int propId, int zone) {
        }
    };

    mCarPropertyManager.registerListener(mCarPropertyEventListener,VehiclePropertyIds.PERF_VEHICLE_SPEED,/ * rate=* / 5);

2.CarPropertyManager的相关类

除了和 CarPropertyManager相关的这几个 Manager之外,在之前的例子中,还出现了 如 VehiclePropertyIds、CarPropertyValue、CarPropertyConfig等相关的辅助类,由于种类 繁多,有必要在这里梳理一下各个辅助类的作用。

(1)VehiclePropertyIds,CarPropertyManager都是通过属性ID来对应具体的功能的, 不同功能对应不同的ID,VehiclePropertyIds中列出了所有在 VehicleHAL 中定义的功能 属性,是AndroidAutomotiveOS官方定义的属性集合。

(2)VehicleAreaDoor,许多功能点都分多个区域,在设置、获取相应属性时,需要传入区域 参数,VehicleAreaDoor定义了与车门相关的区域值,在使用与车门相关的属性时配套使用。

(3)VehicleAreaMirror,与 VehicleAreaDoor类似,多区域定义,后视镜区域值。

(4)VehicleAreaSeat,多区域定义,座位区域值。

(5)VehicleAreaWheel,多区域定义,车胎区域值。

(6)VehicleAreaWindow,多区域定义,车窗区域值。

(7)VehicleAreaType,区域类型是用以区分一个属性所对应的位置的。对于非多区域 属性,往往使用 VEHICLE_AREA_TYPE_GLOBAL 作为其区域ID。每个区域属性都必 须使用预定义的区域类型,即车门、车窗、座椅、轮胎、后视镜中的一个。每种区域类型都有 一组在区域类型的枚举中定义的位标记,也就是前文中使用的像SEAT_ROW_1_LEFT 这 53 第 5 章 CarPropertyService———车辆属性服务 样具体的区域值。

(8)VehicleLightState,灯光状态,开、关、日间。

(9)VehicleLightSwitch,灯光切换,开、关、日间、自动。

(10)VehicleOilLevel,油量状态。

以上这些辅助类中,都定义了相关的静态变量,同时,这些值都与 VehicleHAL 的相关 定义一一对应,在 CarAPI中将其再次定义是为了方便上层应用使用。

        除了以上 几 个 定 义 静 态 变 量 的 辅 助 类 以 外,还 会 经 常 用 到 CarPropertyConfig 和 CarPropertyValue这两个模板类。CarPropertyConfig和 CarPropertyValue非常有用,通 过前者能获取到一个属性的静态参数,如取值范围、类型、支持的区域等;通过后者能获取 一个属性的值和状态。

        这里举两个简单的例子。

        (1)通过 CarPropertyManager获取当前车辆支持的属性(注意,需要拥有对应属性的 权限才能获取)。

CarPropertyConfig对象的成员变量如表5-4所示。

开发者可以通过以上成员变量对应的 get方法获取具体的值。对于区域属性来说, CarPropertyConfig中还封装了额外的方法方便开发者获取特定区域的取值,AreaConfig类 的getMinValue、getMaxValue方法可以返回某一属性特定区域的取值范围。

        (2)通过 CarPropertyManager获取当前的车速。

        CarPropertyValue对象的成员变量如表5-5所示。

虽然看上去很简单,但实际使用过程中会涉及较多的判断,开发者可以进一步对属性进 行封装管理,并总结一些有用的实践。CarPropertyConfig和 CarPropertyValue这两个类 同样 和 VehicleHAL 中 的 定 义 的 结 构 体 相 关 联,CarService 会 将 从 HAL 层 获 取 的 VehiclePropConfig和 VehiclePropValue① 分别转换为CarPropertyConfig和CarPropertyValue。

3.进一步了解 CarPropertyManager 

通过前文的介绍,读者应该已经了解了 CarPropertyManager的重要性。因此有必要进 一步了解 CarPropertyManager背后的原理,更全面地掌握它。 熟悉 Android的读者应该知道,在 Android中往往一个 Manager会对应一个Service,例如 ActivityManager对应着 ActivityManagerService;PackageManager对应着PackageManagerService。 它 们 运 行 在 不 同 的 进 程 中,通 过 Binder 这 一 IPC 机 制 进 行 通 信。 同 样 地,与 CarPropertyManager相对应的是 CarPropertyService这一服务。 同时,读者如果对车辆电子电器的架构有一定了解,那么应该知道,各个具体的功能往 往有对应的电子控制单元(ElectronicControlUnit,ECU)进行控制。例如,控制座椅位置 的命令,最终需要发送到负责控制座椅的 ECU 中才能使座椅移动。 因此,一次控制命令的调用过程大致如图5-1所示。

上层的应用通过 CarAPI提供的接口进行设置,最终通过车辆总线将命令发送给对应 的 ECU,ECU 返 回 结 果 给 CarService,并 通 过 回 调 通 知 相 关 应 用。 这 一 过 程 中 的 ① VehiclePropConfig和 VehiclePropValue定义在/hardware/interfaces/automotive/vehicle/2.0/types.hal文件中。 55 第 5 章 CarPropertyService———车辆属性服务 VehicleHAL非 常 重 要,它 指 的 是 制 造 商 实 现 的 硬 件 抽 象 层 服 务,实 现 了 Android AutomotiveOS定义的相关硬件抽象层接口。由于不同汽车制造商与ECU 的通信方式、标 准、数据格式都不尽相同,所以需要对其进行抽象,统一接口,而具体逻辑则由汽车制造商自 己实现。关于 VehicleHAL的具体内容,会在后面的章节再展开。 下面通过源码,进一步了解 CarPropertyManager中的具体实现,建议读者在阅读的同 时打开源码文件进行查看。 以下是 CarPropertyManager的构造函数实现:

在 CarPropertyManager的构造函数中,获得了ICarProperty的远程对象,通过该远程 对象就可以调用 CarPropertyService。关于 Binder机制的具体实现及 AIDL 的调用过程, 在此就不做展开了①。 再来看看 CarPropertyManager的setProperty的调用过程:

通过 mService对象,调用 CarPropertyService中对应的方法:

这里出现了一个新的对象 mHal,它是 PropertyHalService对象的实例。

接着调用 VehicleHal的set方法,虽然对象命名叫 VehicleHal,但该 VehicleHal对象 依然是在CarService进程中定义并创建的对象。还没有看到对 HAL层的Binder调用。接着往下:

VehicleHal中的set方法只是进一步调用了 HalClient对象的setValue方法。

在 HalClient的setValue方法中,终于发现这个 mVehicle对象是一个 HIDL调用的远 程对象,通过它,实际上调用的是抽象层 VehicleHal的实现。这里涉及了 Android8.0引入 的 HIDL机制,不详细展开了①。随着 HIDL 机制的引入,VehicleHal运行在独立的进程 中,由设备制造商或汽车制造商进行实现。

        以上就是一次完整的设置属性值的调用过程,可以看到设置命令最终将发送给制造商 实现的 VehicleHal进程,并由 VehicleHal最终完成该次调用。

        再来追踪 VehicleHal中的事件的传递过程。

        通过设置的流程,可以发现发起 HIDL调用的远程对象是被 HalClient对象所持有的, 与 VehicleHal的 直 接 交 互 是 在 HalClient 中 完 成 的。 因 此 事 件 的 向 上 传 递 也 是 从 HalClient开始的。在收到上报的事件之前,上层应用首先要注册相应的监听方法。

        当应用调用 CarPropertyManager的registerListener方法时,其会调用 CarPropertyService 的registerListener方法。

上述源码进一步 调 用 PropertyHalService的 subscribeProperty 方 法,中 间 会 再 经 过 VehicleHal.java的调用,最后调用 HalClient中的subscribe方法,调用的路径和设置的流 程是一样的。在此省略一些中间过程,直接来看 HalClient的subscribe方法的实现:

  这里将 mInternalCallback对象传递给了 Hal层。mInternalCallback对象的实例是继 承了IVehicleCallback.Stub的 HIDL桩对象,实现如下:              

通过IVehicleCallback,制造商实现的 VehicleHal进程就可以将事件传递给 CarService 进程了。有兴趣的读者可以进一步追踪当IVehicleCallback的onPropertyEvent方法被调 用后,事件又是如何传递给应用注册的监听器的。

        上文出现了一些新的对象,为了便于理解,整理上述类之间的关系,见图5-2。

在 CarService中虽然有 VehicleHal类,但该类并不直接调用 HIDL 方法,而是进一步 调 用 HalClient 封 装 的 方 法,HalClient 才 是 真 正 与 HAL 层 打 交 道 的 类。 同 时, PropertyHalService处理与 CarPropertyService相关的业务逻辑,在后面的内容中,还会接触 InputHalService、PowerHalService,VehicleHal会将不同的事件分发给对应的类进行处理。 总体来说,通过 CarPropertyService的层层调用,最后通过IVehicle与实现了车辆硬件 抽象层的进程通信。VehicleHal进程由各个厂家进行实现,再进一步将消息发送给关联的 ECU,实现控制功能。

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

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

相关文章

基于多反应堆的高并发服务器【C/C++/Reactor】(中)在EventLoop中处理被激活的文件描述符的事件

文件描述符处理与回调函数 一、主要概念 反应堆模型&#xff1a;一种处理系统事件或网络事件的模型&#xff0c;当文件描述符被激活时&#xff0c;可以检测到文件描述符&#xff1a;在操作系统中&#xff0c;用于标识打开的文件、套接字等的一种数据类型 处理激活的文件描述符…

k8s中ConfigMap详解及应用

一、ConfigMap概述 ConfigMap是k8s的一个配置管理组件&#xff0c;可以将配置以key-value的形式传递&#xff0c;通常用来保存不需要加密的配置信息&#xff0c;加密信息则需用到Secret&#xff0c;主要用来应对以下场景&#xff1a; 使用k8s部署应用&#xff0c;当你将应用配置…

DrGraph原理示教 - OpenCV 4 功能 - 二值化

二值化&#xff0c;也就是处理结果为0或1&#xff0c;当然是针对图像的各像素而言的 1或0&#xff0c;对应于有无&#xff0c;也就是留下有用的&#xff0c;删除无用的&#xff0c;有用的部分&#xff0c;就是关心的部分 在图像处理中&#xff0c;也不仅仅只是1或0&#xff0c;…

docker安装postgresql15或者PG15

1. 查询版本 docker search postgresql docker pull postgres:15.3 # 也可以拉取其他版本2.运行容器并挂载数据卷 mkdir -p /data/postgresql docker run --name postgres \--restartalways \-e POSTGRES_PASSWORDpostgresql \-p 5433:5432 \-v /data/postgresql:/var/lib/p…

工业制造领域,折弯工艺如何进行优化?

若将消费互联网与工业互联网相比较&#xff0c;消费互联网就好似一片宽度为1000米、深度仅有1米的水域&#xff0c;而工业互联网则类似于宽度有1000米、深达10000米的海域。消费互联网因为被限制了深度&#xff0c;便只能在浅显的焦虑中创造出一种消费趋势。相较之下&#xff0…

数据库迁移工具包:DBSofts ESF Database Migration Crack

ESF 数据库迁移工具包 - 11.2.17 允许您通过 3 个步骤在各种数据库格式之间迁移数据&#xff0c;无需任何脚本&#xff01; DBSofts ESF Database Migration它极大地减少了与以下任何数据库格式之间迁移的工作量、成本和风险&#xff1a;Oracle、MySQL、MariaDB、SQL Server、…

(15)Linux 进程创建与终止函数forkslab 分派器

前言&#xff1a;本章我们主要讲解进程的创建与终止&#xff0c;最后简单介绍一下 slab 分派器。 一、进程创建&#xff08;Process creation&#xff09; 1、分叉函数 fork 在 中&#xff0c; fork 函数是非常重要的函数&#xff0c;它从已存在进程中创建一个新的进程。 …

html引入react以及hook的使用

html引入react 效果代码注意 效果 分享react demo片段的时候&#xff0c;如果是整个工程项目就有点太麻烦了&#xff0c;打开速度慢&#xff0c;文件多且没必要&#xff0c;这个时候用html就很方便。 在html中能正常使用useState 和 useEffect 等hook。 代码 <!DOCTYPE htm…

助力成长的开源项目 —— 筑梦之路

闯关式 SQL 自学&#xff1a;sql-mother 免费的闯关式 SQL 自学教程网站&#xff0c;从 0 到 1 带大家掌握常用 SQL 语法&#xff0c;目前一共有 30 多个关卡&#xff0c;希望你在通关的时候&#xff0c;变身为一个 SQL 高手。除了闯关模式之外&#xff0c;这个项目支持自由选…

Redis(二)数据类型

文章目录 官网备注十大数据类型StringListHashSetZSetBitmapHyperLogLog&#xff1a;GEOStreamBitfield 官网 英文&#xff1a;https://redis.io/commands/ 中文&#xff1a;http://www.redis.cn/commands.html 备注 命令不区分大小写&#xff0c;key区分大小写帮助命令help…

阿里云服务器开放端口Oracle 1521方法教程

阿里云服务器ECS端口是在安全组设置的&#xff0c;Oracle数据库1521端口号开放是在安全组中添加规则来实现的&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云服务器开放Oracle 1521端口方法教程&#xff1a; 阿里云服务器开放Oracle 1521端口 在阿里云服务器ECS…

前端Web系统架构设计

文章目录 1.目录结构定义2. 路由封装2.1 API路由定义2.2 组件路由定义 3. Axios请求开发4. 环境变量封装5. storage模块封装(sessionStorage, localStorage)6. 公共函数封装(日期,金额,权限..)7. 通用交互定义(删除二次确认,类别,面包屑...)8. 接口全貌概览 1.目录结构定义 2. …

mysql 单表 操作 最大条数验证 以及优化

1、背景 开车的多年老司机&#xff0c;是不是经常听到过&#xff0c;“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”&#xff0c;“你这个表数据都马上要到 2000w 了&#xff0c;难怪查询速度慢”。 2、实验 实验一把看看… 建一张表 CREATE TABL…

机器学习-基于Word2vec搜狐新闻文本分类实验

机器学习-基于Word2vec搜狐新闻文本分类实验 实验介绍 Word2vec是一群用来产生词向量的相关模型&#xff0c;由Google公司在2013年开放。Word2vec可以根据给定的语料库&#xff0c;通过优化后的训练模型快速有效地将一个词语表达成向量形式&#xff0c;为自然语言处理领域的应…

STC进阶开发(三)蜂鸣器、RTC时钟、I2C总线、外部中断、RTC闹钟设置、RTC计时器设置

前言 这一期我们首先学习如何让蜂鸣器响起来&#xff0c;并且如何让蜂鸣器发出简单的歌曲&#xff0c;然后我们介绍RTC时钟&#xff0c;要想明白RTC时钟&#xff0c;我们还需要先介绍I2C总线和外部中断。接下来就开始这一期的学习吧&#xff01; 蜂鸣器 简单介绍 蜂鸣器是一种…

论文笔记:CellSense: Human Mobility Recovery via Cellular Network Data Enhancement

1 intro 1.1 背景 1.1.1 蜂窝计费记录&#xff08;CBR&#xff09; 人类移动性在蜂窝网络上的研究近些年得到了显著关注&#xff0c;这主要是因为手机的高渗透率和收集手机数据的边际成本低蜂窝服务提供商收集蜂窝计费记录&#xff08;CBR&#xff09;用于计费目的&#xf…

哲学家进餐问题-第三十二天

目录 问题描述 解决问题 结论 问题描述 解决问题 1、 关系分析&#xff1a;找出题目中描述的各个进程&#xff0c;分析它们之间的同步、互斥关系 系统中有5个哲学家进程&#xff0c;5位哲学家与左右邻居对其中间筷子的访问是互斥关系 2、整理思路&#xff1a;根据各进程的操…

ubuntu terminator 非常好用的护眼配置

安装 sudo apt install terminator 配置文件&#xff1a;sudo gedit ~/.config/terminator/config &#xff08;如果没有就创建&#xff09; 配置如下&#xff1a; [global_config] handle_size -3 title_transmit_fg_color "#000000" title_trans…

KBDNO1.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复

不少小伙伴&#xff0c;求助电脑报错“KBDNO1.DLL文件缺失&#xff0c;软件或游戏无法启动或运行”&#xff0c;应该怎么办&#xff1f; 首先&#xff0c;我们先来了解“KBDNO1.DLL文件”是什么&#xff1f; KBDNO1.DLL是Windows操作系统中的一个动态链接库文件&#xff0c;主…

Java基础进阶(学习笔记)

注&#xff1a;本篇的代码和PPT图片来源于黑马程序员&#xff0c;本篇仅为学习笔记 static static 是静态的意思&#xff0c;可以修饰成员变量&#xff0c;也可以修饰成员方法 修饰成员的特点&#xff1a; 被其修饰的成员, 被该类的所有对象所共享 多了一种调用方式, 可以通过…