HMI车载开发:汽车与Android的关系:Android Automotive

1: Android Automotive

     Android Auto是以手机为中心的。这种模型既有好处,也有坏处。

    Android Automotive 如果是系统直接内置于汽车,那就是完全不一样的体验了。而Android Automotive则是面向这个方向设计的,同时一旦讲系统内置余汽车,可以完成的功能将大大增强,例如:直接在中控触摸屏上调整空调和座椅,或者获取汽车油耗,刹车使用等等。

  Android Auto : 好处是:数据和应用始终是一致的,不存在需要数据同步的问题,手机上装的软件和已有的数据,接到汽车直接就有了。而坏处是,每次得拿出手机,汽车只是手机一个外设。并且,这种模式不便于对于汽车本身的控制和相关数据的获取。

2:源码和架构

 Android Automative的源码包含在 AOSP中,整体架构如下:

 从上图我们可以看出,Android Automative是在原先Android的系统架构上增加了一些与车相关的(虚线框中绿色背景)模块。

包括:

Car App : OEM和第三方开发的App

Car Api:  提供给汽车App特有的接口

Car Service: 系统中与车相关的服务

Vehicle Network Service:  汽车网络服务

Vehicle HAL : 汽车硬件的抽象层描述

2.1 : Car App

/car_product/build/car.mk 
这些App的源码都位于/platform/packages/services/Car/目录下

这个文件中列出了汽车系统中专有的模块,首字母大写的模块都是汽车系统中专有的App.

 2.2 :  Car Api

源码:/platform/packages/services/Car/car-lib

开发汽车专有的App自然需要专有的Api . 这些API 对于其他平台(手机和平板)通常是没有任何意义的,所以这些Api 没有包含在 Android Framework SDK中。

下面这张大图列出了所有Car Api 

  • android.car : 包含了与车相关的基本Api . 例如: 车辆后视镜,门,座位,窗口等。
  • carbin: 座舱相关API
  • hvac : 通风空调相关API (hvac : Heating ventialtion and air conditioning)
  • property: 属性相关Api
  • radio:收音机相关Api
  • pm:应用包相关API
  • render:渲染相关API
  • menu:车辆应用菜单相关API
  • annotation:注解
  • app:
  • cluster:仪表盘相关API
  • content:
  • diagnostic:汽车诊断相关API
  • hardware:车辆硬件相关API
  • input:输入相关API
  • media:多媒体相关API
  • navigation:导航相关API
  • setting:设置相关API
  • vms:汽车检测相关API

 2.3:car Service

在Android Automative中的 Car Service集中在一个App中。所以可以想象,这个App需要非常高的权限,所以这是一个系统App,其中Manifest开头如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        package="com.android.car"
        coreApp="true"
        android:sharedUserId="android.uid.system">

android:sharedUserId属性使得这个应用具有系统权限。

Car Service并非一个服务,而是一系列的服务。这些服务都在ICarImpl.java构造函数中列了出来。

public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
        CanBusErrorNotifier errorNotifier) {
    mContext = serviceContext;
    mHal = new VehicleHal(vehicle);
    mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
    mCarPowerManagementService = new CarPowerManagementService(
            mHal.getPowerHal(), systemInterface);
    mCarSensorService = new CarSensorService(serviceContext, mHal.getSensorHal());
    mCarPackageManagerService = new CarPackageManagerService(serviceContext, mCarSensorService,
            mSystemActivityMonitoringService);
    mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
    mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
    mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
    mCarInfoService = new CarInfoService(serviceContext, mHal.getInfoHal());
    mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
    mCarAudioService = new CarAudioService(serviceContext, mHal.getAudioHal(),
            mCarInputService, errorNotifier);
    mCarCabinService = new CarCabinService(serviceContext, mHal.getCabinHal());
    mCarHvacService = new CarHvacService(serviceContext, mHal.getHvacHal());
    mCarRadioService = new CarRadioService(serviceContext, mHal.getRadioHal());
    mCarNightService = new CarNightService(serviceContext, mCarSensorService);
    mInstrumentClusterService = new InstrumentClusterService(serviceContext,
            mAppFocusService, mCarInputService);
    mSystemStateControllerService = new SystemStateControllerService(serviceContext,
            mCarPowerManagementService, mCarAudioService, this);
    mCarVendorExtensionService = new CarVendorExtensionService(serviceContext,
            mHal.getVendorExtensionHal());
    mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
    mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService,
            mCarSensorService, mPerUserCarServiceHelper);
    if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
        mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
        mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
    }
    mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());

    ...

 2.4:Car Tool

还有几个模块没有出现在上面的架构图中。但它们也包含在了Android Automative系统中,这里一并介绍一下。

2.4.1 :  VMS

VMS全称是Vehicle Monitor Service。正如其名称所示,这个服务用来监测其他进程。

源码:

vehicle_monitor_service
libvehiclemonitor/

在运行时,这个服务是一个独立的进程,在init.car.rc中有关于它的配置:

service vms /system/bin/vehicle_monitor_service
   class core
   user root
   group root
   critical

