赞
踩
目录
HIDL是Hardware Interface Definition Language的简称。在Android Project Treble被提出,在android O中被全面的推送,设计 HIDL 这个机制的目的,主要目的是把框架(framework)与 HAL 进行隔离,使得框架部分可以直接被覆盖、更新,而不需要重新对 HAL 进行编译。
HIDL 实际上是用于进行进程间通信(Inter-process Communication,IPC)的。进程间的通信可以称为 Binder 化(Binderized)。对于必须连接到进程的库,也可以使用 passthough 模式(但在Java中不支持)。
下面编写HIDL实例
.hal文件的语言格式是C++和Java的结合体。
在 AOSP代码目录创建 hardware/interfaces/serialport/1.0/(1.0代表版本,后续版本升级添加文件2.0)
新建ISerialPort.hal,主要类
- package android.hardware.serialport@1.0;
-
- import ISerialPortCallback;
-
- interface ISerialPort {
- initSerialPort(string address, int32_t baudrate, int32_t flags);//初始化串口
- startRead();//开始读取
- stopRead();//结束读取
- closeSerialPort();//关闭串口
- sendSerialPort(vec<int32_t> buf, int32_t size) generates (bool res);//写入数据
- setCallback(int32_t type, ISerialPortCallback callback);//回调读取的数据
- };
新建 types.hal (非必要,用于定义结构体,复杂变量可在此定义)
- package android.hardware.serialport@1.0;
-
- struct SerialPortEvent {
- int32_t what;//数据类型
- int32_t length;//数据长度
- vec<int32_t> data;//数据
- };
-
- enum SerialPortType : int32_t {
- VARIOUS = 0,
- VDR = 1,
- CAR_BODY = 2,
- AIR = 3,
- KEY = 4,
- FCT = 5,
- AUTOPILOT = 6,
- };
新建ISerialPortCallback.hal,用于回调
- package android.hardware.serialport@1.0;
-
- interface ISerialPortCallback {
- oneway onDataChange(SerialPortEvent event);
- };
使用hidl-gen的前提是AOSP全编通过,如果之前全编通过可不用再次全编
- source ./build/envsetup.sh
- lunch car_mt2712-eng
- make -j4
- make hidl-gen -j4
设置临时变量
- PACKAGE=android.hardware.serialport@1.0
- LOC=hardware/interfaces/serialport/1.0/default
使用hidl-gen生成default目录 里的C++文件
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
使用hidl-gen生成default目录 里的Android.bp文件
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
使用update-makefiles.sh生成1.0目录下的Android.bp
./hardware/interfaces/update-makefiles.sh
此时的目录结构为
- └── 1.0
- ├── Android.bp
- ├── default
- │ ├── Android.bp
- │ ├── SerialPortCallback.cpp
- │ ├── SerialPortCallback.h
- │ ├── SerialPort.cpp
- │ ├── SerialPort.h
- ├── ISerialPortCallback.hal
- ├── ISerialPort.hal
- └── types.hal
SerialPort.h (由hidl-gen工具生成)
- #ifndef ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H
- #define ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H
-
- #include <android/hardware/serialport/1.0/ISerialPort.h>
- #include <hidl/MQDescriptor.h>
- #include <hidl/Status.h>
- #include "android/log.h"
-
- static const char *TAG="serialport";
- #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
- #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)
-
- namespace android {
- namespace hardware {
- namespace serialport {
- namespace V1_0 {
- namespace implementation {
-
- using ::android::hardware::hidl_array;
- using ::android::hardware::hidl_memory;
- using ::android::hardware::hidl_string;
- using ::android::hardware::hidl_vec;
- using ::android::hardware::Return;
- using ::android::hardware::Void;
- using ::android::sp;
-
- struct SerialPort : public ISerialPort {
- // Methods from ::android::hardware::serialport::V1_0::ISerialPort follow.
- Return<void> initSerialPort(const hidl_string& address, int32_t baudrate, int32_t flags) override;
- Return<void> startRead() override;
- Return<void> stopRead() override;
- Return<void> closeSerialPort() override;
- Return<bool> sendSerialPort(const hidl_vec<int32_t>& buf, int32_t size) override;
- Return<void> setCallback(int32_t type, const sp<::android::hardware::serialport::V1_0::ISerialPortCallback>& callback) override;
-
- // Methods from ::android::hidl::base::V1_0::IBase follow.
- private:
- void run();
-
- };
-
- // FIXME: most likely delete, this is only for passthrough implementations
- // extern "C" ISerialPort* HIDL_FETCH_ISerialPort(const char* name);
-
- } // namespace implementation
- } // namespace V1_0
- } // namespace serialport
- } // namespace hardware
- } // namespace android
-
- #endif // ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H
SerialPort.cpp (由hidl-gen工具生成)
实现各个方法,由于代码比较多多,就不贴出来。SerialPort.cpp
新建android.hardware.serialport@1.0-service.rc 启动脚本
- service serialport-hal-1-0 /vendor/bin/hw/android.hardware.serialport@1.0-service
- class hal
- user system
- group system
新建service.cpp
- #define LOG_TAG "serialport1.0-service"
-
- #include <android/log.h>
- #include <hidl/HidlTransportSupport.h>
- #include "SerialPort.h"
-
- using android::sp;
- using android::status_t;
- using android::OK;
-
- using android::hardware::configureRpcThreadpool;
- using android::hardware::joinRpcThreadpool;
- using android::hardware::serialport::V1_0::ISerialPort;
- using android::hardware::serialport::V1_0::implementation::SerialPort;
-
- int main(int /* argc */, char* /* argv */ []) {
- android::sp<ISerialPort> service = new SerialPort();
-
- configureRpcThreadpool(4, true /*callerWillJoin*/);
- status_t status = service->registerAsService();
-
- if (status == OK) {
- LOGD("SerialPort HAL Ready.");
- service->initSerialPort("/dev/ttyS2", 115200, 0);
- service->startRead();
- joinRpcThreadpool();
- }
-
- LOGD("Cannot register Serialport HAL service");
- return 1;
- }
修改Android.bp
- cc_library_shared {
- // FIXME: this should only be -impl for a passthrough hal.
- // In most cases, to convert this to a binderized implementation, you should:
- // - change '-impl' to '-service' here and make it a cc_binary instead of a
- // cc_library_shared.
- // - add a *.rc file for this module.
- // - delete HIDL_FETCH_I* functions.
- // - call configureRpcThreadpool and registerAsService on the instance.
- // You may also want to append '-impl/-service' with a specific identifier like
- // '-vendor' or '-<hardware identifier>' etc to distinguish it.
- name: "android.hardware.serialport@1.0-impl",
- relative_install_path: "hw",
- // FIXME: this should be 'vendor: true' for modules that will eventually be
- // on AOSP.
- proprietary: true,
- srcs: [
- "SerialPort.cpp",
- ],
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libutils",
- "liblog",
- "android.hardware.serialport@1.0",
- ],
- }
-
- cc_binary {
- name: "android.hardware.serialport@1.0-service",
- relative_install_path: "hw",
- defaults: ["hidl_defaults"],
- proprietary: true,
- init_rc: ["android.hardware.serialport@1.0-service.rc"],
- srcs: [
- "SerialPort.cpp",
- "service.cpp",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- "libdl",
- "libutils",
- "libhardware",
- "libhidlbase",
- "libhidltransport",
- "android.hardware.serialport@1.0",
- ],
- }
调用 update-makefiles.sh更新一下
在目录aosp\build\make\target\product\vndk 里
28.txt 和 current.txt 按照字母顺序新增
VNDK-core: android.hardware.serialport@1.0.so
lunch的是car_mt2712-eng,芯片是MTK的2712,所以在device找到下面目录aosp\device\mediatek/mt2712/manifest_ab.xml,由于是mtk提供的代码,所以在manifest_ab.xml添加,正常应该在manifest.xml
- <hal format="hidl">
- <name>android.hardware.serialport</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>ISerialPort</name>
- <instance>default</instance>
- </interface>
- </hal>
mediatek/mt2712/device.mk添加 启动 serialport service
- # serialport HAL
- PRODUCT_PACKAGES += \
- android.hardware.serialport@1.0-service \
- android.hardware.serialport@1.0-impl
对应sepolicy, Google 也设定了不同的存放目录, 以便进行分离, 以Google 默认的sepolicy 为例. /system/sepolicy
public: android 和 vendor 共享的sepolicy 定义, 通常情况下, 意味着vendor 开发者可能为此新增一些权限. 一般system/vendor 共用的一些类型和属性的定义, neverallow 限制等会存放于此.
private: 通常意义上的仅限于system image 内部的使用, 不对vendor 开放. 这个只会编译到system image 中.
vendor: 它仅仅能引用public 目录下的相关定义, 这个只会编译到vendor image 中. 但它依旧可以对system image 里面的module 设定sepolicy(对应module 需要在public 下进行声明); 在很大程度上绕过了Google GTS 约束测试.
mapping: 为兼容老版本的sepolicy 而导入, 只有在system image version > vendor version 的时候, 才可能被用到. 即包括两方面, 新版本增加的type , 新版本移除的type, 以及老版本public, 新版本private 等变化的设定, 以兼容老版本.
file_contexts 添加
- /(vendor|system/vendor)/bin/hw/android\.hardware\.serialport@1\.0-service u:object_r:hal_serialport_default_exec:s0
- #file_contexts文件保存系统中所有文件的安全上下文定义,每行前半部分是文件的路径,后面是它的安全上下文的定义(hal_serialport_default_exec)
新建 hal_serialport_default.te
在TE中,所有的东西都被抽象成类型。进程,抽象成类型;资源,抽象成类型。属性,是类型的集合。所以,TE规则中的最小单位就是类型。
#定义一个 名字为 hal_serialport_default 的type
#TYPE是定义主体和客体所属的类型,对于进程而言,它的类型也称为domian。
#通常主体的type具有domian属性,因此,我们也把主体的type称为domain,将domain设置为hal_test_default的属性,表明zygote是用来描述进程的安全上下文的。
- type hal_serialport_default, domain;
- hal_server_domain(hal_serialport_default, hal_serialport)
-
- type hal_serialport_default_exec, exec_type, vendor_file_type, file_type;
- init_daemon_domain(hal_serialport_default)
- allow hal_serialport_default serial_device:chr_file rw_file_perms;
attributes 添加
hal_attribute(serialport);
hwservice.te 添加
type hal_serialport_hwservice, hwservice_manager_type;
新建 hal_serialport.te
- # HwBinder IPC from client to server, and callbacks
- binder_call(hal_serialport_client, hal_serialport_server)
- binder_call(hal_serialport_server, hal_serialport_client)
-
- add_hwservice(hal_serialport_server, hal_serialport_hwservice)
-
- allow hal_serialport_client hal_serialport_hwservice:hwservice_manager find;
将以上修改同步到aosp\system\sepolicy\prebuilts\api\28.0\public
hwservice_contexts 添加
android.hardware.serialport::ISerialPort u:object_r:hal_serialport_hwservice:s0
private/compat/26.0/26.0.ignore.cil 添加
hal_serialport_hwservice
private/compat/27.0/27.0.ignore.cil 添加
hal_serialport_hwservice
将以上修改同步到aosp\system\sepolicy\prebuilts\api\28.0\private
添加frameworks/baseservices/core/java/com/android/server/SerialService.java,具体添加方法这里就不写了,framework添加新service的方法可以自行百度。下面是主要类
ISerialPortService.aidl
- package android.os.serialport;
-
- import android.os.serialport.ISerialPortListener;
-
- interface ISerialPortService {
- boolean sendData(in byte [] buf, int size);
- void registerCallback(ISerialPortListener listener);
- void unRegisterCallback(ISerialPortListener listener);
- }
SerialPortService.java
- package com.android.server;
-
- import android.hardware.serialport.V1_0.ISerialPort;
- import android.hardware.serialport.V1_0.ISerialPortCallback;
- import android.hardware.serialport.V1_0.SerialPortEvent;
-
- public class SerialPortService extends ISerialPortService.Stub {
- private Context mContext;
- private ISerialPort mHalService;
-
- public SerialPortService(Context context) {
- mContext = context;
- mHalService = ISerialPort.getService();//获取service
- if (mHalService != null) {//设置监听回调
- mHalService.setCallback(mType, new ISerialPortCallback.Stub() {
- @Override
- public void onDataChange(SerialPortEvent event) {
-
- }
- });
- }
- }
- }
SerialPortManager.java,主要为应用层提供接口
- public class SerialPortManager {
- public static final String TAG = "SerialPortManager";
-
- private ISerialPortService mService;
- private int mMsgId;
-
- public SerialPortManager(ISerialPortService service) {
- mService = service;
- }
-
- public boolean sendData(byte[] buf, int size) {
- try {
- if (mService != null) {
- ArrayList<Integer> list = new ArrayList();
- for (byte b : buf) {
- list.add(b & 0xFF);
- }
- return mService.sendData(buf, size);
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- return false;
- }
- public void registerCallback(SerialPortListener listener) {
- try {
- if (mService != null) {
- mService.registerCallback(listener);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void unRegisterCallback(SerialPortListener listener) {
- try {
- if (mService != null) {
- mService.unRegisterCallback(listener);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
同framework的SerialServiceManager.java提供接口来实现串口通信,sendData用于写数据,callback回调用于读取串口的数据
至此一个完整HIDL实例,用于串口通信,基于android 9.0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。