当前位置:   article > 正文

Android HAL层添加HIDL实例实现串口通信_android 新增hidl接口

android 新增hidl接口

目录

概述

实现过程

一、hardware部分

1.1 编写hal

1.2 使用hidl-gen生成变量

1.3 实现.cpp

1.4 添加启动service

1.5 VNDK相关

二、device部分

三、SELinux部分——hal service

3.1 vendor 目录

3.2 public 目录

3.3 private 目录

四、framework 实现

五、应用层调用

概述

HIDL是Hardware Interface Definition Language的简称。在Android Project Treble被提出,在android O中被全面的推送,设计 HIDL 这个机制的目的,主要目的是把框架(framework)与 HAL 进行隔离,使得框架部分可以直接被覆盖、更新,而不需要重新对 HAL 进行编译。

HIDL 实际上是用于进行进程间通信(Inter-process Communication,IPC)的。进程间的通信可以称为 Binder 化(Binderized)。对于必须连接到进程的库,也可以使用 passthough 模式(但在Java中不支持)。

下面编写HIDL实例

实现过程

一、hardware部分

1.1 编写hal

.hal文件的语言格式是C++和Java的结合体。

在 AOSP代码目录创建 hardware/interfaces/serialport/1.0/(1.0代表版本,后续版本升级添加文件2.0)

新建ISerialPort.hal,主要类

  1. package android.hardware.serialport@1.0;
  2. import ISerialPortCallback;
  3. interface ISerialPort {
  4. initSerialPort(string address, int32_t baudrate, int32_t flags);//初始化串口
  5. startRead();//开始读取
  6. stopRead();//结束读取
  7. closeSerialPort();//关闭串口
  8. sendSerialPort(vec<int32_t> buf, int32_t size) generates (bool res);//写入数据
  9. setCallback(int32_t type, ISerialPortCallback callback);//回调读取的数据
  10. };

新建 types.hal (非必要,用于定义结构体,复杂变量可在此定义)

  1. package android.hardware.serialport@1.0;
  2. struct SerialPortEvent {
  3. int32_t what;//数据类型
  4. int32_t length;//数据长度
  5. vec<int32_t> data;//数据
  6. };
  7. enum SerialPortType : int32_t {
  8. VARIOUS = 0,
  9. VDR = 1,
  10. CAR_BODY = 2,
  11. AIR = 3,
  12. KEY = 4,
  13. FCT = 5,
  14. AUTOPILOT = 6,
  15. };

新建ISerialPortCallback.hal,用于回调

  1. package android.hardware.serialport@1.0;
  2. interface ISerialPortCallback {
  3. oneway onDataChange(SerialPortEvent event);
  4. };

1.2 使用hidl-gen生成变量

使用hidl-gen的前提是AOSP全编通过,如果之前全编通过可不用再次全编

  1. source ./build/envsetup.sh
  2. lunch car_mt2712-eng
  3. make -j4
  4. make hidl-gen -j4

设置临时变量

  1. PACKAGE=android.hardware.serialport@1.0
  2. 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. └── 1.0
  2. ├── Android.bp
  3. ├── default
  4. │   ├── Android.bp
  5. │   ├── SerialPortCallback.cpp
  6. │   ├── SerialPortCallback.h
  7. │   ├── SerialPort.cpp
  8. │   ├── SerialPort.h
  9. ├── ISerialPortCallback.hal
  10. ├── ISerialPort.hal
  11. └── types.hal

1.3 实现.cpp

SerialPort.h (由hidl-gen工具生成)

  1. #ifndef ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H
  2. #define ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H
  3. #include <android/hardware/serialport/1.0/ISerialPort.h>
  4. #include <hidl/MQDescriptor.h>
  5. #include <hidl/Status.h>
  6. #include "android/log.h"
  7. static const char *TAG="serialport";
  8. #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
  9. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
  10. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
  11. #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
  12. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)
  13. namespace android {
  14. namespace hardware {
  15. namespace serialport {
  16. namespace V1_0 {
  17. namespace implementation {
  18. using ::android::hardware::hidl_array;
  19. using ::android::hardware::hidl_memory;
  20. using ::android::hardware::hidl_string;
  21. using ::android::hardware::hidl_vec;
  22. using ::android::hardware::Return;
  23. using ::android::hardware::Void;
  24. using ::android::sp;
  25. struct SerialPort : public ISerialPort {
  26. // Methods from ::android::hardware::serialport::V1_0::ISerialPort follow.
  27. Return<void> initSerialPort(const hidl_string& address, int32_t baudrate, int32_t flags) override;
  28. Return<void> startRead() override;
  29. Return<void> stopRead() override;
  30. Return<void> closeSerialPort() override;
  31. Return<bool> sendSerialPort(const hidl_vec<int32_t>& buf, int32_t size) override;
  32. Return<void> setCallback(int32_t type, const sp<::android::hardware::serialport::V1_0::ISerialPortCallback>& callback) override;
  33. // Methods from ::android::hidl::base::V1_0::IBase follow.
  34. private:
  35. void run();
  36. };
  37. // FIXME: most likely delete, this is only for passthrough implementations
  38. // extern "C" ISerialPort* HIDL_FETCH_ISerialPort(const char* name);
  39. } // namespace implementation
  40. } // namespace V1_0
  41. } // namespace serialport
  42. } // namespace hardware
  43. } // namespace android
  44. #endif // ANDROID_HARDWARE_SERIALPORT_V1_0_SERIALPORT_H

