我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android汽车服务篇(三) CarPropertyService下篇

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android汽车服务篇(三) CarPropertyService下篇

一. 简介

        上篇文章介绍了Android汽车服务篇(二) CarPropertyService上篇, 我们继续看一看看CarPropertyService, 这个服务也是很重要的, 绝大部分与车辆硬件功能相关联的属性,如空调, 车舱功能, 车辆传感器等都是通过CarPropertyService来读取或者设置的.

         CarPropertyManager 是CarPropertyService在客户端的代理, 通过CarPropertyManager提供的API,可以设置和获取车辆各个属性的状态.

二. 座舱服务 CarCabinManager

        CarCabinManager提供的是座舱内相关功能的API, 包括座椅,安全带,车窗等. 它在用法上和CarHvacManager类似, 同样的CarCabinManager也是系统级别的,只有拥有系统权限的应用才可以使用.

        CarCabinManager的属性

CarCabinManager中的属性都和座舱内的硬件设备相关,如车门,后视镜,座椅等. 与这些设备相关的属性又根据其特点进行了细分,对于可以移动,调节的设备而言,会有不同方向之分.

下表中的列出了CarCabinManager中所包含的属性, 以及属性所对应的主要设备和功能

属性类型功能
ID_DOOR_POSint车门
ID_DOOR_MOVEint
ID_DOOR_LOCKbool
ID_MIRROR_Z_POSint后视镜
ID_MIRROR_Z_MOVEint
ID_MIRROR_Y_POSint
ID_MIRROR_Y_MOVEint
ID_MIRROR_LOCK

bool

ID_MIRROR_FOLDbool
ID_SEAT_MEMORY_SELECT

int

座椅记忆
ID_SEAT_MEMORY_SET

int

ID_SEAT_BELT_BUCKLED

bool

安全带
ID_SEAT_BELT_HEIGHT_POSint
ID_SEAT_BELT_HEIGHT_MOVEint
ID_SEAT_FORE_AFT_POSint座椅前后位置
ID_SEAT_FORE_AFT_MOVEint
ID_SEAT_BACKREST_ANGLE_1_POSint座椅靠背
ID_SEAT_BACKREST_ANGLE_1_MOVEint
ID_SEAT_BACKREST_ANGLE_2_POSint
ID_SEAT_BACKREST_ANGLE_2_MOVEint
ID_SEAT_HEIGHT_POSint座椅高度
ID_SEAT_HEIGHT_MOVEint
ID_SEAT_DEPTH_POSint座椅深度
ID_SEAT_DEPTH_MOVEint

                                                                               表一

属性类型功能
ID_SEAT_TILT_POSint座椅倾角
ID_SEAT_TILT_MOVEint
ID_SEAT_LUMBAR_FORE_AFT_POSint腰托
ID_SEAT_LUMBAR_FORE_AFT_MOVEint
ID_SEAT_LUMBAR_SIDE_SUPPORT_POSint
ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVEint
ID_SEAT_HEADREST_HEIGHT_POSint头枕
ID_SEAT_HEADREST_HEIGHT_MOVEint
ID_SEAT_HEADREST_ANGLE_POSint
ID_SEAT_HEADREST_ANGLE_MOVEint
ID_SEAT_HEADREST_FORE_AFT_POSint
ID_SEAT_HEADREST_FORE_AFT_MOVEint
ID_WINDOW_POSint车窗
 
ID_WINDOW_MOVEint
ID_WINDOW_LOCKbool

                                                                                 表二

        可以看到CarCabinManager中最主要的是和座椅相关的属性,同时还有车窗,后视镜相关的功能. 大部分功能同时会有位置(position)和移动(move)两个属性.其中位置属性主要是设置具体的位置值而移动则是该设备的移动方向.

        

        CarCabinManager丰富了车内设施的控制功能,通过它提供的API,开发者可以为驾驶者提供很多个性化的功能,如座椅调节, 车窗调节

        在用法上, CarCabinManager和CarHvacManager非常相似,同样可以获取或设置属性的值, 并对属性变化进行监听. API也没有什么两样. 

        相关的权限主要有以下三个:

      

