【Android】VehiclePropertyAccess引起CarService崩溃
VehiclePropertyAccess引起CarService崩溃
VehiclePropertyAccess
VehiclePropertyAccess属性,用于定义车辆属性的访问权限。权限包括
- 读:READ,只可以读取,不能写入。
VehiclePropertyAccess:READ
- 写:WRITE,只可以写入,不能读取。
VehiclePropertyAccess:WRITE
- 读写
VehiclePropertyAccess:READ_WRITE
这些车辆属性被定义在Vechile的types.hal中。编译时,会被转成VehiclPropConfig,记录到每个车辆属性中。
对于车辆属性的操作,在Android11版本,调用CarService注册监听属性,如果违反了其权限规定,会导致CarService崩溃。
原生CarService因为属性注册崩溃
违反VehiclePropertyAccess权限,导致的CarService崩溃

某应用调用 CarPropertyManager的registerCallback接口,注册监听属性ID。该操作,导致CarService反复崩溃。
崩溃代码流程分析
- CarPropertyService.java,应用调用registerListener注册监听属性ID
@Overridepublic void registerListener(int propertyId, float updateRateHz,ICarPropertyEventListener iCarPropertyEventListener) throws IllegalArgumentException{}
- CarPropertyService.java,服务端对应registerListener的实现
@Override
public void registerListener(int propId, float rate, ICarPropertyEventListener listener)
{if (DBG) {Slog.d(TAG, "registerListener: propId=0x" + toHexString(propId) + " rate=" + rate);}if (listener == null) {Slog.e(TAG, "registerListener: Listener is null.");throw new IllegalArgumentException("listener cannot be null.");}IBinder listenerBinder = listener.asBinder();CarPropertyConfig propertyConfig;Client finalClient;synchronized (mLock) {propertyConfig = mConfigs.get(propId);if (propertyConfig == null) {// Do not attempt to register an invalid propIdSlog.e(TAG, "registerListener: propId is not in config list: 0x" + toHexString(propId));return;}ICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));// Get or create the client for this listenerClient client = mClientMap.get(listenerBinder);if (client == null) {client = new Client(listener);}client.addProperty(propId, rate);// Insert the client into the propId --> clients mapList<Client> clients = mPropIdClientMap.get(propId);if (clients == null) {clients = new CopyOnWriteArrayList<Client>();mPropIdClientMap.put(propId, clients);}if (!clients.contains(client)) {clients.add(client);}// Set the HAL listener if necessaryif (!mListenerIsSet) {mHal.setListener(this);}// Set the new rateif (rate > mHal.getSampleRate(propId)) {mHal.subscribeProperty(propId, rate);}finalClient = client;}// propertyConfig and client are NonNull.mHandler.post(() ->getAndDispatchPropertyInitValue(propertyConfig, finalClient));
}
- 两个主要流程:注册属性,获取属性初始值并派发
public void subscribeProperty(HalServiceBase service, int property,float samplingRateHz, int flags) throws IllegalArgumentException {if (DBG) {Slog.i(CarLog.TAG_HAL, "subscribeProperty, service:" + service+ ", " + toCarPropertyLog(property));}VehiclePropConfig config;synchronized (mLock) {config = mAllProperties.get(property);}if (config == null) {throw new IllegalArgumentException("subscribe error: config is null for property 0x"+ toHexString(property));} else if (isPropertySubscribable(config)) {SubscribeOptions opts = new SubscribeOptions();opts.propId = property;opts.sampleRate = samplingRateHz;opts.flags = flags;synchronized (mLock) {assertServiceOwnerLocked(service, property);mSubscribedProperties.put(property, opts);}try {mHalClient.subscribe(opts);} catch (RemoteException e) {Slog.e(CarLog.TAG_HAL, "Failed to subscribe to " + toCarPropertyLog(property), e);}} else {Slog.e(CarLog.TAG_HAL, "Cannot subscribe to " + toCarPropertyLog(property));}
}
- VehicleHal.java, isPropertySubscribable判断车辆属性是否可读,如果不可读不能注册。比如属性ID是"VehiclePropertyAccess:READ",就不能注册了。
static boolean isPropertySubscribable(VehiclePropConfig config) {if ((config.access & VehiclePropertyAccess.READ) == 0|| (config.changeMode == VehiclePropertyChangeMode.STATIC)) {return false;}return true;
}
- 接下来,获取属性初始值。哪怕不能注册的属性ID,也会去获取,所以导致了上面的CarService崩溃问题。CarPropertyService.java
private void getAndDispatchPropertyInitValue(CarPropertyConfig config, Client client) { List<CarPropertyEvent> events = new LinkedList<>();int propId = config.getPropertyId();if (config.isGlobalProperty()) {CarPropertyValue value = mHal.getPropertySafe(propId, 0);if (value != null) {CarPropertyEvent event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);events.add(event);}} else {for (int areaId : config.getAreaIds()) {CarPropertyValue value = mHal.getPropertySafe(propId, areaId);if (value != null) {CarPropertyEvent event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);events.add(event);}}}try {client.getListener().onEvent(events);} catch (RemoteException ex) {// If we cannot send a record, its likely the connection snapped. Let the binder// death handle the situation.Slog.e(TAG, "onEvent calling failed: " + ex);}
}
- HalClient.java,getValue,获取属性ID的值。
VehiclePropValue getValue(VehiclePropValue requestedPropValue) {final ObjectWrapper<VehiclePropValue> valueWrapper = new ObjectWrapper<>();int status = invokeRetriable(() -> {ValueResult res = internalGet(requestedPropValue);valueWrapper.object = res.propValue;return res.status;}, mWaitCapMs, mSleepMs);if (StatusCode.INVALID_ARG == status) {throw new IllegalArgumentException(getValueErrorMessage("get", requestedPropValue));}if (StatusCode.OK != status || valueWrapper.object == null) {// If valueWrapper.object is null and status is StatusCode.Ok, change the status to be// NOT_AVAILABLE.if (StatusCode.OK == status) {status = StatusCode.NOT_AVAILABLE;}Log.e(TAG, getPropertyErrorMessage("get", requestedPropValue, status));throw new ServiceSpecificException(status,"Failed to get property: 0x" + Integer.toHexString(requestedPropValue.prop)+ " in areaId: 0x" + Integer.toHexString(requestedPropValue.areaId));}return valueWrapper.object;
}
- 如果是VehiclePropertyAccess:READ的属性,上述代码会抛出ServiceSpecificException异常。导致CarService崩溃。code 4,ACCESS_DENIED。
Android12修复方式
android12已修复该问题。使用了getPropertySafe,捕获异常。
/*** Return property or null if property is not ready yet or there is an exception in HAL.*/
@Nullable
public CarPropertyValue getPropertySafe(int mgrPropId, int areaId) {
try {return getProperty(mgrPropId, areaId);} catch (Exception e) {Slog.e(TAG, "get property value failed for property id: 0x "+ toHexString(mgrPropId) + " area id: 0x" + toHexString(areaId)+ " exception: " + e);return null;}
}
相关文章:
【Android】VehiclePropertyAccess引起CarService崩溃
VehiclePropertyAccess引起CarService崩溃 VehiclePropertyAccess VehiclePropertyAccess属性,用于定义车辆属性的访问权限。权限包括 读:READ,只可以读取,不能写入。 VehiclePropertyAccess:READ写:WRITE…...
深度剖析:复制带随机指针的链表算法实现
在链表相关的算法中,复制一个带有随机指针的链表是一个经典且具有一定难度的问题。本文将深入分析一段用C语言实现的复制带随机指针链表的代码,通过模块化的方式详细解释每段代码的作用,帮助读者更好地理解这一复杂算法。 作者主页…...
Java 大视界 -- Java 大数据在智慧文旅旅游目的地营销与品牌传播中的应用(150)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
SQLMesh SCD-2 时间维度实战:餐饮菜单价格演化追踪
场景背景:动态菜单价格管理 考虑某连锁餐厅的菜单管理系统,需要记录食品价格的历史变更轨迹。业务需求包括: 记录每次价格调整的时间点支持历史价格查询(如"2020年1月2日汉堡多少钱")维护当前有效价格清单…...
uniapp自身bug | uniapp+vue3打包后 index.html无法直接运行
前提: 已经修改了基础路径 打开打包文件,双击运行index.html报错,无法访问页面 uniappvue2项目是可以正常运行的 vue3修改publicPath: ./后,也是可以正常访问打包文件中的index.html 点进控制台提供的链接:https:/…...
数据分析面试--京东
1.考察日期函数的应用 select Order_date, count(distinct user_id) as uv from (select user_id, Order_date, row_number() over(partition by user_id order by Order_date) as new_tagfrom ord where date_diff(current_date(), Order_date)<30 ) t where new_tag1 gro…...
Centos7搭建Zabbix4.x监控HCL模拟网络设备:zabbix-server搭建及监控基础04
兰生幽谷,不为莫服而不芳; 君子行义,不为莫知而止休。 4.OID查看工具Getif安装及使用 找度娘下载Getif,该软件比较老,可以用来查看OID编码,我的宿主机是Win11,无法安装。所以只有到虚拟机win12去安装&am…...
爬虫:scrapy面试题大全(60个scrapy经典面试题和详解)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. 什么是Scrapy?2. Scrapy 框架的组件及其作用?3. Scrapy的工作流程是什么?(运行机制)4. 如何创建一个Scrapy项目?5. 如何定义一个Spider?6. 如何在Scrapy中提取数据?7. Scrapy中的Item是什么?8. Scrapy中的P…...
Ubuntu Debian 系统下挂载 Samba 共享目录的完整指南
文章目录 Ubuntu & Debian 系统下挂载 Samba 共享目录的完整指南前提条件挂载 Samba 共享临时挂载避免明文密码永久挂载 常见选项卸载故障排查 Ubuntu & Debian 系统下挂载 Samba 共享目录的完整指南 想把NAS中的内容通过Samba挂载到 OrangePi 5B,但是 Ora…...
蓝桥杯2023年第十四届省赛真题-异或和之差
题目来自DOTCPP: 思路: 什么是异或和? ①题目要求我们选择两个不相交的子段,我们可以枚举一个分界线i,子段1在 i 的左边, 子段2在 i 的右边,分别找到子段1和子段2的最大值、最小值。 ②怎么确…...
考研课程安排(自用)
文章目录 408数据结构(王道)计算机组成原理(王道)操作系统(王道)计算机网络(湖科大版) 数学一高等数学(微积分)线性代数和概率论 408 数据结构(王…...
linux命令行工具进阶
文章目录 前言ssh免密登录,免密码登录,公私钥查看与修改IP地址临时修改永久修改 mount临时切换根文件系统永久切换根文件系统loop文件partedinitramfsuboot command line总结 前言 本文记录了一些不经常用到,但在某个时刻需要用到的一些指令…...
Linux系统管理实战:文件权限配置、用户组协作与日志处理全解析
1、创建/www目录,在/www目录下新建name和https目录,在name和https目录下分别创建一个index.html文件,name下面的index.html文件中包含当前主机的主机名,https目录下的index.html文件中包含当前主机的ip地址。 (1&…...
[自动化] 【八爪鱼】使用八爪鱼实现CSDN文章自动阅读脚本
在CSDN上,文章的阅读量往往是衡量内容影响力的一个重要指标。为了测试自动化手段能否提高阅读数,我尝试使用网页自动化工具来模拟人工阅读某个ID的文章。 1. 网页自动化的常见方案 谈到网页自动化,Selenium 是一个最常见的选择。它可以通过…...
Go语言分布式锁实战:dlock助力构建高并发稳定系统
在构建分布式系统时,一个常见且棘手的问题便是资源竞争和数据一致性问题。分布式锁作为一种常用的解决方案,在多个进程或节点之间协调访问共享资源时显得尤为重要。今天,我们将介绍一款分布式锁库——dlock,并通过详细的使用示例带…...
如何提高G口服务器的安全性?
G口服务器可以支持千兆网络传输速度,能够为企业提供更快的数据处理能力和传输能力,随着网络流量的不断增长以及复杂计算任务的普及,企业对于网络带宽的要求也在相应提高,而G口服务器则可以降低网络的延迟度,大幅度提高…...
为没有CMake配置的第三方库添加CMake配置
1 编写CMakeLists.txt cmake_minimum_required(VERSION 3.15) #如果你第三方库和自己的库没有xxxConfig.cmake #请修改项目名称和命名空间(一般不需要) project("pthreads" LANGUAGES C CXX) set(KC_NAMESPACE "") #set(K…...
Linux驱动编程 - seq_open、single_open使用方法
目录 前言: 一、seq_xxx 1、seq_xxx 函数介绍 1.1 seq_open 1.2 seq_read 1.3 seq_lseek 1.4 seq_release 1.5 格式化输出函数 2、seq_open 实例 二、single_xxx 函数 1、single_xxx 函数介绍 1.1 single_open 1.2 single_start 1.3 single_next 1.4 single_stop…...
N列股票收盘价为起点的马科维茨(Markowitz)均值—方差理论
1. 数据准备与收益率计算 输入数据: 假设你有一个矩阵,每一列代表一只股票的历史收盘价序列。每一行对应一个时间点的收盘价。 计算收益率: 马科维茨理论要求使用资产的收益率而非价格。常用的收益率计算方法有对数收益率或简单收益率。 2.…...
【嵌入式学习2】函数
目录 ## 函数 ## 函数分类 ## 函数定义 1、无参数无返回值 2、有参数无返回值 3、有参数有返回值 ## 函数声明 ## 局部变量和全局变量 ## 多文件编程 如何避免把同一个头文件 include 多次,或者头文件嵌套包含? 命令行编译文件 头文件包含的…...
模式搜索+扩散模型:FlowMo重构图像Token化的技术革命
图像Token化作为现代生成式AI系统的核心技术,长期面临对抗性训练不稳定、潜在空间冗余等挑战。斯坦福大学李飞飞与吴佳俊团队提出的FlowMo(Flow towards Modes)创新性地融合模式搜索与扩散模型,在多个关键维度突破传统方法局限&am…...
mac brew 安装的php@7.4 打开redis扩展
1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…...
OSPF多区域通信
作业要求: 1、多区域0SPF area 0、area10、are20 2、AR5、AR6作为stub区,使用环回接口与Pc1进行通信 第一步:为各端口配置IP地址 AR1: <Huawei>sys [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 5.5.5.1 24 [Huawei-GigabitEther…...
C++模板编程与元编程面试题及参考答案(精选100道题)
目录 解释 C++ 模板的实例化过程,显式实例化与隐式实例化的区别 模板函数在不同翻译单元中的 ODR(单一定义规则)问题 模板参数推导失败的可能场景及解决方法 模板函数中 auto 返回类型的推导规则 如何限制模板函数仅接受特定类型的参数?(非 C++20 概念场景) 函数模板…...
括弧匹配检验(信息学奥赛一本通-1354)
【题目描述】 假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([ ]())或[([ ][ ࿳…...
三、重学C++—C语言内存管理
上一章节: 二、重学C—C语言核心-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146191640?spm1001.2014.3001.5502 本章节代码: cPart2 CuiQingCheng/cppstudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/cppstudy/tree/…...
算法题(105):小猫爬山
审题: 本题需要我们找出将n个小猫放在有限重的缆车上运下山所需的最小缆车数 时间复杂度分析:本题的数据量小于等于18,所以我们在做好剪枝的前提下可以使用深度优先搜索解题 思路: 方法一:dfs 搜索策略:将小…...
C语言-适配器模式详解与实践
文章目录 C语言适配器模式详解与实践1. 什么是适配器模式?2. 为什么需要适配器模式?3. 实际应用场景4. 代码实现4.1 UML 关系图4.2 头文件 (sensor_adapter.h)4.3 实现文件 (sensor_adapter.c)4.4 使用示例 (main.c) 5. 代码分析5.1 关键设计点5.2 实现特…...
线程的pthread_create、pthread_join、pthread_exit、pthread_detach函数
线程的创建(pthread_create) pthread_t tid;//本质是unsigned long类型,打印时得到的是该线程的虚拟地址int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg ); pthread_t *thre…...
测试专项4:AI算法测试在测试行业中,该如何定位自己自述
这岗位到底干啥的? 打个比方: 你就像AI模型的“质检员产品经理风险顾问”三合一。 质检员: 别人造了个AI模型(比如人脸识别系统),你不能光看它实验室成绩好,得把它丢到现实里折腾:…...