SerialPort.cpp (由hidl-gen工具生成)

实现各个方法,由于代码比较多多,就不贴出来。SerialPort.cpp

1.4 添加启动service

新建android.hardware.serialport@1.0-service.rc 启动脚本

  1. service serialport-hal-1-0 /vendor/bin/hw/android.hardware.serialport@1.0-service
  2. class hal
  3. user system
  4. group system

新建service.cpp 

  1. #define LOG_TAG "serialport1.0-service"
  2. #include <android/log.h>
  3. #include <hidl/HidlTransportSupport.h>
  4. #include "SerialPort.h"
  5. using android::sp;
  6. using android::status_t;
  7. using android::OK;
  8. using android::hardware::configureRpcThreadpool;
  9. using android::hardware::joinRpcThreadpool;
  10. using android::hardware::serialport::V1_0::ISerialPort;
  11. using android::hardware::serialport::V1_0::implementation::SerialPort;
  12. int main(int /* argc */, char* /* argv */ []) {
  13. android::sp<ISerialPort> service = new SerialPort();
  14. configureRpcThreadpool(4, true /*callerWillJoin*/);
  15. status_t status = service->registerAsService();
  16. if (status == OK) {
  17. LOGD("SerialPort HAL Ready.");
  18. service->initSerialPort("/dev/ttyS2", 115200, 0);
  19. service->startRead();
  20. joinRpcThreadpool();
  21. }
  22. LOGD("Cannot register Serialport HAL service");
  23. return 1;
  24. }

修改Android.bp

  1. cc_library_shared {
  2. // FIXME: this should only be -impl for a passthrough hal.
  3. // In most cases, to convert this to a binderized implementation, you should:
  4. // - change '-impl' to '-service' here and make it a cc_binary instead of a
  5. // cc_library_shared.
  6. // - add a *.rc file for this module.
  7. // - delete HIDL_FETCH_I* functions.
  8. // - call configureRpcThreadpool and registerAsService on the instance.
  9. // You may also want to append '-impl/-service' with a specific identifier like
  10. // '-vendor' or '-<hardware identifier>' etc to distinguish it.
  11. name: "android.hardware.serialport@1.0-impl",
  12. relative_install_path: "hw",
  13. // FIXME: this should be 'vendor: true' for modules that will eventually be
  14. // on AOSP.
  15. proprietary: true,
  16. srcs: [
  17. "SerialPort.cpp",
  18. ],
  19. shared_libs: [
  20. "libhidlbase",
  21. "libhidltransport",
  22. "libutils",
  23. "liblog",
  24. "android.hardware.serialport@1.0",
  25. ],
  26. }
  27. cc_binary {
  28. name: "android.hardware.serialport@1.0-service",
  29. relative_install_path: "hw",
  30. defaults: ["hidl_defaults"],
  31. proprietary: true,
  32. init_rc: ["android.hardware.serialport@1.0-service.rc"],
  33. srcs: [
  34. "SerialPort.cpp",
  35. "service.cpp",
  36. ],
  37. shared_libs: [
  38. "libbase",
  39. "liblog",
  40. "libdl",
  41. "libutils",
  42. "libhardware",
  43. "libhidlbase",
  44. "libhidltransport",
  45. "android.hardware.serialport@1.0",
  46. ],
  47. }

调用 update-makefiles.sh更新一下

1.5 VNDK相关

在目录aosp\build\make\target\product\vndk 里

28.txt 和 current.txt 按照字母顺序新增

VNDK-core: android.hardware.serialport@1.0.so

二、device部分