on boot
    start vms

这是一个Binder服务,并提供了C++和Java的Binder接口用来供其他模块使用。

2.4.2 :EVS

Android 8.0包含一个汽车 HIDL 硬件抽象层(HAL),可用于在 Android 启动过程的初期提供图像捕获和显示,并在系统启动后继续运行直到系统终止。HAL包含外部视景系统 (Exterior View System,简称EVS) 堆栈,通常用于在具有车载信息娱乐(IVI)系统(基于 Android)的车辆中支持后视摄像头和环绕视图显示。EVS 还支持在用户应用中实现高级功能。

其中 EVS包括以下系统组件

 

  • EVS应用:该应用负责从EVS管理器请求视频帧,并将用于显示的已完成的帧发送回EVS管理器。EVS和汽车服务可供使用后,它便立即由init启动。OEM可视需要修改或替换EVS应用。

  • EVS 管理器:EVS管理器可提供 EVS 应用所需的编译块,以实现从简单的后视摄像头显示到6DOF多相机渲染的任何功能。它的接口通过 HIDL呈现,并被编译为接受多个并发客户端。其他应用和服务(特别是汽车服务)可以查询 EVS 管理器状态,以了解EVS系统何时处于活动状态。

  • EVS HIDL接口:在 EVS 系统中,相机和显示元素均在 android.hardware.automotive.evs 程序包中进行定义。用于实践接口的示例实现(生成合成测试图像并验证图像进行往返的过程)在 /hardware/interfaces/automotive/evs/1.0/default 中进行提供。

  • 内核驱动程序:支持EVS堆栈的设备需要使用内核驱动程序。OEM无需创建新驱动程序,他们可以选择通过现有相机和/或显示硬件驱动程序来支持EVS所需的功能。重复使用驱动程序可能会有好处,对于图像呈现可能需要与其他活动线程协调的显示驱动程序来说尤其如此。

2.4.3 :ODB2

ODB全称是On-Board Diagnostics。这是一种装置于车中用以监控车辆运行状态和回报异常的系统,可于车辆的子系统出现问题时,产生故障代码和提醒讯号通知车主和车厂诊断维修。1980年车上诊断系统发明后,早期仅能以指示灯形式回报故障发生与否。随着计算机技术的进步,目前已经能回报各式各样的实时数据和标准化故障代码(diagnostic trouble codes,DTC),使得汽车故障诊断维修方法发生翻天覆地的变化。

OBD-II是基于OBD-I的基础上,增加了资料容量并将其标准化。OBD-II明确定义了连接器型式、脚位、可用通讯协定以及讯息格式。OBD-II同时也提供额外可监控汽车参数清单以及编码方式说明。

AOSP中的ODB2库是以一个Java静态库的形式存在的。

2.5: Vehicle Network Service

源码:

vehicle_network_service
libvehiclenetwork

Vehicle Network Service的结构和VMS的结构是类似的,也是一个可执行文件(vehicle_network_service)加一个库(libvehiclenetwork)的形式。

libvehiclenetwork中既包含了C++的库,也包含了Java语言的库。对于需要跨语言访问的数据结构,使用Protocol Buffers 格式描述:libvehiclenetwork/proto/。

vehicle Network Service的主要作用是通过它来设置HAL属性(见下文HAL)。这些属性在VehicleNetworkConsts.java中已经全部列出:

