Hidl编程实战(一)——定义HAL服务

news2024/11/15 21:36:44

1. 概述

hidl基本知识可以参考官网
安卓官网-hidl
也讲解了C++和Java实现hidl
本文讲解C++Hal服务的创建

2. 文件的创建

aosp整编过的代码,可以直接choosecombo后使用hidl-gen工具。如果没有整编过,可以单编hidl-gen工具。
hidl-gen工具可以用来协助创建hidl。

Process FQNAME, PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?, to create output.

         -h: Prints this menu.
         -L <language>: The following options are available:
            check           : Parses the interface to see if valid but doesn't write any files.
            c++             : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.
            c++-headers     : (internal) Generates C++ headers for interface files for talking to HIDL interfaces.
            c++-sources     : (internal) Generates C++ sources for interface files for talking to HIDL interfaces.
            export-header   : Generates a header file from @export enumerations to help maintain legacy code.
            c++-impl        : Generates boilerplate implementation of a hidl interface in C++ (for convenience).
            c++-impl-headers: c++-impl but headers only.
            c++-impl-sources: c++-impl but sources only.
            c++-adapter     : Takes a x.(y+n) interface and mocks an x.y interface.
            c++-adapter-headers: c++-adapter but helper headers only.
            c++-adapter-sources: c++-adapter but helper sources only.
            c++-adapter-main: c++-adapter but the adapter binary source only.
            java            : (internal) Generates Java library for talking to HIDL interfaces in Java.
            java-constants  : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists).
            vts             : (internal) Generates vts proto files for use in vtsd.
            makefile        : (removed) Used to generate makefiles for -Ljava and -Ljava-constants.
            androidbp       : (internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.
            androidbp-impl  : Generates boilerplate bp files for implementation created with -Lc++-impl.
            hash            : Prints hashes of interface in `current.txt` format to standard out.
            function-count  : Prints the total number of functions added by the package or interface.
            dependencies    : Prints all depended types.
         -O <owner>: The owner of the module for -Landroidbp(-impl)?.
         -o <output path>: Location to output files.
         -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.
         -R: Do not add default package roots if not specified in -r.
         -r <package:path root>: E.g., android.hardware:hardware/interfaces.
         -v: verbose output.
         -d <depfile>: location of depfile to write to.

2.1 创建hal接口

三方创建的hal接口一般位于vendor/厂商名/interfaces下,然后每一个hidl模块创建一个子目录。
hal接口需要使用hidl中的数据类型,具体可参照安卓官网

package vendor.vendorname.hardware.hidltest@1.0;

interface ITest {
    add(int32_t a, int32_t b) generates (int32_t result);
};

package指定软件包,interface指定hal接口,接口的全限定名称其实是软件包::接口名。

2.2 hash值写入current.txt

current.txt记录interfaces中所有接口的hash值,hal接口编译的时候会判断hash值,如果hash值改变,就会编译失败。其目的在于不允许改变接口文件,可以升级接口版本,依赖最初的接口版本,然后把新版本接口的hash值插入current.txt文件中,实现版本迭代。

hidl-gen -L hash -r vendor.vendorname.hardware:vendor/vendorname/interfaces vendor.vendorname.hardware.hidltest@1.0 >> interfaces/current.txt

借助hidl-gen工具生成hash值,并写入current.txt文件中,生成的hash值示例如下:

bac86584fe7fb75f0ccf0bc956428031f69074edfac20c4bd4106ccd41514dab vendor.vendorname.hardware.hidltest@1.0::ITest

2.3 创建hal接口的bp文件

借助hidl-gen工具生成hal接口的bp文件

hidl-gen -L androidbp -r vendor.vendorname.hardware:vendor/vendorname/interfaces vendor.vendorname.hardware.hidltest@1.0

生成的Androi.bp文件如下

// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "vendor.vendorname.hardware.hidltest@1.0",
    root: "vendor.vendorname.hardware",
    product_specific: true,
    srcs: [
        "ITest.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}

product_specific: true指定生成的文件在product分区
root指定父路径,一般需要在interfaces路径下添加bp文件
vendor/vendorname/interfaces/Android.bp

hidl_package_root {
    name: "vendor.vendorname.hardware",
    path: "vendor/vendorname/interfaces",
}

subdir = [
    "*",
]

这里指定了hidl的根路径。

2.4 生成C++文件

hidl-gen -o vendor/vendorname/interfaces/hidltest/1.0/default -L c++-impl -r vendor.vendorname.hardware:vendor/vendorname/interfaces vendor.vendorname.hardware.hidltest@1.0

通过-o参数来指定生成文件的目录
在这里插入图片描述
生成了一个头文件和一个源文件
Test.h

// FIXME: your file license if you have one

#pragma once

#include <vendor/vendorname/hardware/hidltest/1.0/ITest.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace vendor {
namespace vendorname {
namespace hardware {
namespace hidltest {
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 Test : public ITest {
    // Methods from ::vendor::vendorname::hardware::hidltest::V1_0::ITest follow.
    Return<int32_t> add(int32_t a, int32_t b) override;

    // Methods from ::android::hidl::base::V1_0::IBase follow.

};

// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" ITest* HIDL_FETCH_ITest(const char* name);

}  // namespace implementation
}  // namespace V1_0
}  // namespace hidltest
}  // namespace hardware
}  // namespace vendorname
}  // namespace vendor