lunch的是car_mt2712-eng,芯片是MTK的2712,所以在device找到下面目录aosp\device\mediatek/mt2712/manifest_ab.xml,由于是mtk提供的代码,所以在manifest_ab.xml添加,正常应该在manifest.xml

  1. <hal format="hidl">
  2. <name>android.hardware.serialport</name>
  3. <transport>hwbinder</transport>
  4. <version>1.0</version>
  5. <interface>
  6. <name>ISerialPort</name>
  7. <instance>default</instance>
  8. </interface>
  9. </hal>

mediatek/mt2712/device.mk添加 启动 serialport service

  1. # serialport HAL
  2. PRODUCT_PACKAGES += \
  3. android.hardware.serialport@1.0-service \
  4. android.hardware.serialport@1.0-impl

三、SELinux部分——hal service

对应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 等变化的设定, 以兼容老版本.

3.1 vendor 目录

file_contexts 添加

  1. /(vendor|system/vendor)/bin/hw/android\.hardware\.serialport@1\.0-service u:object_r:hal_serialport_default_exec:s0
  2. #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是用来描述进程的安全上下文的。

  1. type hal_serialport_default, domain;
  2. hal_server_domain(hal_serialport_default, hal_serialport)
  3. type hal_serialport_default_exec, exec_type, vendor_file_type, file_type;
  4. init_daemon_domain(hal_serialport_default)
  5. allow hal_serialport_default serial_device:chr_file rw_file_perms;

3.2 public 目录

attributes 添加

hal_attribute(serialport);

hwservice.te 添加

type hal_serialport_hwservice, hwservice_manager_type;

新建 hal_serialport.te

  1. # HwBinder IPC from client to server, and callbacks
  2. binder_call(hal_serialport_client, hal_serialport_server)
  3. binder_call(hal_serialport_server, hal_serialport_client)
  4. add_hwservice(hal_serialport_server, hal_serialport_hwservice)
  5. allow hal_serialport_client hal_serialport_hwservice:hwservice_manager find;

将以上修改同步到aosp\system\sepolicy\prebuilts\api\28.0\public

3.3 private 目录

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

四、framework 实现

添加frameworks/baseservices/core/java/com/android/server/SerialService.java,具体添加方法这里就不写了,framework添加新service的方法可以自行百度。下面是主要类

ISerialPortService.aidl

  1. package android.os.serialport;
  2. import android.os.serialport.ISerialPortListener;
  3. interface ISerialPortService {
  4. boolean sendData(in byte [] buf, int size);
  5. void registerCallback(ISerialPortListener listener);
  6. void unRegisterCallback(ISerialPortListener listener);
  7. }

 SerialPortService.java

  1. package com.android.server;
  2. import android.hardware.serialport.V1_0.ISerialPort;
  3. import android.hardware.serialport.V1_0.ISerialPortCallback;
  4. import android.hardware.serialport.V1_0.SerialPortEvent;
  5. public class SerialPortService extends ISerialPortService.Stub {
  6. private Context mContext;
  7. private ISerialPort mHalService;
  8. public SerialPortService(Context context) {
  9. mContext = context;
  10. mHalService = ISerialPort.getService();//获取service
  11. if (mHalService != null) {//设置监听回调
  12. mHalService.setCallback(mType, new ISerialPortCallback.Stub() {
  13. @Override
  14. public void onDataChange(SerialPortEvent event) {
  15. }
  16. });
  17. }
  18. }
  19. }

 SerialPortManager.java,主要为应用层提供接口

  1. public class SerialPortManager {
  2. public static final String TAG = "SerialPortManager";
  3. private ISerialPortService mService;
  4. private int mMsgId;
  5. public SerialPortManager(ISerialPortService service) {
  6. mService = service;
  7. }
  8. public boolean sendData(byte[] buf, int size) {
  9. try {
  10. if (mService != null) {
  11. ArrayList<Integer> list = new ArrayList();
  12. for (byte b : buf) {
  13. list.add(b & 0xFF);
  14. }
  15. return mService.sendData(buf, size);
  16. }
  17. } catch (RemoteException e) {
  18. e.printStackTrace();
  19. }
  20. return false;
  21. }
  22. public void registerCallback(SerialPortListener listener) {
  23. try {
  24. if (mService != null) {
  25. mService.registerCallback(listener);
  26. }
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. public void unRegisterCallback(SerialPortListener listener) {
  32. try {
  33. if (mService != null) {
  34. mService.unRegisterCallback(listener);
  35. }
  36. } catch (Exception e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }

五、应用层调用

同framework的SerialServiceManager.java提供接口来实现串口通信,sendData用于写数据,callback回调用于读取串口的数据

 至此一个完整HIDL实例,用于串口通信,基于android 9.0

代码在github,  https://github.com/niuzhuangzhuang/serialport

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/255847?site
推荐阅读
相关标签
  

闽ICP备14008679号