HIDL 语法学习

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 中:

  1. Make:LOCAL_SHARED_LIBRARIES += android.hardware.test@1.0

  2.  #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
  1. prebuilts/api/26.0/nonplat_sepolicy.cil
  2. prebuilts/api/28.0/private/compat/26.0/26.0.cil
  3. private/compat/26.0/26.0.cil
  4. #       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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值