首页 > 其他分享 >aidl实现hal

aidl实现hal

时间:2024-05-22 18:09:39浏览次数:24  
标签:hal AIDL aidl 实现 hardware hongxi android include

Stable AIDL HAL 实战
背景:
官方:https://source.android.com/devices/architecture/aidl/aidl-hals.

Google 在Android 11引入了AIDL for HALs,旨在代替HIDL原先的作用。在之后的Android版本推荐使用AIDL 实现Hal层的访问。
这样做的原因,应该有以下几点:

AIDL比HIDL存在的时间更长(仅从Android 8到Android 10),并在许多其他地方使用,如Android框架组件之间或应用程序中。既然AIDL具有稳定性支持,就可以用单一的IPC方式从HAL到框架进程或者应用进程。
AIDL还有一个比HIDL更好的版本控制系统。
再详细的展开说就是:

AIDL 更成熟,使用更广泛,如果HAL层也使用了AIDL的方式,那么就可以直接从应用进程调用到HAL 进程,以前使用HIDL的时候实现应用进程访问HAL的服务,需要在system server进程的中介。来个图:

以前使用HIDL的方式,如果后续vendor HAL version需要迭代升级,那么就需要再创建一个子目录,过程中实际上做很多的重复工作,冗余而效率不高。
值得注意的是:在HAL 层使用AIDL必须使用Stable AIDL, 和我们在应用层或者框架层稍微不同,因为和vendor的接口设计要兼顾稳定性,system和vendor的更新速率不一样。

HALs using AIDL to communicate between framework components must use Stable AIDL.

使用AIDL for HALs
1. 定义HAL接口
创建对应的模块目录:/hardware/interfaces/hongxi/aidl/
创建aidl文件:/hardware/interfaces/hongxi/aidl/android/hardware/hongxi/IHongxi.aidl

package android.hardware.hongxi;

@VintfStability
interface IHongxi {
String getName();

void setName(in String msg);
}

 

每个类型定义都必须使用@VintfStability进行注释。
如果想要定义类型,参考同用的AIDL的定义就行,同时比通用的AIDL多了枚举、结构体、parcelable类型(注意这些类型跟Android版本有关,13以下的版本不一定有全)

2. 配置Android.bp
创建顶层Android.bp:/hardware/interfaces/hongxi/aidl/Android.bp

aidl_interface {
   name: "android.hardware.hongxi",
   vendor: true,
   srcs: ["android/hardware/hongxi/*.aidl"],
   stability: "vintf",
   owner: "hongxi.zhu",
   backend: {
       cpp: {
           enabled: false,
       },
       java: {
              enabled: false,
       },
   },
}

 

backend: 服务的后端,AIDL支持四种后端,分别是C++/JAVA/NDK/RUST, 我们将使用NDK(谷歌推荐),因此将CPP和JAVA后端声明为false

使用java的话会生成jar,apk可以直接引用 out\soong\.intermediates\hardware\interfaces\hongxi\aidl\android.hardware.hongxi-V1-java\android_common\javac\android.hardware.hongxi-V1-java.jar

java: {
            sdk_version: "module_current",
              
       },

 

为了方便测试,设置vendor:true并删除vendor_available,因为这是一个自定义供应商HAL,删除vndk部分,因此这个HAL仅位于vendor分区,不受VNDK限制,真正开发中,如需开启需要自己解决VNDK的限制问题,这里就不单独列出。

3. 编译模块
mmm hardware/interfaces/hongxi/


然后就会报错:

[ 74% 227/303] echo "API dump for the current version of AIDL interface android.hardware.hongxi does not exist." && echo Run "m android.hardware.hongxi-update-api", or add "unstable: true" to the build ru
FAILED: out/soong/.intermediates/hardware/interfaces/hongxi/aidl/android.hardware.hongxi-api/checkapi_current.timestamp
echo "API dump for the current version of AIDL interface android.hardware.hongxi does not exist." && echo Run "m android.hardware.hongxi-update-api", or add "unstable: true" to the build rule for the inte
rface if it does not need to be versioned && false
API dump for the current version of AIDL interface android.hardware.hongxi does not exist.
Run m android.hardware.hongxi-update-api, or add unstable: true to the build rule for the interface if it does not need to be versioned
19:29:13 ninja failed with: exit status 1

原因是当前版本没有这个接口,需要更新下API,按照提示来:

m android.hardware.hongxi-update-api

然后再重新编译模块:

mmm hardware/interfaces/hongxi/

4. 实现HAL 接口
We will use the ndk_platfrom library, therefore, let check the generated code for ndk_platform.我们需要在实现的接口编译脚本中引用模块的ndk_platfrom, 且我们要实现的接口在编译时都生成了对应的源码,我们只需要拷贝出来并实现,所以先看下,刚才的编译都生成了什么:

cd out/soong/.intermediates/hardware/interfaces/hongxi/aidl/android.hardware.hongxi-V1-ndk-source
find .
.
./gen
./gen/android
./gen/android/hardware
./gen/android/hardware/hongxi
./gen/android/hardware/hongxi/IHongxi.cpp.d
./gen/android/hardware/hongxi/IHongxi.cpp
./gen/include
./gen/include/aidl
./gen/include/aidl/android
./gen/include/aidl/android/hardware
./gen/include/aidl/android/hardware/hongxi
./gen/include/aidl/android/hardware/hongxi/BpHongxi.h
./gen/include/aidl/android/hardware/hongxi/BnHongxi.h
./gen/include/aidl/android/hardware/hongxi/IHongxi.h
./gen/timestamp

在IHongxi.h头文件中找到我们要实现的接口:

virtual ::ndk::ScopedAStatus getName(std::string* _aidl_return) = 0;
virtual ::ndk::ScopedAStatus setName(const std::string& in_msg) = 0;

接下来就需要创建后端源码文件,来实现这些接口:
/hardware/interfaces/hongxi/aidl/default/Hongxi.h

#pragma once

#include <aidl/android/hardware/hongxi/BnHongxi.h>

namespace aidl {
namespace android {
namespace hardware {
namespace hongxi {

class Hongxi : public BnHongxi {
    public:
        //String getName();
        ndk::ScopedAStatus getName(std::string* _aidl_return);

        //void setName(in String msg);
        ndk::ScopedAStatus setName(const std::string& in_msg);

    private:
        std::string name = "";
};

}  // namespace hongxi
}  // namespace hardware
}  // namespace android
}  // namespace aidl

 

/hardware/interfaces/hongxi/aidl/default/Hongxi.cpp

#define LOG_TAG "Hongxi"

#include <utils/Log.h>
#include <iostream>
#include "Hongxi.h"

namespace aidl {
namespace android {
namespace hardware {
namespace hongxi {

ndk::ScopedAStatus Hongxi::getName(std::string* _aidl_return) {

    *_aidl_return = name;

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Hongxi::setName(const std::string& in_msg) {

    name = in_msg;

    return ndk::ScopedAStatus::ok();
}

}  // namespace hongxi
}  // namespace hardware
}  // namespace android
}  // namespace aidl

 

 

5. 实现服务:
/hardware/interfaces/hongxi/aidl/default/main.cpp

#define LOG_TAG "Hongxi"

#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include "Hongxi.h"

using aidl::android::hardware::hongxi::Hongxi;
using std::string_literals::operator""s;

int main() {
    // Enable vndbinder to allow vendor-to-venfor binder call
    android::ProcessState::initWithDriver("/dev/vndbinder"); //使用vnbinder的配置

    ABinderProcess_setThreadPoolMaxThreadCount(0); // vnbinder的线程池独立,需要单独配置 
    ABinderProcess_startThreadPool();

    std::shared_ptr<Hongxi> hongxi = ndk::SharedRefBase::make<Hongxi>();
    const std::string desc = Hongxi::descriptor + "/default"s;

    if (hongxi != nullptr) {
        if(AServiceManager_addService(hongxi->asBinder().get(), desc.c_str()) != STATUS_OK) {
            ALOGE("Failed to register IHongxi service");
            return -1;
        }
    } else {
        ALOGE("Failed to get IHongxi instance");
        return -1;
    }

    ALOGD("IHongxi service starts to join service pool");
    ABinderProcess_joinThreadPool();

    return EXIT_FAILURE;  // should not reached
}

 

 

8. 编写服务启动的rc脚本
/hardware/interfaces/hongxi/aidl/default/android.hardware.hongxi-service.rc

service android.hardware.hongxi-service /vendor/bin/hw/android.hardware.hongxi-service
        interface aidl android.hardware.hongxi.IHongxi/default
        class hal
        user system
        group system

 


9. 声明VINTF AIDL 接口
/hardware/interfaces/hongxi/aidl/default/android.hardware.hongxi-service.xml

<manifest version="1.0" type="device">
    <hal format="aidl">
        <name>android.hardware.hongxi</name>
        <fqname>IHongxi/default</fqname>
    </hal>
</manifest>

 

7. 编写服务构建脚本
/hardware/interfaces/hongxi/aidl/default/Android.bp

cc_binary {
    name: "android.hardware.hongxi-service",
    vendor: true,
    relative_install_path: "hw",
    init_rc: ["android.hardware.hongxi-service.rc"],
    vintf_fragments: ["android.hardware.hongxi-service.xml"],

    srcs: [
        "Hongxi.cpp",
        "main.cpp",
    ],

    cflags: [
        "-Wall",
        "-Werror",
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libhardware",
        "libbinder_ndk",
        "libbinder",
        "libutils",
        "android.hardware.hongxi-V1-ndk",
    ],
}

 

 

将模块加入系统中
device\rockchip\rk356x\device.mk

# add for Hongxi
PRODUCT_PACKAGES += \
android.hardware.hongxi \
android.hardware.hongxi-service \

将模块添加到兼容性矩阵中
# (选下标最新的那个)
hardware/interfaces/compatibility_matrices/compatibility_matrix.5.xml
#(这个不一定有,如果没有就不加)
hardware/interfaces/compatibility_matrices/compatibility_matrix.current.xml