Test.cpp

// FIXME: your file license if you have one

#include "Test.h"

namespace vendor {
namespace vendorname {
namespace hardware {
namespace hidltest {
namespace V1_0 {
namespace implementation {

// Methods from ::vendor::vendorname::hardware::hidltest::V1_0::ITest follow.
Return<int32_t> Test::add(int32_t a, int32_t b) {
    // TODO implement
    //return int32_t {}; 原生生成的
    return a + b;
}


// Methods from ::android::hidl::base::V1_0::IBase follow.

//ITest* HIDL_FETCH_ITest(const char* /* name */) {
    //return new Test();
//}
//
}  // namespace implementation
}  // namespace V1_0
}  // namespace hidltest
}  // namespace hardware
}  // namespace vendorname
}  // namespace vendor

可以看到软件包名会转换成namespace,并将hal接口生成了对应的实现,我们可以在实现中进行修改。

2.5 创建源码的bp文件

hidl-gen -o vendor/vendorname/interfaces/hidltest/1.0/default -L androidbp-impl -r vendor.vendorname.hardware:vendor/vendorname/interfaces vendor.vendorname.hardware.hidltest@1.0

同样通过-o指定生成的bp文件跟C++文件在同一个目录
原生的bp文件

// FIXME: your file license if you have one

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: "vendor.vendorname.hardware.hidltest@1.0-impl",
    relative_install_path: "hw",
    // FIXME: this should be 'vendor: true' for modules that will eventually be
    // on AOSP.
    proprietary: true,
    srcs: [
        "Test.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "vendor.vendorname.hardware.hidltest@1.0",
    ],
}

默认是生成so文件的直通式hal,开发绑定式hal需要对此bp文件进行修改

// FIXME: your file license if you have one

cc_binary {
    name: "vendor.vendorname.hardware.hidltest@1.0-service",
    relative_install_path: "hw",
    defaults: ["hidl_defaults"],
    proprietary: true,
    srcs: [
        "Test.cpp",
        "service.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "libcutils",
        "liblog",
        "vendor.vendorname.hardware.hidltest@1.0",
    ],
    init_rc: [
        "vendor.vendorname.hardware.hidltest@1.0-service",
    ]
}

首先是改成cc_binary,让源代码编译成一个可执行文件。更改name,默认是生成直通式hal的impl结尾,结尾改成service。添加defaults导入hidl_defaults定义,里面有hidl相关定义。srcs添加service.cpp,并创建该文件在当前目录,后续介绍。shared_libs添加常用的so依赖。添加init_rc启动文件,后续介绍。
service.cpp