public static final int VEHICLE_PROPERTY_INFO_VIN = 0x00000100;
public static final int VEHICLE_PROPERTY_INFO_MAKE = 0x00000101;
public static final int VEHICLE_PROPERTY_INFO_MODEL = 0x00000102;
public static final int VEHICLE_PROPERTY_INFO_MODEL_YEAR = 0x00000103;
public static final int VEHICLE_PROPERTY_INFO_FUEL_CAPACITY = 0x00000104;
public static final int VEHICLE_PROPERTY_PERF_ODOMETER = 0x00000204;
public static final int VEHICLE_PROPERTY_PERF_VEHICLE_SPEED = 0x00000207;
public static final int VEHICLE_PROPERTY_ENGINE_COOLANT_TEMP = 0x00000301;
public static final int VEHICLE_PROPERTY_ENGINE_OIL_TEMP = 0x00000304;
public static final int VEHICLE_PROPERTY_ENGINE_RPM = 0x00000305;
public static final int VEHICLE_PROPERTY_GEAR_SELECTION = 0x00000400;
public static final int VEHICLE_PROPERTY_CURRENT_GEAR = 0x00000401;
public static final int VEHICLE_PROPERTY_PARKING_BRAKE_ON = 0x00000402;
public static final int VEHICLE_PROPERTY_DRIVING_STATUS = 0x00000404;
public static final int VEHICLE_PROPERTY_FUEL_LEVEL_LOW = 0x00000405;
public static final int VEHICLE_PROPERTY_NIGHT_MODE = 0x00000407;
public static final int VEHICLE_PROPERTY_HVAC_FAN_SPEED = 0x00000500;
public static final int VEHICLE_PROPERTY_HVAC_FAN_DIRECTION = 0x00000501;
public static final int VEHICLE_PROPERTY_HVAC_TEMPERATURE_CURRENT = 0x00000502;
public static final int VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET = 0x00000503;
public static final int VEHICLE_PROPERTY_HVAC_DEFROSTER = 0x00000504;
public static final int VEHICLE_PROPERTY_HVAC_AC_ON = 0x00000505;
public static final int VEHICLE_PROPERTY_HVAC_MAX_AC_ON = 0x00000506;
public static final int VEHICLE_PROPERTY_HVAC_MAX_DEFROST_ON = 0x00000507;
public static final int VEHICLE_PROPERTY_HVAC_RECIRC_ON = 0x00000508;
public static final int VEHICLE_PROPERTY_HVAC_DUAL_ON = 0x00000509;
public static final int VEHICLE_PROPERTY_ENV_OUTSIDE_TEMPERATURE = 0x00000703;
public static final int VEHICLE_PROPERTY_ENV_CABIN_TEMPERATURE = 0x00000704;
public static final int VEHICLE_PROPERTY_RADIO_PRESET = 0x0000801;
public static final int VEHICLE_PROPERTY_AUDIO_FOCUS = 0x00000900;
public static final int VEHICLE_PROPERTY_AUDIO_VOLUME = 0x00000901;
public static final int VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT = 0x00000902;
public static final int VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY = 0x00000903;
public static final int VEHICLE_PROPERTY_AUDIO_HW_VARIANT = 0x00000904;
public static final int VEHICLE_PROPERTY_AP_POWER_STATE = 0x00000A00;
public static final int VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS = 0x00000A01;
public static final int VEHICLE_PROPERTY_AP_POWER_BOOTUP_REASON = 0x00000A02;
public static final int VEHICLE_PROPERTY_HW_KEY_INPUT = 0x00000A10;
public static final int VEHICLE_PROPERTY_INSTRUMENT_CLUSTER_INFO = 0x00000A20;
public static final int VEHICLE_PROPERTY_CUSTOM_START = 0x70000000;
public static final int VEHICLE_PROPERTY_CUSTOM_END = 0x73ffffff;
public static final int VEHICLE_PROPERTY_INTERNAL_START = 0x74000000;
public static final int VEHICLE_PROPERTY_INTERNAL_END = 0x74ffffff;
public static final int VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE = 0x74000000;

2.6:  HAL

源码:

hardware/libhardware/include/hardware/vehicle.h
hardware/libhardware/modules/vehicle/

车载HAL(Hareware Abstract Layer,硬件抽象层)接口会定义OEM可以实现的属性,并会包含属性元数据(例如,属性是否为 int 以及允许使用哪些更改模式)。车载 HAL 接口是以对属性(特定功能的抽象表示)的访问(读取、写入、订阅)为基础。

2.6.1: HAL接口

车载HAL使用以下接口:

  • vehicle_prop_config_t const *(*list_properties)(..., int* num_properties) 列出车载 HAL 所支持的所有属性的配置。车辆网络服务只会使用受支持的属性。

  • (*get)(..., vehicle_prop_value_t *data) 读取属性的当前值。对于区域属性,每个区域都可能具有不同的值。

  • (*set)(..., const vehicle_prop_value_t *data) 为属性写入相应值。写入的结果是按属性进行定义。

  • (*subscribe)(..., int32_t prop, float sample_rate, int32_t zones) 监视属性值的变化,回调见下文。

  • (*release_memory_from_get)(struct vehicle_hw_device* device, vehicle_prop_value_t *data) 释放从 get 调用分配的内存。

车载HAL使用以下回调接口:

  • (*vehicle_event_callback_fn)(const vehicle_prop_value_t *event_data) 通知车辆属性值的变化。

  • (*vehicle_error_callback_fn)(int32_t error_code, int32_t property, int32_t operation) 返回全局车载 HAL级错误或每个属性的错误。全局错误会导致HAL重新启动,这可能导致包括应用在内的其他组件重新启动。

2.6.2:属性与区域

每个属性都由 int32 键唯一标识,且具有预定义的类型(value_type):INT32(和数组)、INT64、BOOLEAN、FLOAT(和数组)、字符串、字节。

区域类型除了值之外还有区域。车载HAL定义了下面几种区域类型:

enum vehicle_zone_type {
    VEHICLE_ZONE_TYPE_NONE      = 0x00,
    VEHICLE_ZONE_TYPE_ZONE      = 0x01,
    VEHICLE_ZONE_TYPE_SEAT      = 0x02,
    VEHICLE_ZONE_TYPE_DOOR      = 0x04,
    VEHICLE_ZONE_TYPE_WINDOW    = 0x10,
    VEHICLE_ZONE_TYPE_MIRROR    = 0x20,
};

举一个获取 HVAC温度的调用过程

 下面是设置HAVC温度的调用过程

图中缩写说明如下:

  • CS:CarService

  • VNS:VehicleNetworkService

  • VHAL:Vehicle HAL

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值