Android服务模块作用,Android 9.0 AutotoMotive模块之CarService
Android 9.0 AutotoMotive模块之CarService
Android 9.0 AutotoMotive模块之CarService
上一篇对Automotive模块的Vhal作了总结,本篇文章主要从上层CarService的实现来构析Automotive所提供的功能。 这里主要从以下几点进行源码解读。
CarService功能解析权限定义与检查
CarService与Vhal通信
模拟器的创建与使用
附录:权限定义表
CarService是一个拥有最高优先级的应用服务,它的的源码在 packages/services/Car 目录下面,这个目录下存在许多的工程,这里我们只关心service这个文件夹,service下包含了CarService的服务实现。
权限定义与检查
CarService针对一些特殊的属性读写,定义了对属性值的访问权限,定义方式在service目录中的AndroidManifest.xml中,具体权限定义的字段以及其意义可以参考本文末尾附录表,CarService在PropertyHalServiceIds.java这个类中将属性字段与权限对应起来,属性的权限组,通过SparseArray容器保存,key为属性字段,value为一个Pair类型的变量,first值为读所需权限,second值为写所需权限,并提供了权限获取接口,定义的伪代码如下:
// Index (key is propertyId, and the value is readPermission, writePermission
private final SparseArray> mProps;
mProps = new SparseArray<>();
// Add propertyId and read/write permissions
// Cabin Properties
mProps.put(VehicleProperty.DOOR_POS, new Pair<>(
Car.PERMISSION_CONTROL_CAR_DOORS,
Car.PERMISSION_CONTROL_CAR_DOORS));
mProps.put(VehicleProperty.DOOR_MOVE, new Pair<>(
Car.PERMISSION_CONTROL_CAR_DOORS,
Car.PERMISSION_CONTROL_CAR_DOORS));
...
...
一些比较危险的属性,其属性值读写需要调用方应用具有指定的权限才可以操作。那在服务中到底是如何check权限的呢? 让我们来一起先捡个软柿子捏捏。看一下空调温度模块,设置驾驶位空调温度的流程。
从流程图可以看到,check Permission权限检查的操作在CarPropertyService(CPS)中进行,只有在权限通过后,才能将输入下发到VHAL中。 CPS中中通过调用ICarImpl中的静态方法来确定调用方有权限执行此功能。
@Override
public void setProperty(CarPropertyValue prop) {
int propId = prop.getPropertyId();
if (mConfigs.get(propId) == null) {
// Do not attempt to register an invalid propId
Log.e(TAG, "setProperty: propId is not in config list:0x" + toHexString(propId));
return;
}
//从根据属性ID从权限组中获取写入权限,然后再调用安卓原生判断权限的方式进行判断,如果没有权限,则报RuntimeException异常,中断调用方的应用进程
ICarImpl.assertPermission(mContext, mHal.getWritePermission(propId));
//如果有权限,则将属性下发
mHal.setProperty(prop);
}
CarService与Vhal通信
上面一节介绍了CarService通信的权限检查模块,之所以要单独提取出来讲一下流程,是因为本人在调试过程中被权限这块绕了一点时间. 然后接着分析上面提到的vhal模块与Service之间的通信,之前的文章也讲过vhal使用了hidl接口,最终会编译出一个jar包,具体查阅此篇Android 9.0 AutotoMotive模块之Vehicle, 生成的 android.hardware.automotive.vehicle-V2.0-java.jar被service编译的时候依赖了,其中自动生成的IVehicle接口中就实现了Service与Vhal进行binder通信的逻辑,所以这部分我们不要太关心,只需要知道拿到IVehicle接口实例就能通信就OK了, 那怎么拿到该实例呢,IVehicle中有一个这样的方法
android.hardware.automotive.vehicle.V2_0.IVehicle.getService()
这是一个静态方法,CarService也正是通过该方法拿到IVehicle的实例
@Nullable
private static IVehicle getVehicle() {
try {
return android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
} catch (RemoteException e) {
Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle service", e);
} catch (NoSuchElementException e) {
Log.e(CarLog.TAG_SERVICE, "IVehicle service not registered yet");
}
return null;
}
具体的流程如下
public void onCreate() {
Log.i(CarLog.TAG_SERVICE, "Service onCreate");
mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);
//获取IVehicle对象
mVehicle = getVehicle();
//VHal服务未运行(远端Binder没有找到对应的服务),直接报错
if (mVehicle == null) {
throw new IllegalStateException("Vehicle HAL service is not available.");
}
try {
//获取vehicle接口名称
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);
//初始化ICarImpl对象,CarService中的功能实现与Manager的管理定义在该类中。
mICarImpl = new ICarImpl(this,
mVehicle,
SystemInterface.Builder.defaultSystemInterface(this).build(),
mCanBusErrorNotifier,
mVehicleInterfaceName);
mICarImpl.init();
//通知bootstat模块car service启动成功
SystemProperties.set("boot.car_service_created", "1");
//注册服务死亡通知
linkToDeath(mVehicle, mVehicleDeathRecipient);
//将该服务作为远程服务注册到ServiceManager
ServiceManager.addService("car_service", mICarImpl);
super.onCreate();
}
ICarImpl这里就不深入分析了,简单介绍一下,主要是将车上的各个模块拆解成一个个子模块去管理,比如空调, 车身信息这类属性模块对应的管理模块就是CarPropertyService。 音频管理,则是CarAudioService等等。我们主要介绍一下服务数据是如何下发的,也就是CarPropertyService中setProperty的后续处理逻辑。
还是用权限的那个例子,空调温度设置到CPS中的setProperty之后,会调用PropertyHalService中的setProperty方法,源码如下:
public void setProperty(CarPropertyValue prop) {
//查找该属性是否未有效的属性
int halPropId = managerToHalPropId(prop.getPropertyId());
Log.d(TAG, "PropertyHalService setProperty halPropId = " + halPropId);
if (halPropId == NOT_SUPPORTED_PROPERTY) {
throw new IllegalArgumentException("Invalid property Id : 0x"
+ toHexString(prop.getPropertyId()));
}
//将CarPropertyValue转换为VehiclePropValue对象,注意这个VehiclePropValue是hidl自动生成的,包含在jar包中,下发该对象后,vhal模块能够直接取值。
VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
try {
mVehicleHal.set(halProp);
} catch (PropertyTimeoutException e) {
Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
throw new RuntimeException(e);
}
}
最后一路set到IVehicle中,将数据发送给vhal
public void setValue(VehiclePropValue propValue) throws PropertyTimeoutException {
int status = invokeRetriable(() -> {
try {
//此处将VehiclePropValue下发到VHAL模块
return mVehicle.set(propValue);
} catch (RemoteException e) {
Log.e(CarLog.TAG_HAL, "Failed to set value", e);
return StatusCode.TRY_AGAIN;
}
}, WAIT_CAP_FOR_RETRIABLE_RESULT_MS, SLEEP_BETWEEN_RETRIABLE_INVOKES_MS);
//vhal上报,该参数无效
if (StatusCode.INVALID_ARG == status) {
throw new IllegalArgumentException(
String.format("Failed to set value for: 0x%x, areaId: 0x%x",
propValue.prop, propValue.areaId));
}
//错误码:设置失败,请重试
if (StatusCode.TRY_AGAIN == status) {
throw new PropertyTimeoutException(propValue.prop);
}
if (StatusCode.OK != status) {
throw new IllegalStateException(
String.format("Failed to set property: 0x%x, areaId: 0x%x, "
+ "code: %d", propValue.prop, propValue.areaId, status));
}
}
至此,service的set结束,read流程与set差不多,此处不再赘述。
模拟器的创建与使用
Android Studio中使用模拟器,流程如下,打开AVD manager -> create Virture Device -> AutoMotive -> x86镜像,下载镜像完成后,打开即可
模拟器启动后,点击右边工具栏的三个点
在如下界面中就可以模拟车身数据进行通信调试了。
附录:权限定义表
权限定义
权限说明
权限等级
android.car.permission.ADJUST_CAR_CABIN
操作轿厢信息的权限
系统权限
android.car.permission.CAR_ENERGY
访问车辆引擎类型的权限
危险权限
android.car.permission.CAR_IDENTIFICATION
汽车VIN码的访问权限
系统权限
android.car.permission.CONTROL_CAR_CLIMATE
操作空调的权限
系统权限
android.car.permission.CONTROL_CAR_DOORS
操作车门信息的权限
系统权限
android.car.permission.CONTROL_CAR_WINDOWS
操作车窗信息的权限
系统权限
android.car.permission.CONTROL_CAR_MIRRORS
操作车辆后视镜信息的权限
系统权限
android.car.permission.CONTROL_CAR_SEATS
操作车辆座椅信息的权限
系统权限
android.car.permission.CAR_MILEAGE
行驶里程访问权限
系统权限
android.car.permission.CAR_TIRES
轮胎相关属性的读写
系统权限
android.car.permission.CAR_SPEED
车速属性读取
危险权限
android.car.permission.CAR_ENERGY_PORTS
油箱口或者充电口信息的访问权限
普通权限
android.car.permission.CAR_ENGINE_DETAILED
访问发动机详细信息的权限
系统权限
android.car.permission.CAR_DYNAMICS_STATE
动态值访问权限
系统权限
android.car.permission.CAR_VENDOR_EXTENSION
访问特殊的通信信道
系统权限
android.car.permission.CAR_PROJECTION
允许访问car projection相关api的权限
系统权限
android.car.permission.CAR_MOCK_VEHICLE_HAL
允许模拟车身数据
系统权限
android.car.permission.CAR_INFO
允许调用CarInfoManager API的权限
普通权限
android.car.permission.CAR_EXTERIOR_ENVIRONMENT
读取车外温度的权限
普通权限
android.car.permission.CAR_EXTERIOR_LIGHTS"
读取外车灯信息的权限
系统权限
android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"
控制外车灯信息的权限
系统权限
android.car.permission.CAR_POWERTRAIN
读取动力传输系统信息的权限
普通权限
android.car.permission.CAR_NAVIGATION_MANAGER
使用CarNavigationStatusManager API的权限
系统权限
android.car.permission.CAR_DIAGNOSTICS
读取车辆诊断内容(包括客制化字段)权限
系统权限
android.car.permission.CLEAR_CAR_DIAGNOSTICS
清理车辆诊断信息的权限
系统权限
android.car.permission.VMS_PUBLISHER
访问VMS publisher API的权限
系统权限
android.car.permission.VMS_SUBSCRIBER
访问VMS subscriber API的权限
系统权限
android.car.permission.CAR_DRIVING_STATE
访问CarDrivingStateService去获取驾驶状态的权限
系统权限
android.car.permission.CAR_DRIVING_STATE
访问CarDrivingStateService去获取驾驶状态的权限
系统权限
android.car.permission.CONTROL_APP_BLOCKING
未知权限
系统权限
android.car.permission.CAR_CONTROL_AUDIO_VOLUME
控制音量
系统权限
android.car.permission.CAR_CONTROL_AUDIO_SETTINGS
音量设置
系统权限
android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
系统签名
android.car.permission.BIND_CAR_INPUT_SERVICE
系统签名
android.car.permission.CAR_DISPLAY_IN_CLUSTER
应用程序必须有此签名才能在仪表盘上显示
系统权限
android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
应用程序调用CarInstrumentClusterManager在仪表盘中启动Activity时需要此权限
系统权限
android.car.permission.STORAGE_MONITORING
系统权限
Android 9.0 AutotoMotive模块之CarService相关教程
Android服务模块作用,Android 9.0 AutotoMotive模块之CarService相关推荐
- android服务无法启动,Android服务无法启动(Android service would't start)
Android服务无法启动(Android service would't start) 我正在尝试在Android中实现简单的服务,但我无法统计基本服务. 这是我的主要课程: import java ...
- Android适配器以及作用,Android RecyclerView 通用适配器的实现
分析 我们需要在RecyclerViewAdapter内部维持一个数据集合的引用 需要实现Item的点击事件,包括短按和长按,并需要向外部提供设置监听器的方法 这个适配器必须通用,所以应该是泛型的,并 ...
- android布局的作用,Android UI布局经验总结
如何在Android中动态设置颜色透明?10%20%到100% Android布局分析工具HierarchyView Android使用include/merge/ViewStub优化布局 List的 ...
- android 服务自动结束,Android服务自动停止
我正在制作一个带有闹钟功能的应用程序.我正在使用这种服务,不断检查设备的当前时间与我的数据库中的时间.Android服务自动停止 我的问题是,如果应用程序从后台删除或设备是rebooted,此serv ...
- android 混淆规则作用,Android混淆规则
简介 Java代码是非常容易反编译的.为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理. ProGuard是一个混淆代码的开源项目.它的主要作用就是混淆,当然它还能对字节码 ...
- android服务下载apk,Android 一个简单的版本更新下载apk小示例
一.简介: 1.运用 okhttp + notification 通知栏带进度的下载apk,下载完毕后并自动安装,如果用户取消可在通知栏点击安装,点击一次通知栏移除,同时支持自动静默下载(后台默默下载 ...
- android服务常驻内存,android service常驻内存的一点思考
我们总是不想自己的Android service被系统清理,以前时候大家最常用的办法就是在JNI里面fork出子进程,然后监视 service进程状态,被系统杀死了就重启它. 我分别在android4 ...
- android scaletype没作用,Android源码系列之深入理解ImageView的ScaleType属性
做Android开发的童靴们肯定对系统自带的控件使用的都非常熟悉,比如Button.TextView.ImageView等.如果你问我具体使用,我会给说:拿ImageView来说吧,首先创建一个新的项 ...
- android minheight的作用,Android 自定义 View 最少必要知识
1. 什么是自定义 View? 1.1 定义 在 Android 系统中,界面中所有能看到的元素都是 View.默认情况下,Android 系统为开发者提供了很多 View,比如用于展示文本信息的 T ...
最新文章
- 转android项目开发 工作日志 2011.10.8--onConfigurationChanged屏幕改变事件
- Android 利用方向传感器实现 指南针
- gzencode php demo,8个必备的PHP功能实例代码
- python升级版本命令-CentOS7 下升级Python版本
- C++虚函数的实现方式
- centos7 下进行数据库自动备份
- 【David Silver强化学习公开课】-8:Integrating Learning and Planning
- atm机java+gui+oracle编程代码_java应用在哪里?
- Interlocked..::.Add 方法
- 手把手教你 3 个 Linux 中快速检测端口的小技巧
- Linux Shell编程笔记一:相关命令
- 我的账号 小米云服务器地址,小米云服务登录
- 天池大数据竞赛 Spaceack带你利用Pandas,趋势图与桑基图分析美国选民候选人喜好度
- c语言汉字编码转换,请问如何用C语言实现汉字和Unicode编码的转换 求程序
- C语言男性标准体重,2019男人标准体重表!
- 记录win10无法通过IE浏览器设置受信任的站点的几种方法
- 计算机上机模拟试题答案,[计算机类试卷]国家二级VB机试(上机操作)模拟试卷420及答案与解析.doc...
- android设置UI界面背景,Android ROM定制——界面美化基础(framework-res、SystemUI修改)...
- nacos注册成功但是服务管理界面没有内容
- oracle中表数据更新提交后自动被还原的原因查找
热门文章
- 2021-11-11阿里巴巴双十一高峰如何逆袭,高并发秘诀
- 2021年危险化学品经营单位安全管理人员考试题库及危险化学品经营单位安全管理人员操作证考试
- 如何修改eclipse的主题颜色、背景颜色、编辑框颜色
- 关于maya中的sets集
- 为什么显示芒果tv服务器异常怎么办,芒果tv打不开怎么办 芒果tv打不开解决方法...
- OPPO软件商店APP侵权投诉流程
- Android过时方法怎么处理,Android过时方法总结
- windows mobile linux,智能手机器操作系统 Windows Mobile和Symbian及LinLinux详解
- 树莓派4b部署LNMP+Tor,搭建在Dark web上的网站
- 海湾9000报初始未定义故障_海湾9000操作说明书.doc