# define LOG_TAG "vendorname"

#include <android/log.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <vendor/vendorname/hardware/hidltest/1.0/ITest.h>
#include <stdio.h>
#include <unistd.h>
#include "Test.h"

using vendor::vendorname::hardware::hidltest::V1_0::ITest;
using vendor::vendorname::hardware::hidltest::V1_0::implementation::Test;
using android::sp;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;

int main() {
    ALOGI("begin vendorname hwbinder service");
    
    sp<ITest> instance = new Test();

    configureRpcThreadpool(1, true);

    android::status_t status = instance->registerAsService();
    if (status != android::OK)
    {
        ALOGE("Could not register vendorname Service!");
        return -1;
    }
    
    while(true) {
        ALOGI("vendorname hal service recycle");
        sleep(1);
    }
    
    joinRpcThreadpool();

    return 0;
}

service.cpp中的main函数是编译出的hal service二进制可执行文件的执行入口。而可执行文件的调用有rc文件负责。
rc文件

service hidltest_service vendor/bin/hw/vendor.vendorname.hardware.hidltest@1.0-service
    class hal
    user system
    group system

系统启动时,会加载读取rc文件,然后service这一行会使系统加载后面路径下的bin文件

3 编译产物

在interfaces目录下mm编译,编译完成后会在out/target/product/{brandname}/vendor生成以下产物
在这里插入图片描述
需要注意的是,整编的时候,并不能打入手机的版本中。需要添加

PRODUCT_PACKAGES += \
    vendor.vendorname.hardware.hidltest@1.0 \
    vendor.vendorname.hardware.hidltest@1.0-service

在device/coral/coral/device.mk中添加自定义mk文件,编译出错
在这里插入图片描述
由此看是编译通过了,需要解决编译无法打入版本的问题,这里看问题是对打进版本包的文件有限制。参考网上的解决方式,在envsetup.sh中添加环境变量

@@ -323,6 +323,8 @@ function setpaths()
     unset ANDROID_TARGET_OUT_TESTCASES
     export ANDROID_TARGET_OUT_TESTCASES=$(get_abs_build_var TARGET_OUT_TESTCASES)

+    export DISABLE_ARTIFACT_PATH_REQUIREMENTS="true"
+
     # needed for building linux on MacOS
     # TODO: fix the path
     #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include

如果是真机调试,发现刷机后手机中system下有了接口so文件,但是vendor下还是没有service。以pixel4xl为例,这是因为,真机刷机时需要下载谷歌的驱动,驱动解压到aosp的根目录,会使用一个固定的vendor.img镜像,而非是我们使用aosp编译的aosp镜像。流程如下
解压后的BoardConfig.mk中
device/google/coral/coral/BoardConfig.mk

include device/google/coral/BoardConfig-common.mk

device/google/coral/BoardConfig-common.mk

-include vendor/google_devices/coral/proprietary/BoardConfigVendor.mk

-include的意思是如果文件不存在,也不会报致命错误,而是所有加载完之后再重新检查,如果还是不存在,则报警告
vendor/google_devices/coral/proprietary/BoardConfigVendor.mk

ifneq ($(filter flame,$(TARGET_DEVICE)),)
-include vendor/google_devices/flame/BoardConfigPartial.mk
-include vendor/qcom/flame/BoardConfigPartial.mk
else
-include vendor/google_devices/coral/BoardConfigPartial.mk
-include vendor/qcom/coral/BoardConfigPartial.mk
endif

vendor/google_devices/coral/BoardConfigPartial.mk

BOARD_PREBUILT_VENDORIMAGE := vendor/google_devices/coral/proprietary/vendor.img