三. 制造商扩展服务 CarVendorExtensionManager

        市场上的汽车品牌种类繁多,每款车型的功能又不相同.汽车制造商们也在不断推陈出新,推出一些属于品牌特有的功能来吸引消费者的目光. 要想将说有的功能都定义为标准的属性肯定非常困难.

        对此 AAOS的做法是, 除了定义目前市场上绝大多数车型都适用的属性外,同样允许制造商根据自己所拥有的其他功能进行扩展, 这就是本节CarVendorExtensionManager的主要作用. 它让制造商可以扩展VehicleHAL中已经定义的属性,加入额外的功能.

 3.1 CarVendorExtensionManager用法

通过以下方式获取CarVendorExtensionManager对象的实例

        Car car = Car.createCar(this);        CarVendorExtensionManager vendorManager = (CarVendorExtensionManager)car.getCarManager(Car.VENDOR_EXTENSION_SERVICE);

要使用CarVendorExtensionManager需要申请如下权限:

该权限同时是系统级别的,普通的第三方应用无法使用.

3.2 获取和设置属性

        在属性的设置或获取上, CarVendorExtensionManager和CarHvacManager. CarCabinManager的使用方法区别并不大, 但是由于是扩展的属性, 属性的类型是不确定的,所以在调用setProperty和getProperty时需要传入属性的类型. 

        举个例子, 自定义了一个 CUSTOM_FLOAT_AREA 属性,且值为float型,如果该区域是多区域的,还需要传入区域值, 获取和设置该属性的方法如下:

        //设置属性值        vendorManager.setProperty(Float.class, CUSTOM_FLOAT_AREA, VehicleAreaSeat.SEAT_ROW_1_CENTER, value);        //获取实际值        float actualVaule = vendorManager.getProperty(Float.class, CUSTOM_FLOAT_AREA, VehicleAreaSeat.SEAT_ROW_1_CENTER);

我们可以看看packages/services/Car/car-lib/class="lazy" data-src/android/car/hardware/CarVendorExtensionManager.java 的 这两个方法

 public  void setProperty(Class propertyClass, int propId, int area, E value) {        mPropertyManager.setProperty(propertyClass, propId, area, value);} public  E getProperty(Class propertyClass, int propId, int area) {        return mPropertyManager.getProperty(propertyClass, propId, area).getValue();    }

3.3 监听属性变化

CarVendorExtensionManager同样可以通过注册回调接口的方式来监听属性值发生的变化. 方式十分简单.实现CarVendorExtensionCallback就可以了.方式如下:

         //创建一个监听器对象        CarVendorExtensionListener listener = new CarVendorExtensionListener();        //注册监听器        vendorManager.registerCallback(listener);        //移除监听器        vendorManager.unregisterCallback(listener);class CarVendorExtensionListener implements CarVendorExtensionManager.CarVendorExtensionCallback{    @Override    public void onChangeEvent(CarPropertyValue carPropertyValue) {    }    @Override    public void onErrorEvent(int i, int i1) {    }}

需要注意的是, 尽管注册的是CarVendorExtensionCallback,但是该回调方法不仅会收到扩展属性相关的变化事件,对于其他属性的变化事件(如空调,传感器)也有可能被传递过里. 因此在onChangeEvent方法中需要做好相关的判断,确保该次事件是所需要的.

有了CarVendorExtensionManager, CarService一下子有了拥有扩展属性的能力,让原来看上去有限的功能,变得可以丰富无比,当然实际上还是得依赖制造商的实现.  

对于需要使用自定义属性的应用, 只需要知道确切的ID和类型.

四.  车辆属性API  CarPropertyManager

本节介绍最重要的一个Manager :  CarPropertyManager. 在Android10中,它变成了车辆属性的主要API, 并允许任何运行在 AAOS上的应用进行调用. 

