【Android】VehiclePropertyAccess引起CarService崩溃

news2025/7/14 7:35:56

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
 @Override
 public 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 propId
		Slog.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 listener
	Client client = mClientMap.get(listenerBinder);
	if (client == null) {
		client = new Client(listener);
	}
	client.addProperty(propId, rate);
	// Insert the client into the propId --> clients map
	List<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 necessary
	if (!mListenerIsSet) {
		mHal.setListener(this);
	}
	// Set the new rate
	if (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;
    }
}

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

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

相关文章

深度剖析:复制带随机指针的链表算法实现

在链表相关的算法中&#xff0c;复制一个带有随机指针的链表是一个经典且具有一定难度的问题。本文将深入分析一段用C语言实现的复制带随机指针链表的代码&#xff0c;通过模块化的方式详细解释每段代码的作用&#xff0c;帮助读者更好地理解这一复杂算法。 作者主页&#xf…

Java 大视界 -- Java 大数据在智慧文旅旅游目的地营销与品牌传播中的应用(150)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

SQLMesh SCD-2 时间维度实战:餐饮菜单价格演化追踪

场景背景&#xff1a;动态菜单价格管理 考虑某连锁餐厅的菜单管理系统&#xff0c;需要记录食品价格的历史变更轨迹。业务需求包括&#xff1a; 记录每次价格调整的时间点支持历史价格查询&#xff08;如"2020年1月2日汉堡多少钱"&#xff09;维护当前有效价格清单…

uniapp自身bug | uniapp+vue3打包后 index.html无法直接运行

前提&#xff1a; 已经修改了基础路径 打开打包文件&#xff0c;双击运行index.html报错&#xff0c;无法访问页面 uniappvue2项目是可以正常运行的 vue3修改publicPath: ./后&#xff0c;也是可以正常访问打包文件中的index.html 点进控制台提供的链接&#xff1a;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

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 4.OID查看工具Getif安装及使用 找度娘下载Getif&#xff0c;该软件比较老&#xff0c;可以用来查看OID编码&#xff0c;我的宿主机是Win11,无法安装。所以只有到虚拟机win12去安装&am…

蓝桥杯2023年第十四届省赛真题-异或和之差

题目来自DOTCPP&#xff1a; 思路&#xff1a; 什么是异或和&#xff1f; ①题目要求我们选择两个不相交的子段&#xff0c;我们可以枚举一个分界线i&#xff0c;子段1在 i 的左边&#xff0c; 子段2在 i 的右边&#xff0c;分别找到子段1和子段2的最大值、最小值。 ②怎么确…

Linux系统管理实战:文件权限配置、用户组协作与日志处理全解析

1、创建/www目录&#xff0c;在/www目录下新建name和https目录&#xff0c;在name和https目录下分别创建一个index.html文件&#xff0c;name下面的index.html文件中包含当前主机的主机名&#xff0c;https目录下的index.html文件中包含当前主机的ip地址。 &#xff08;1&…

[自动化] 【八爪鱼】使用八爪鱼实现CSDN文章自动阅读脚本

在CSDN上&#xff0c;文章的阅读量往往是衡量内容影响力的一个重要指标。为了测试自动化手段能否提高阅读数&#xff0c;我尝试使用网页自动化工具来模拟人工阅读某个ID的文章。 1. 网页自动化的常见方案 谈到网页自动化&#xff0c;Selenium 是一个最常见的选择。它可以通过…

N列股票收盘价为起点的马科维茨(Markowitz)均值—方差理论

1. 数据准备与收益率计算 输入数据&#xff1a; 假设你有一个矩阵&#xff0c;每一列代表一只股票的历史收盘价序列。每一行对应一个时间点的收盘价。 计算收益率&#xff1a; 马科维茨理论要求使用资产的收益率而非价格。常用的收益率计算方法有对数收益率或简单收益率。 2.…

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区&#xff0c;使用环回接口与Pc1进行通信 第一步&#xff1a;为各端口配置IP地址 AR1: <Huawei>sys [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 5.5.5.1 24 [Huawei-GigabitEther…

三、重学C++—C语言内存管理

上一章节&#xff1a; 二、重学C—C语言核心-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146191640?spm1001.2014.3001.5502 本章节代码&#xff1a; cPart2 CuiQingCheng/cppstudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/cppstudy/tree/…

算法题(105):小猫爬山

审题&#xff1a; 本题需要我们找出将n个小猫放在有限重的缆车上运下山所需的最小缆车数 时间复杂度分析&#xff1a;本题的数据量小于等于18&#xff0c;所以我们在做好剪枝的前提下可以使用深度优先搜索解题 思路&#xff1a; 方法一&#xff1a;dfs 搜索策略&#xff1a;将小…

线程的pthread_create、pthread_join、pthread_exit、pthread_detach函数

线程的创建&#xff08;pthread_create&#xff09; pthread_t tid;//本质是unsigned long类型&#xff0c;打印时得到的是该线程的虚拟地址int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg ); pthread_t *thre…

测试专项4:AI算法测试在测试行业中,该如何定位自己自述

这岗位到底干啥的&#xff1f; 打个比方&#xff1a; 你就像AI模型的“质检员产品经理风险顾问”三合一。 质检员&#xff1a; 别人造了个AI模型&#xff08;比如人脸识别系统&#xff09;&#xff0c;你不能光看它实验室成绩好&#xff0c;得把它丢到现实里折腾&#xff1a;…

【C语言系列】数据在内存中存储

数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端&#xff1f;2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…

【中文翻译】第12章-The Algorithmic Foundations of Differential Privacy

由于GitHub项目仅翻译到前5章&#xff0c;我们从第6章开始通过大语言模型翻译&#xff0c;并导出markdown格式。 大模型难免存在错漏&#xff0c;请读者指正。 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 12 其他模型 到目前为止&…

图解模糊推理过程(超详细步骤)

我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数&#xff0c;下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数&#xff08;Π-shaped Membership Function&#xff09;的详细介绍及python示例”都有详细讲解&#xff1a;https://lzm07.b…

datawhale组队学习-大语言模型-task5:主流模型架构及新型架构

目录 5.3 主流架构 5.3.1 编码器-解码器架构 5.3.2 因果解码器架构 5.3.3 前缀解码器架构 5.4 长上下文模型 5.4.1 扩展位置编码 5.4.2 调整上下文窗口 5.4.3 长文本数据 5.5 新型模型架构 5.5.1 参数化状态空间模型 5.5.2 状态空间模型变种 5.3 主流架构 在预训…