对比out目录下的vendor.img和该目录下的vendor.img的md5值,发现一样的。
如果想要定制自己的vendor镜像可参考博文
[Android]基于AOSP源码为Pixel3编译vendor.img
如果是手动加载,此时hal服务已经能够启动
但是对于开机自启动来说,并不能启动,开机加载hal服务的时候,需要给hal服务配置selinux规则,否则会启动失败。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6应用层-6.3【实验】【计算机网络】

6应用层-6.3【实验】【计算机网络】 前言推荐6应用层知识DHCP协议分析DHCP报文格式DHCP抓包分析 6.1 Web服务与FTP服务配置6.2 DNS域名系统配置6.3 DHCP动态协议参数配置实验目的实验内容及实验环境实验原理实验过程1.搭建网络环境2.配置路由器3.配置DSCP服务器4.完成右侧网络主…

20230627通过WPS给PPT幻灯片加入页码

20230627通过WPS给PPT幻灯片加入页码 2023/6/27 23:16 缘起&#xff1a;不想每次都手工给打印的PPT加页码&#xff0c;就通过百度搜索来自动加页码了&#xff01; 真是偷懒让人进步呀&#xff01; 百度搜索&#xff1a;ppt加页码怎么设置 方法步骤.png ?点击「插入」选项卡「幻…

C++(Day1)

思维导图 2.定义一个命名空间Myspace&#xff0c;包含以下函数&#xff1a;将一个字符串中的所有单词进行反转&#xff0c;并输出反转后的结果。例如&#xff0c;输入字符串为"Hello World"&#xff0c;输出结果为"olleH dlroW"&#xff0c;并在主函数内测…

GPT所想即所见的快速解惑

这是学习笔记的第 2464篇文章 在很多年前&#xff0c;自己脑袋里面冒出来这样的一段文字&#xff0c; 黑暗中一个孩子站在田野上看着另外一个孩子 就好像自己在看自己。 说是感慨也好&#xff0c;伤感也罢。那种画面感是一直难以名状的&#xff0c;最近试了下GPT&#xff0c;给…

7.用python写网络爬虫,验证码处理

前言 验证码&#xff08;CAPTCHA&#xff09;的全称为全自动区分计算机和人类的公开图灵测试&#xff08;Completely Automated Public Turing testtotellComputersand Humans Apart&#xff09;从其全称可以看出&#xff0c;验证码用 于测试用户是否为真实人类。一个典型的验证…

高速电路设计系列分享-熟悉JESD204B(下)

目录 概要 整体架构流程 技术名词解释 技术细节 1.物理层 小结 概要 随着高速ADC跨入GSPS范围&#xff0c;与FPGA(定制ASIC)进行数据传输的首选接口协JESD204B。为了捕捉频率范围更高的RF频谱&#xff0c;需要宽带RFADC。在其推动下&#xff0c;对于能够捕捉更宽带宽并支持配置…

eclipse配置tomcat

一、为什么要配置tomcat &#xff1f; Eclipse是一款非常流行的Java开发集成环境&#xff08;IDE&#xff09;&#xff0c;它主要用于开发Java语言相关的应用程序。而Tomcat则是一个流行的开源Web服务器&#xff0c;也是一个Servlet容器。 在Java Web应用程序的开发过程中&…

有哪些免费好用的Python IDE(集成开发环境)?

工欲善其事&#xff0c;必先利其器。Python的学习过程少不了集成开发编辑环境(IDE)。这些Python IDE会提供插件、工具等帮助开发者加快使用Python开发的速度&#xff0c;提高效率。这里收集了一些对开发者非常有帮助的Python IDE(来自hittp://doc.okbase.net/havoc/archive/242…

【CGAL】Clion+vcpkg+MacOS M2

安装brew 链接如下&#xff1a; MacBook使用笔记&#xff1a;安装Homebrew&#xff08;M1&#xff09; - 知乎 打开mac终端&#xff0c;输入&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 这个是国内镜…

【Java面试题】设计模式

