Stable AIDL HAL 实战

背景:

官方:https://source.android.com/devices/architecture/aidl/aidl-hals.

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

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

再详细的展开说就是:

  1. AIDL 更成熟,使用更广泛,如果HAL层也使用了AIDL的方式,那么就可以直接从应用进程调用到HAL 进程,以前使用HIDL的时候实现应用进程访问HAL的服务,需要在system server进程的中介。来个图:
  2. 以前使用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,},},
}
  1. backend: 服务的后端,AIDL支持四种后端,分别是C++/JAVA/NDK/RUST, 我们将使用NDK(谷歌推荐),因此将CPP和JAVA后端声明为false(实际上我试了这两个,编译有问题,还没解决,后续解决了更新出来)。

  2. 为了方便测试,设置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-ndk_platform-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 callandroid::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-serviceinterface aidl android.hardware.hongxi.IHongxi/defaultclass haluser systemgroup 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-ndk_platform",],
}

将模块加入系统中

/build/target/product/base_vendor.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权限

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

客户端测试

  1. cpp-client(user process)
  2. apk-client(user process)
  3. SystemService-client(system server process)

AIDL for HALs实战相关推荐

  1. [Android]Android 下实现点亮 Led

    Android 下的实现点亮 led 1 准备驱动 1.1 修改设备树 在设备树中添加节点,在 / 节点下添加 led_test 节点,在 &iomuxc 节点下添加 led_test 的 p ...

  2. java aidl多线程_AIDL踩坑实战

    AIDL理论 AIDL(Android 接口定义语言)可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口. 在 Android 上,一个进程通常无法访问另一个进程的内 ...

  3. Android实战技术:深入理解Android的RPC方式与AIDL

    目录(?)[-] Understanding ADIL 揭开面纱 脱去外套 本质--脱去内衣 原理和内幕 不用AIDL来实现 Understanding ADIL AIDL是一个接口描述文件,用于实现 ...

  4. 调试系列2:bugreport实战篇

    原址 一.Bugreport 文章Bugreport源码篇(一)从源码角度阐释了Bugreport,那么本文则是从实战角度来说说,如何看懂bugreport,对于通过bugreport获取到内容往往非 ...

  5. Android R系统aidl文件怎么对应的java文件找不到了?

        Android R系统aidl文件怎么对应的java文件找不到了? 引言   Android系列博客沉寂很久了,很久了!不是我已经离开了江湖,而是最近忙着给OpenHarmony鸿蒙小系统,标 ...

  6. Android阿面试积累,android项目开发实战密码

    公差为1的等差数列求和,如何优化 自己的优势在哪里 注解如何获取,反射为何耗性能? Java的GC机制,分代回收策略 Binder机制:ServiceManager什么时候注册的? int,long的 ...

  7. Android项目实战--手机卫士35--清除程序缓存

    最新实战教程,让你了解Android自动化刷量.作弊与防作弊的那些事,案例:刷友盟统计.批量注册苹果帐号 因为一直忙着工作的事,也很久没有更新我们这个项目了,今天就给大家讲一下那个清除缓存的功能,其实 ...

  8. Android AIDL 传递对象(Parceable),深度解读Netty

    import xj.musicserver.MusicInfo; interface IPlayListener { /** Demonstrates some basic types that yo ...

  9. Android高级工程师技能知识储备,android实战项目源码

    二.显示 5.Ui(控件.事件处理) 窗口.视图 简单的基控件 复杂的组合控件 动画 事件及其传机制 三.存储 6.数据存储 Sharedpreferences Properties (java) F ...

最新文章

  1. Linux错误代码15872,Linux运维常用命令
  2. 实体链接(Entity Linking)、依存句法分析、成分句法树、词袋模型、文本向量空间模型(TF-IDF)、
  3. Python属性访问拦截器的用法
  4. 201117阶段二SQLite数据库
  5. 分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0
  6. 前端学习(3198):jsx语法规则2
  7. 开发技巧(3-1)Eclipse查找关键字
  8. android基础之TabSpec和TabHost
  9. java ojdbc 还需要装 oracle client 吗,ojdbc连接数据库
  10. python单例模式数据库连接池_《java设计模式》一文带你了解单例模式
  11. InDesign教程,如何更改字体和字体大小?
  12. ASP.NET 中的 SQL Server 应用服务数据库角色和视图
  13. MyBatis基础:MyBatis入门(1)
  14. kettle 教程(一):简介及入门
  15. 彩色图像灰度化 (RGB ⇒ Gray )(RGB ⇒ YUV)(Verilog)
  16. [python]一个特别好的学习python网站
  17. c1报考驾驶证网站php删除,c1驾驶证有违章,c1驾驶证免三种违章
  18. 待我君临天下,定许你一世繁华。
  19. 用C++做一个特小型恶意程序
  20. 通俗理解拉普拉斯算子(Laplace)

热门文章

  1. CS269I:Incentives in Computer Science 学习笔记 Lecture 12 对称信息和声誉系统
  2. Android路由的实现
  3. PTA-L2-028 秀恩爱分得快 (25分)
  4. 软件测试必备技能有哪些呢?
  5. 三星率先推出全球首款可3G上网Gear S智能手表
  6. 王者荣耀s22服务器未响应是什么意思,《王者荣耀》s22卡顿解决方法 s22更新后卡顿怎么办...
  7. Kindle Fire平板电脑为什么是7英寸?
  8. 推荐一款好用的截屏截色工具snipaste
  9. 互换奇偶位 (爱思创算法四)
  10. QTreeView复选框的实现