HIDL 语法
HIDL语言类似于C(但不使用C预处理器)
/* / 表示文档注释.
/* */ 表示文档多行注释.
// 表示在一行结束后注释
[empty] 表明当前项的值为空
? 放置在项前,表明该项为可选项.
… 表明该序列包含0个或多个如前述使用分隔符隔开的项
, 逗号用于分隔序列中的元素
; 分号用于标记每个元素的结束位置.
@entry 当前HAL模块被使用时应当被最先调用的接口
@exit 当前HAL模块被调用时应当被最后调用的接口
@callflow(next={“name_a”, “name_b”, “name_c”}) 当前接口被调用后可能被调用的接口列表。其中name_a接口被调用的概率最大,name_c接口被调用的概率最小。如果只存在1个可能被调用的接口,那么花括号{ }可以省略不写。如果给定的接口名无效,则会导致VTS编译失败。
@callflow(next={“*”}) 当前接口被调用后可能会调用任意接口
usage: hidl-gen [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ [-t] fqname+
-r <package:path root>: E.g., android.hardware:hardware/interfaces.
hidl-gen F 07-15 17:59:31 23162 23162 Coordinator.cpp:211] Check failed: ret != mPackageRoots.end() Unable to find package root for vendor.rockchip.hardware.bk9531@1.0
hidl-gen -o vendor/rockchip/hardware/interfaces/bk9531/1.0/default -Lc++-impl -r rockchip.hardware:vendor/rockchip/hardware/interfaces -r android.hidl:system/libhidl/transport rockchip.hardware.bk9531@1.0
如果将package 放在Vendor目录下,对应的修改
hal callbackhal 文件名一定要一致,否则无法生成,调了好久
hidl-gen -o vendor/rockchip/hardware/interfaces/GdsunflyBsp/1.0/default -Landroidbp-impl -r rockchip.hardware:vendor/rockchip/hardware/interfaces -r android.hidl:system/libhidl/transport rockchip.hardware.GdsunflyBsp@1.0
// makefile 出错
hidl-gen -o vendor/rockchip/hardware/interfaces/bk9531/1.0/default -Lmakefile -r rockchip.hardware:vendor/rockchip/hardware/interfaces -r android.hidl:system/libhidl/transport rockchip.hardware.bk9531@1.0
hidl-gen -o vendor/rockchip/hardware/interfaces/GdsunflyBsp/1.0/default -Lhash -r rockchip.hardware:vendor/rockchip/hardware/interfaces -r android.hidl:system/libhidl/transport rockchip.hardware.GdsunflyBsp@1.0
reinterpret_cast
5.2 实现C++ 调用hidl service的例子
首先将 HAL 库添加到 makefile 中:
-
Make:LOCAL_SHARED_LIBRARIES += android.hardware.test@1.0
-
#define LOG_TAG "TEST_CLINET"
#include <android/hardware/test/1.0/ITest.h>
#include <log/log.h>
using android::hardware::test::V1_0::ITest;
using android::hardware::test::V1_0::LedStatus;
using android::hardware::test::V1_0::BrightnessRange;
using android::hardware::hidl_vec;
using android::sp;
int main(){
// BrightnessRange range;
sp<ITest> service = ITest::getService();
if( service == nullptr ){
ALOGE("Can't find ITest service...");
return -1;
}
ALOGE("ITest ON");
service->on();
ALOGE("ITest OFF");
service->off();
ALOGE("ITest set");
service->set(LedStatus::LED_ON);
ALOGE("ITest get");
LedStatus ret = service->get();
ALOGE("ITest get: %d",ret);
service->getBrightnessRange([](bool ret1,BrightnessRange range){
ALOGE("ITest getBrightnessRange ret: %d",ret1);
ALOGE("ITest getBrightnessRange Max: %d",range.max);
ALOGE("ITest getBrightnessRange Min: %d",range.min);
});
int32_t array[] = {5, 6, 7};
hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
bool ret2 = service->setBrightnessValue(hv1);
ALOGE("ITest getBrightnessValue bool: %d",ret2);
return 0;
}
hidl_vec<uint32_t> volumes;
volumes.resize(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
volumes[i] = 0;
}
vector<int> vec; //声明一个int型向量
vector<int> vec(8); //声明一个初始大小为8的int型向量
vector<int> vec(10, -1); //声明一个初始大小为10且值都是-1的int型向量
vector<int> vec{1, 2, 3, 4, 5}; //声明一个int型变量并依次赋值
vector<int> vec(tmp); //声明并用tmp向量初始化vec向量
vector<int> vec(temp.begin(), temp.begin()+3); //用向量temp的第0个到第2个值初始化vec向量
int arr[5] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5); //将arr数组的元素用于初始化vec向量
vector<int> vec(&arr[1], &arr[4]); //将arr[1]~arr[4]范围内的元素作为vec的初始值
vector<vector<int>> vec; //声明一个二维数组
vector<vector<int>> vec(4); //声明一个4行的二维数组
vector<vector<int>> vec(4, vector<int>(5,6)); //声明一个4行5列的二维数组并赋值维6
vector<vector<vector<int>>> a; //声明一个三维数组
vector<vector<vector<int>>> a(4); //声明一个三维数组,第一维度为4
编译错误及解决
Failed to resolve typeattributeset statement at system/sepolicy/private/compat/27.0/27.0.cil:1486 Failed to compile cildb: -2
解决方法:将nonplat_sepolicy.cil配置完毕
- \Android P_9.0\system\sepolicy\prebuilts\api\26.0\nonplat_sepolicy.cil
- prebuilts/api/26.0/nonplat_sepolicy.cil
- prebuilts/api/28.0/private/compat/26.0/26.0.cil
- private/compat/26.0/26.0.cil
- # modified: prebuilts/api/26.0/nonplat_sepolicy.cil
# modified: prebuilts/api/27.0/nonplat_sepolicy.cil
# modified: prebuilts/api/28.0/private/compat/26.0/26.0.cil
# modified: prebuilts/api/28.0/private/compat/27.0/27.0.cil
# modified: prebuilts/api/28.0/private/service_contexts
# modified: prebuilts/api/28.0/public/service.te
# modified: private/compat/26.0/26.0.cil
# modified: private/compat/27.0/27.0.cil
# modified: private/service_contexts
# modified: public/service.te
原文链接:https://blog.csdn.net/su749520/article/details/82800050
9、使用JAVA实现客户端调用
为了方便eclipse或者Android Studio调用接口函数,需要编译出classes.jar包。但是jack编译出来的文件是classes.jack。如图
/obj/JAVA_LIBRARIES/rockchip.hardware.bk9531-V1.0-java-static_intermediates$ ls
classes.jack
为了编译出classes.jar,需要打开hardware/interfaces/gunder/1.0目录的Android.mk,在include $(CLEAR_VARS)下面添加LOCAL_JACK_ENABLED := disabled。这样编译的时候就不走jack编译了。如下:
HIDL最全编译流程_u013357557的专栏-CSDN博客
一. 概述
AIDL和HIDL都是主要用于跨进程通信,本质是Binder通信。
总体流程都是先写.aidl文件或.hal文件,这个文件只有接口定义哦不是实现,然后利用工具自动生成代码,再利用生成的代码写具体接口的实现及调用。
二. 核心流程的核心理解
网上很多说不清楚,不要扯虚头巴脑的一堆,我说下核心流程:
先.aidl生成代码,比如 IMyAidlInterface.aidl 生成代码,server侧和client侧都要有哦,包名要一样。
Server侧:继承生成代码中的 IMyAidlInterface.Stub 类来实现接口,比如 class MyBinder extends IMyAidlInterface.Stub,因为 service 通信时候你要调用接口所以在 onBind() 中返回该类。
Client侧:onServiceConnected() 里获取刚才准备好的 MyBinder 类,iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service),调用接口的方式就直接 iMyAidlInterface.[接口] 就可以了。
对照我说的流程看一遍实际例子,你会透彻理解!最后部分我提供了优秀博客例子。
.hal 流程一样的,只不过不叫 Proxy 和 Stub ,而是叫 Bp 和 Bn。
三. 一些术语
对于AIDL生成java代码,客户端(client)对应 Proxy,服务端(server)对应 Stub。注意,也可生成c++代码,如今 framework 与 native 通信经常使用。
对于HIDL生成c++代码,客户端(client)对应 Bp(Binder Proxy),服务端(server)对应 Bn(Binder Native)。
本质一样。
可以这样理解,你要去银行存钱,你找个代理人去存,存在ATM里。你是client,银行是server,代理人是proxy,ATM是stub。钱需要是序列化数据Parcel。
原文链接:https://blog.csdn.net/weixin_36389889/article/details/125949031