文章目录 设计模式你知道哪些?工厂模式单例模式★★★适配器模式代理模式定义作用静态代理动态代理★★★ 观察者模式★★★责任链模式 设计模式你知道哪些? ​ 创建型模式&#xff08;Creational Pattern&#xff09;&#xff1a;对类的实例化过程进行了抽象&#xff0c;能…

vegeta压测工具源码修改, 增加 摸高模式

在pacer.go中增加如下代码. pacer接口实现类作用就是控制吞吐量, 什么时间吞吐量多少. 摸高模式(梯度加压)效果如下 type HighTouchPacer struct {StartAt RateSlope float64HighTouchTimes float64PerHighTouchDuration float64PerStayDu…

uniapp 封装 navbar tabbar

最近换了一家公司工作 因为上家公司老板给的钱不多 还特别会压榨员工 好了好了&#xff0c;不扯皮了 1、封装navbar&#xff1a; 首先需要在pages.json中将对应页面的原生navbar给取消 举例&#xff1a; {"pages": [{"path" : "pages/home/inde…

Windows 10 首次RDP提示需要修改密码的处理方式

有一台Windows 10 的机器&#xff0c; 系统管理员给了一个RDP账号和密码&#xff0c; 使用这个账号远程登录这台机器&#xff0c; 在命令行输入 mstsc 命令&#xff0c;输入用户名密码之后却无法正常登入&#xff0c; 提示要修改密码&#xff0c; 提示的信息如下&#xff1a;…

《计算机系统与网络安全》 第三章 网络攻击预防与技术

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【Android】跨端安全小计

前言 在挖移动端的时候&#xff0c;通常会关注跨端方向的问题&#xff0c;因为我们能直接从webview容器去访问native的代码&#xff0c;从客户端角度&#xff0c;从前端能直接深入到客户端&#xff0c;所以跨端这块比较有研究意义。 本文详细介绍android前端到客户端跨端通信…

用pytorch进行BERT文本分类

BERT 是一个强大的语言模型&#xff0c;至少有两个原因&#xff1a; 它使用从 BooksCorpus &#xff08;有 8 亿字&#xff09;和 Wikipedia&#xff08;有 25 亿字&#xff09;中提取的未标记数据进行预训练。顾名思义&#xff0c;它是通过利用编码器堆栈的双向特性进行预训练…

集合专题----set篇

1、Set 接口和常用方法 &#xff08;1&#xff09;Set 接口基本介绍 ① 无序&#xff08;添加和去除的顺序不一致&#xff09;&#xff0c;没有索引&#xff1b; ② 不允许重复元素&#xff0c;所以最多包含一个null&#xff1b; &#xff08;2&#xff09;Set 接口的常用方…

自动驾驶开源数据集(附下载链接)

自动驾驶是带动新兴产业的一个突破点&#xff0c;也是中国结合新能源汽车&#xff0c;实现汽车产业弯道超车的不二手段&#xff0c;是打破国外燃油车技术壁垒的关键一步&#xff01;它不会停止&#xff0c;只是在蓄势待发&#xff01; 数据集介绍&#xff1a;点击 自动驾驶场…

java进阶—通俗易懂线程池的概念(底层原理)及使用

前言 首先&#xff0c;我们知道创建一个线程 可以直接 使用 new Thread(() ->{}).start();这种形式来创建&#xff0c;当线程的run 方法执行结束&#xff0c;线程就终止了&#xff0c;线程对象就会被垃圾回收机制&#xff08;GC&#xff09;释放 然而在我们 开发工作中&…

智安网络|攻防演练对抗:网络边界自动化防御的关键

在当今高度互联的数字世界中&#xff0c;网络安全的重要性日益凸显。为了应对不断增长的网络威胁&#xff0c;组织和企业需要采取主动的防御策略&#xff0c;其中攻防演练对抗和自动化防御在保护网络边界方面扮演着重要的角色。本文将探讨攻防演练对抗的意义&#xff0c;并介绍…