4.1 CarPropertyManager用法

        熟悉了上面介绍的5个服务的相关用法后,在CarPropertyManager的使用上, 对相关的用法有所了解, 接下来这里再做一点补充.

        关于属性的获取, 在CarPropertyManager.java中除了有getProperty方法之外, 还有getBooleanProperty. getIntProperty这样明确属性类型的获取方法. 这些方法的最后实现还是对getProperty方法的封装.

        public int getIntProperty(int prop, int area) {        //最后还是调用的getProperty方法        CarPropertyValue carProp = getProperty(Integer.class, prop, area);        return carProp != null ? carProp.getValue() : 0;    }public  CarPropertyValue getProperty(@NonNull Class clazz, int propId, int areaId) {        if (DBG) {            Log.d(TAG, "getProperty, propId: 0x" + toHexString(propId)                    + ", areaId: 0x" + toHexString(areaId) + ", class: " + clazz);        }        try {            CarPropertyValue propVal = mService.getProperty(propId, areaId);            if (propVal != null && propVal.getValue() != null) {                Class actualClass = propVal.getValue().getClass();                if (actualClass != clazz) {                    throw new IllegalArgumentException("Invalid property type. " + "Expected: "+ clazz + ", but was: " + actualClass);                }            }            return propVal;        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }

注意事项:  官方推荐开发者使用getProperty来获取相应的属性值, 因为getProperty方法返回的是CarPropertyValue对象,其不仅仅包含属性值,还包括属性的状态,而getIntProperty等方法在属性不可用的情况下,返回的是默认值,所以会造成有些时候读取的数据不准确.

下面已NIGHT_MODE(昼夜模式)属性为例子, 说明使用getProperty的好处.

private void testCarPropertyManager() {        Car car = Car.createCar(this);        CarPropertyManager carProperty = (CarPropertyManager)car.getCarManager(Car.PROPERTY_SERVICE);        CarPropertyValue val = carProperty.getProperty(Boolean.class, NIGHT_MODE, 0);        if(val == null || val.getStatus() != CarPropertyValue.STATUS_AVAILABLE) {            // 该属性不支持或不可用, 使用当前时间判断昼夜情况        } else if (val.getValue()) {            //黑夜模式        } else {            //白昼模式        }    }

虽然getProperty 方法会增加源码的数量,  但还是推荐大家使用该方式获取属性.

在设置属性方面, CarPropertyManager同样提供了setProperty以及明确类型的setIntProperty, setBooleanProperty等方法. 当然这些方法最后还是调用的setProperty.

  public void setBooleanProperty(int prop, int areaId, boolean val) {        setProperty(Boolean.class, prop, areaId, val);    }   public void setFloatProperty(int prop, int areaId, float val) {        setProperty(Float.class, prop, areaId, val);    }    //最终调用的还是这个方法    public  void setProperty(@NonNull Class clazz, int propId, int areaId, @NonNull E val) {        if (DBG) {            Log.d(TAG, "setProperty, propId: 0x" + toHexString(propId)                    + ", areaId: 0x" + toHexString(areaId) + ", class: " + clazz + ", val: " + val);        }        try {            mService.setProperty(new CarPropertyValue<>(propId, areaId, val));        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }

4.2 注册监听器

在注册监听属性变化方面, CarPropertyManager提供更细的监听方法, 它可以监听到单个属性值的变化, 开发者可以通过在注册监听器时传入属性ID指定监听器所对应的属性. 同时指定数据上报的频率.

        //注册监听器        CarPropertyListener carPropertyListener = new CarPropertyListener();        carProperty.registerCallback(carPropertyListener, VehiclePropertyIds.PERF_VEHICLE_SPEED, 6);        //移除监听器        carProperty.unregisterCallback(carPropertyListener);class CarPropertyListener implements  CarPropertyManager.CarPropertyEventCallback{    @Override    public void onChangeEvent(CarPropertyValue carPropertyValue) {    }    @Override    public void onErrorEvent(int i, int i1) {    }}

4.3 CarPropertyManager相关类

前文已经提到过CarInfoManager, CarHvacManager, CarSensorManager 都是通过CarPropertyManager实现其功能的. 在其他几个Manager初始化的时候,都会创建属于自己的CarPropertyManager对象. 这几个Manager拥有了CarPropertyManager以后用来做什么呢?

/packages/services/Car/car-lib/class="lazy" data-src/android/car/CarInfoManager.java

    public float getFuelCapacity() {        return mCarPropertyMgr.getFloatProperty(BASIC_INFO_FUEL_CAPACITY, 0);    }        CarInfoManager(IBinder service) {        ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service);        //在构造方法中创建CarPropertyManager对象        mCarPropertyMgr = new CarPropertyManager(mCarPropertyService, null);    }

packages/services/Car/car-lib/class="lazy" data-src/android/car/hardware/hvac/CarHvacManager.java

    public boolean getBooleanProperty(@PropertyId int propertyId, int area) {        return mCarPropertyMgr.getBooleanProperty(propertyId, area);    }    public CarHvacManager(IBinder service, Context context, Handler handler) {        ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service);        //构造方法中 创建CarPropertyManager对象        mCarPropertyMgr = new CarPropertyManager(mCarPropertyService, handler);    }

原来这些Manager就是对CarPropertyManager的调用,其他几个Manager并没有做什么具体的事情,只是把任务交给了CarPropertyManager再去执行.

在前面文章中出现了如VehiclePropertyIds,  CarPropertyValue, CarPropertyConfig等相关的辅助类. 我们在这里梳理一下各个辅助类的作用

辅助类名称功能作用
VehiclePropertyIds

CarPropertyManager都是通过属性ID来对应具体的功能,不同的功能对应不同的ID

VehiclePropertyIds中列出了所有在VehicleHAL中定义的功能属性

VehicleAreaDoor许多功能点都分为多个区域,在设置,获取相应属性时,需要传入区域参数,VehicleAreaDoor定义了与车门相关的区域值,在使用和车门相关的属性时配套使用
VehicleAreaMirror与VehicleAreaDoor类似, 多区域定义, 后视镜区域值
VehicleAreaSet多区域定义, 座位区域值
VehicleAreaWheel多区域定义, 车胎区域值
VehicleAreaWindow多区域定义,车窗区域值
VehicleAreaType

区域类型是用来区分一个属性所对应的位置, 源码类中有6个值:VEHICLE_AREA_TYPE_GLOBAL 对应于非多区域

VEHICLE_AREA_TYPE_WINDOW(车窗)

VEHICLE_AREA_TYPE_SEAT(座椅)

VEHICLE_AREA_TYPE_DOOR(车门)

VEHICLE_AREA_TYPE_MIRROR(后视镜)

VEHICLE_AREA_TYPE_WHEEL(轮胎)

VehicleLightState灯光状态  开    关    日间
VehicleLightSwitch灯光切换, 开   关     日间      自动
VehicleOilLevel油量状态

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

我们也还经常用到CarPropertyConfig 和 CarPropertyValue这两个模板类.

辅助类功能
CarPropertyConfig获取一个属性的静态参数, 如取值范围,类型,支持的区域等
CarPropertyValue获取一个属性的值和状态

我们先看看CarPropertyConfig它的成员变量列表

类型变量名说明
intmAccess该属性是否可读可写(0:不可读不可写;  1:可读;  2:可写;  3:可读写)
intmAreaType区域类型,与VehicleAreaType对应
intmChangeMode变化类型(0:该属性值始终不变; 1:发生变化时通知; 2:以一定频率持续通知当前值)
ArrayListmConfigArray额外的配置属性
StringmConfigString额外的配置信息
floatmMaxSampleRate最大频率(仅对持续上报属性有效)
floatmMinSampleRate最小频率(仅对持续上报属性有效)
intmPropertyId属性ID
SparseArray>mSupportedAreas区域属性,包含该区域的取值范围
ClassmType属性的类型

看下这个例子, 通过CarPropertyManager获取当前车辆支持的属性(需要在清单文件中声明对应的权限)

        Car car = Car.createCar(this);        CarPropertyManager carProperty = (CarPropertyManager)car.getCarManager(Car.PROPERTY_SERVICE);        List carPropertyConfigList = carProperty.getPropertyList();

在来看看CarPropertyValue的成员变量列表

类型变量名说明
intmPropertyId属性ID
intmAreaId区域ID
intmStatus状态(0:可用;  1:不可用;  2:错误)
longmTimestamp时间戳(单位:纳秒)
TmValue当前值

举个例子 获取当前车速:

        Car car = Car.createCar(this);        CarPropertyManager carProperty = (CarPropertyManager)car.getCarManager(Car.PROPERTY_SERVICE);        //获取当前的车速        CarPropertyValue value = carProperty.getProperty(Float.class, VehiclePropertyIds.PERF_VEHICLE_SPEED,                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);

来源地址:https://blog.csdn.net/u012514113/article/details/129841675

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android汽车服务篇(三) CarPropertyService下篇

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录