    <hal format="aidl" optional="true">
        <name>android.hardware.hongxi</name>
        <version>1.0</version>
        <interface>
            <name>IHongxi</name>
            <instance>default</instance>
        </interface>
    </hal>

 

解决Selinux权限
这个后续补充,测试中,会有宏版本和直接添加的版本

客户端测试
cpp-client(user process)
apk-client(user process)

app的libs引入jar包

 使用

IHongxi hongxi;
        IBinder binder = ServiceManager.getService(IINVCASE_AIDL_INTERFACE);
        if (binder == null) {
            Log.e(TAG, "Getting " + IINVCASE_AIDL_INTERFACE + " service daemon binder failed!");
        } else {
            hongxi = IHongxi.Stub.asInterface(binder);
            if (hongxi == null) {
                Log.e(TAG, "Getting IInvcase AIDL daemon interface failed!");
            } else {
                Log.d(TAG, "IInvcase AIDL daemon interface is binded!");
                try {
                    hongxi.setName("aaaa");
                } catch (RemoteException e) {
                    throw new RuntimeException(e);
                }
            }
        }

SystemService-client(system server process)

https://blog.csdn.net/qq_40731414/article/details/126823262

标签:hal,AIDL,aidl,实现,hardware,hongxi,android,include
From: https://www.cnblogs.com/wanglongjiang/p/18206824

相关文章

  • hidl实现hal
    一、前言正如AndroidHIDL概述一文中简单的对HIDL的演进和新架构下Framework与Hal层之间的通信做了介绍。但是笔者的目的是想完整的实现从上层APP到hal之间通信过程,由此可以更加深刻的理解这种机制。  二、BinderizedMode(绑定式)简介从上文介绍,我们......
  • 摸清自定义流程表单开发优点 实现降本增效!
    随着社会竞争压力的增大,很多企业都希望实现降本增效提质的办公效果。那么,借助什么样的软件平台可以让企业在提升市场竞争力的前提下,还能降低开发成本,提高成效?低代码技术平台是目前流行于中小企业办公职场中的平台产品,其中自定义流程表单开发优势特点多、灵活高效、可视化操作界面,......
  • python 实现公众号模板消息推送(亲测有效)
    APPID='xxxxxxxxx'APPSECRET='xxxxxxxxxxxxxx'response=requests.get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(APPID,APPSECRET))ACCESS_TOKEN=response.js......
  • 文件夹加密如何实现?如何保证加密后文件不会被他人查看?
    文件夹加密技术:确保数据安全的关键步骤在我们的数字生活中,个人和企业的敏感信息经常需要通过电子方式存储和传输。为了防止这些信息落入错误的手中,文件夹加密成为了一种重要的数据保护手段。文件夹加密不仅可以防止未授权访问,还能在信息传播过程中保障数据的完整性和机密性。但如......
  • [Unity] 单例基类的实现方式
    Unity单例基类的实现方式游戏开发的过程中我们经常会将各种“Manger”类设为单例,以实现单一资源的全局访问。Unity中的单例一般分为两类,一种是直接继承自Object的普通单例,还有一种是需要继承MonoBehaviour的Mono单例。接下来我将会讲解这两种单例基类的实现方式。注意:由于Unity......
  • 通过 adc 实现一个IO对多个按键读取
    如何实现一个IO对多个按键读取(1)当我们需要实现一个IO对多个按键读取的时候,可以采用如下电路,使用IO口的ADC功能,读取电压值,即可知道哪个按键被按下。(2)旁边加上一个10nf的电容,用于按键消抖......
  • CSS实现梯形
    1、这是结构代码,实现两个体形盒子对称<divclass="container"><divclass="box1"></div><divclass="box2"></div></div>2、这是CSS样式代码.container{width:400px;......
  • 德邦快递携手火山引擎,构建“数据飞轮”实现精准营销
     在快递行业中,数据的复杂性和多样性一直是企业面临的一大挑战。 在近日的采访中,德邦快递谈到通过引入火山引擎数智平台VeDI旗下系列数据产品,解决了长期困扰其营销活动的数据“黑盒”问题,显著提升了用户识别和营销效率,实现了月活用户和下单用户数的跃升。 德邦快递数字......
  • d3 v7树图实现动态边框,新增/编辑兄弟节点、子节点,删除节点和拖拽、缩放,动态边框
    d3版本:v7。PS:在用d3之前需要先了解SVG和CSS相关知识。树图生成部分和部分效果都是用SVG相关标签完成的。 效果图:  全部代码:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=devi......
  • 文件系统(四):FAT32文件系统实现原理
    FAT32是从FAT12、FAT16发展而来,目前主要应用在移动存储设备中,比如SD卡、TF卡。隐藏的FAT文件系统现在也有被大量使用在UEFI启动分区中。为使文章简单易读,下面内容特意隐藏了很多实现细节,关于分区、格式化等相关的内容,可以查看之前的文章:文件系统(一):存储介质、原理与架构文件系......