1、创建相关的目录hal目录及aidl存放目录
~/nx563j_xiaomi$ mkdir hardware/interfaces/mytest
~/nx563j_xiaomi$ cd hardware/interfaces/mytest/
这个是hal工程根目录
接下来要创建aidl的文件存放目录
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest$ mkdir aidl
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest$ cd aidl/
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl$ mkdir -p android/hardware/mytest
注意mkdir -p android/hardware/mytest其实就是包名目录,即模块包名就是android.hardware.mytest.
提示:这个如果为了项目的更加好的维护性建议到自己项目目标的vendor下面进行,目前只是为了演示方便,直接在system的hardware下面
2、创建定义对应aidl文件
创建最重要的aidl接口文件,需要在第一步创建的目录下
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl/android/hardware/mytest$ touch IMyTest.aidl
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl/android/hardware/mytest$ touch MyTestObj.aidl
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl$ tree
.
`-- android
`-- hardware
`-- mytest
|-- IMyTest.aidl
`-- MyTestObj.aidl
编写aidl内容:
IMyTest.aidl
package android.hardware.mytest;
import android.hardware.mytest.MyTestObj;
@VintfStability
interface IMyTest {
MyTestObj test();
}
MyTestObj.aidl
package android.hardware.mytest;
@VintfStability
parcelable MyTestObj {
String key;
int value;
}
其实和普通的aidl基本一样,唯一差别就是要多一些稳定性的声明比如@VintfStability这个注解官方解释如下:
VintfStability
VintfStability declares that a user-defined type (interface, parcelable, and enum) can be used across the system and vendor domains.
还是就是parcelable都是需要进行结构化,成员属性写清楚到aidl
3、编写顶层aidl的Android.bp
最开始的aidl目录创建一个Android.bp
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl$ touch Android.bp
Android.bp
aidl_interface {
name: "android.hardware.mytest",
vendor_available: true,
srcs: ["android/hardware/mytest/*.aidl"],
stability: "vintf",
owner:"qianli.ma",
backend: {
cpp: {
enabled: false,
},
java: {
sdk_version: "module_current",
},
},
}
需要注意以下几个点:
1、要写aidl_interface目标
2、设置成 vendor_available: true即代表vendor和system都可以用,不是vendor独享
3、stability: “vintf” stability保证接口是稳定的属性,目前只支持vintf
4、backend 这里的后端有4个,C++/JAVA/NDK/RUST, 我们将使用NDK和java,因此将CPP声明为false,为啥不使用c++呢?为啥出来个ndk呢?这个google官方给出了解释
https://source.android.google.cn/docs/core/architecture/aidl/aidl-hals#choosing-runtime
Building against the AIDL runtime
AIDL has three different backends: Java, NDK, CPP. To use Stable AIDL, you must always use the system copy of libbinder at system/lib*/libbinder.so and talk on /dev/binder. For code on the vendor image, this means that libbinder (from the VNDK) cannot be used: this library has an unstable C++ API and unstable internals. Instead, native vendor code must use the NDK backend of AIDL, link against libbinder_ndk (which is backed by system libbinder.so), and link against the -ndk_platform libraries created by aidl_interface entries.
大概意思就是一般aidl的vendor和system跨进程中不使用libbinder的包,因为一般vendor使用是vndk下面的包,故无法访问dev/binder,访问其实是dev/vndbinder,所有一般使用是NDK
4、编译接口文件
编译命令:
test@test:~/nx563j_xiaomi$ mmm hardware/interfaces/mytest
但是出现如下错误
[ 62% 200/319] echo "API dump for the current version of AIDL interface android.hardware.mytest does not exist." && echo Run "m android.hardware.mytest-update-api", or add "unstable: true" to the build r
FAILED: out/soong/.intermediates/hardware/interfaces/mytest/aidl/android.hardware.mytest-api/checkapi_current.timestamp
echo "API dump for the current version of AIDL interface android.hardware.mytest does not exist." && echo Run "m android.hardware.mytest-update-api", or add "unstable: true" to the build rule for the int
erface if it does not need to be versioned && false # hash of input list: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
API dump for the current version of AIDL interface android.hardware.mytest does not exist.
Run m android.hardware.mytest-update-api, or add unstable: true to the build rule for the interface if it does not need to be versioned
12:38:45 ninja failed with: exit status 1
#### failed to build some targets (01:04 (mm:ss)) ####
大概意思我们的接口是不存在的需要更新api执行:
m android.hardware.mytest-update-api
下面执行新的编译命令:
m android.hardware.mytest-update-api
成功后如下打印
out/soong/Android-lineage_nx563j.mk was modified, regenerating...
[100% 190/190] //hardware/interfaces/mytest/aidl:android.hardware.mytest-api Updating AIDL API dump version current for android.hardware.mytest (see hardware/interfaces/mytest/aidl/aidl_api/android.hardw
#### build completed successfully (06:57 (mm:ss)) ####
此时的目录已经被生成了aidl_api目录
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest$ tree
.
`-- aidl
|-- Android.bp
|-- aidl_api
| `-- android.hardware.mytest
| `-- current
| `-- android
| `-- hardware
| `-- mytest
| |-- IMyTest.aidl
| `-- MyTestObj.aidl
`-- android
`-- hardware
`-- mytest
|-- IMyTest.aidl
`-- MyTestObj.aidl
然后在进行刚才的编译
test@test:~/nx563j_xiaomi$ mmm hardware/interfaces/mytest
成功后会有如下打印
============================================
[100% 128/128] Install: out/target/product/nx563j/system/framework/android.hardware.mytest-V1-java.jar
#### build completed successfully (03:20 (mm:ss)) ####
这里主要是在编译相关目录生成相关接口代码和库,具体路径如下:
test@test:~/nx563j_xiaomi/out/soong/.intermediates/hardware/interfaces/mytest/aidl$ ls -l
total 20
drwxrwxr-x 3 test test 4096 Dec 12 13:07 android.hardware.mytest-V1-java
drwxrwxr-x 3 test test 4096 Dec 12 13:07 android.hardware.mytest-V1-java-source
drwxrwxr-x 16 test test 4096 Dec 12 13:07 android.hardware.mytest-V1-ndk
drwxrwxr-x 3 test test 4096 Dec 12 13:07 android.hardware.mytest-V1-ndk-source
drwxrwxr-x 3 test test 4096 Dec 12 13:07 android.hardware.mytest-api
test@test:~/nx563j_xiaomi/out/soong/.intermediates/hardware/interfaces/mytest/aidl$
因为bp中backend只对ndk和java有开放,c++已经关闭了
android.hardware.mytest-V1-ndk 代表aidl相关的库
android.hardware.mytest-V1-ndk-source 代表aidl相关的源文件比如一些头文件或者bp,bn文件
有了上面的生成代码和库,我们就可以写一个服务端的程序了
5、编写服务端程序代码
准备好相关的源文件和xml,rc配置文件
test@test:~/nx563j_xiaomi/hardware/interfaces/mytest/aidl/default$ tree
.
|-- Android.bp
|-- MyTestImpl.cpp
|-- MyTestImpl.h
|-- android.hardware.mytest.rc
|-- main.cpp
`-- mytest-default.xml
0 directories, 6 files
分为两部分:
源码部分
MyTestImpl.cpp —Binder服务端的具体实现部分cpp
#define LOG_TAG "MyTestImpl"
#define LOG_NDEBUG 0
#include "MyTestImpl.h"
#include <log/log.h>
#include <stdio.h>
namespace aidl::android::hardware::mytest {
::ndk::ScopedAStatus MyTestImpl::test(::aidl::android::hardware::mytest::MyTestObj* _aidl_return) {
*_aidl_return = mObj;
ALOGE(" MyTestImpl::test ok");
return ::ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::mytest
MyTestImpl.h—Binder服务端的具体实现部分头文件
#ifndef ANDROID_HARDWARE_MYTESTIMPL_H
#define ANDROID_HARDWARE_MYTESTIMPL_H
#include <aidl/android/hardware/mytest/BnMyTest.h>
namespace aidl::android::hardware::mytest {
class MyTestImpl : public BnMyTest {
public:
::aidl::android::hardware::mytest::MyTestObj mObj = {"hello",1};
::ndk::ScopedAStatus test(::aidl::android::hardware::mytest::MyTestObj* _aidl_return) override;
};
} // namespace aidl::android::hardware::mytest
#endif
main.cpp ----主程序入口cpp
#include "MyTestImpl.h"
#define LOG_TAG "MyTestImpl"
#define LOG_NDEBUG 0
#include <iostream>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <stdio.h>
using aidl::android::hardware::mytest::MyTestImpl;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<MyTestImpl> test = ::ndk::SharedRefBase::make<MyTestImpl>();
const std::string instance = std::string() + MyTestImpl::descriptor + "/default";
printf("MyTestImpl instance =%s sde =%p \n", instance.c_str(),test->asBinder().get());
binder_status_t status =
AServiceManager_addService(test->asBinder().get(), instance.c_str());
CHECK_EQ(status, STATUS_OK);
printf("MyTestImpl AServiceManager_addService status=%d \n", status);
fflush(stdout);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}
bp和配置文件部分
Android.bp --编译可执行文件的bp
cc_binary {
name: "android.hardware.mytest.example",
relative_install_path: "hw",
vendor: true,
init_rc: ["android.hardware.mytest.rc"],
vintf_fragments: ["mytest-default.xml"],
shared_libs: [
"android.hardware.mytest-V1-ndk",
"liblog",
"libbase",
"libcutils",
"libutils",
"libbinder_ndk",
],
srcs: [
"main.cpp",
"MyTestImpl.cpp",
],
}
android.hardware.mytest.rc --开机自启动
service vendor.mytest-default /vendor/bin/hw/android.hardware.mytest.example
class hal
user root
group root
mytest-default.xml ----声明接口到vintf中
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.mytest</name>
<version>1</version>
<interface>
<name>IMyTest</name>
<instance>default</instance>
</interface>
</hal>
</manifest>
然后再执行编译命令:
mmm hardware/interfaces/mytest/
出现如下成功提示:
aservices
============================================
[100% 10/10] Install: out/target/product/nx563j/vendor/bin/hw/android.hardware.mytest.example
#### build completed successfully (5 seconds) ####
到此基本上aidl业务模块就完成了,一个简单接口实现就好了
6、模块加入到兼容性矩阵中
应该添加到的目录即文件
hardware/interfaces/compatibility_matrices
test@test:~/nx563j_xiaomi/hardware/interfaces/compatibility_matrices$ ll
total 188
drwxrwxr-x 4 test test 4096 Dec 12 11:39 ./
drwxrwxr-x 54 test test 4096 Dec 12 11:43 ../
-rw-rw-r-- 1 test test 2764 Mar 4 2023 Android.bp
-rw-rw-r-- 1 test test 4860 Mar 4 2023 Android.mk
-rw-rw-r-- 1 test test 2440 Mar 4 2023 CleanSpec.mk
drwxrwxr-x 2 test test 4096 Mar 4 2023 build/
-rw-rw-r-- 1 test test 942 Mar 4 2023 clear_vars.mk
-rw-rw-r-- 1 test test 15448 Mar 4 2023 compatibility_matrix.3.xml
-rw-rw-r-- 1 test test 16709 Mar 4 2023 compatibility_matrix.4.xml
-rw-rw-r-- 1 test test 18568 Mar 4 2023 compatibility_matrix.5.xml
-rw-rw-r-- 1 test test 21273 Mar 4 2023 compatibility_matrix.6.xml
-rw-rw-r-- 1 test test 26116 Dec 12 11:39 compatibility_matrix.7.xml
-rw-rw-r-- 1 test test 26380 Dec 12 11:39 compatibility_matrix.current.xml
-rw-rw-r-- 1 test test 56 Mar 4 2023 compatibility_matrix.empty.xml
-rw-rw-r-- 1 test test 5349 Mar 4 2023 compatibility_matrix.mk
drwxrwxr-x 3 test test 4096 Mar 4 2023 exclude/
-rw-rw-r-- 1 test test 41 Mar 4 2023 manifest.empty.xml
这里应该选数字最大的7和current两个xml文件
compatibility_matrix.7.xml
compatibility_matrix.current.xml
2个文件加入如下内容:
<hal format="aidl">
<name>android.hardware.mytest</name>
<version>1</version>
<interface>
<name>IMyTest</name>
<instance>default</instance>
</interface>
</hal>
7、增加对应selinux权限
这里直接做成了一个patch方便大家直接apply
到system/sepolicy/然后apply下面这个patch
add-selinux.patch
commit 7b459a68fe188b9f051850ac0629c868a31de2c2
Author: Your Name <you@example.com>
Date: Sun Oct 8 10:03:22 2023 +0800
add selinux for hal mytest
Change-Id: I5feeec2aa30cd7fe0d306922225d512c10a0725e
diff --git a/prebuilts/api/33.0/private/hwservice_contexts b/prebuilts/api/33.0/private/hwservice_contexts
index 4a44dc58b..8092f0485 100644
--- a/prebuilts/api/33.0/private/hwservice_contexts
+++ b/prebuilts/api/33.0/private/hwservice_contexts
@@ -6,6 +6,7 @@ android.frameworks.schedulerservice::ISchedulingPolicyService u:object_r:fwk_s
android.frameworks.sensorservice::ISensorManager u:object_r:fwk_sensor_hwservice:s0
android.frameworks.stats::IStats u:object_r:fwk_stats_hwservice:s0
android.hardware.atrace::IAtraceDevice u:object_r:hal_atrace_hwservice:s0
+android.hardware.mytest::IMyTest u:object_r:hal_mytest_hwservice:s0
android.hardware.audio.effect::IEffectsFactory u:object_r:hal_audio_hwservice:s0
android.hardware.audio::IDevicesFactory u:object_r:hal_audio_hwservice:s0
android.hardware.authsecret::IAuthSecret u:object_r:hal_authsecret_hwservice:s0
diff --git a/prebuilts/api/33.0/private/service_contexts b/prebuilts/api/33.0/private/service_contexts
index 72fa16629..936638f18 100644
--- a/prebuilts/api/33.0/private/service_contexts
+++ b/prebuilts/api/33.0/private/service_contexts
@@ -15,6 +15,7 @@ android.hardware.contexthub.IContextHub/default u:object_r:
android.hardware.drm.IDrmFactory/clearkey u:object_r:hal_drm_service:s0
android.hardware.drm.ICryptoFactory/clearkey u:object_r:hal_drm_service:s0
android.hardware.dumpstate.IDumpstateDevice/default u:object_r:hal_dumpstate_service:s0
+android.hardware.mytest.IMyTest/default u:object_r:hal_mytest_service:s0
android.hardware.gnss.IGnss/default u:object_r:hal_gnss_service:s0
android.hardware.graphics.allocator.IAllocator/default u:object_r:hal_graphics_allocator_service:s0
android.hardware.graphics.composer3.IComposer/default u:object_r:hal_graphics_composer_service:s0
diff --git a/private/hwservice_contexts b/private/hwservice_contexts
index 4a44dc58b..8092f0485 100644
--- a/private/hwservice_contexts
+++ b/private/hwservice_contexts
@@ -6,6 +6,7 @@ android.frameworks.schedulerservice::ISchedulingPolicyService u:object_r:fwk_s
android.frameworks.sensorservice::ISensorManager u:object_r:fwk_sensor_hwservice:s0
android.frameworks.stats::IStats u:object_r:fwk_stats_hwservice:s0
android.hardware.atrace::IAtraceDevice u:object_r:hal_atrace_hwservice:s0
+android.hardware.mytest::IMyTest u:object_r:hal_mytest_hwservice:s0
android.hardware.audio.effect::IEffectsFactory u:object_r:hal_audio_hwservice:s0
android.hardware.audio::IDevicesFactory u:object_r:hal_audio_hwservice:s0
android.hardware.authsecret::IAuthSecret u:object_r:hal_authsecret_hwservice:s0
diff --git a/private/service_contexts b/private/service_contexts
index 72fa16629..936638f18 100644
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -15,6 +15,7 @@ android.hardware.contexthub.IContextHub/default u:object_r:
android.hardware.drm.IDrmFactory/clearkey u:object_r:hal_drm_service:s0
android.hardware.drm.ICryptoFactory/clearkey u:object_r:hal_drm_service:s0
android.hardware.dumpstate.IDumpstateDevice/default u:object_r:hal_dumpstate_service:s0
+android.hardware.mytest.IMyTest/default u:object_r:hal_mytest_service:s0
android.hardware.gnss.IGnss/default u:object_r:hal_gnss_service:s0
android.hardware.graphics.allocator.IAllocator/default u:object_r:hal_graphics_allocator_service:s0
android.hardware.graphics.composer3.IComposer/default u:object_r:hal_graphics_composer_service:s0
diff --git a/vendor/file_contexts b/vendor/file_contexts
index 392a750fd..b87914600 100644
--- a/vendor/file_contexts
+++ b/vendor/file_contexts
@@ -105,6 +105,7 @@
/(vendor|system/vendor)/bin/hw/wpa_supplicant u:object_r:hal_wifi_supplicant_default_exec:s0
/(vendor|system/vendor)/bin/install-recovery\.sh u:object_r:vendor_install_recovery_exec:s0
/(vendor|system/vendor)/bin/vndservicemanager u:object_r:vndservicemanager_exec:s0
+/(vendor|system/vendor)/bin/hw/android\.hardware\.mytest\.example u:object_r:hal_mytest_default_exec:s0
#############################
# Same process HALs installed by platform into /vendor
diff --git a/vendor/hal-aidl-mytest.te b/vendor/hal-aidl-mytest.te
new file mode 100644
index 000000000..378df3826
--- /dev/null
+++ b/vendor/hal-aidl-mytest.te
@@ -0,0 +1,39 @@
+# type hal_mytest, domain;
+# type hal_mytest_service, vendor_service, service_manager_type;
+# type hal_mytest_hwservice, hwservice_manager_type, protected_hwservice;
+# type hal_mytest_default_exec, exec_type, vendor_file_type, file_type;
+# init_daemon_domain(hal_mytest);
+
+
+
+# get_prop(hal_mytest, hwservicemanager_prop)
+# add_hwservice(hal_mytest, hal_mytest_hwservice)
+# hwbinder_use(hal_mytest);
+
+
+# allow platform_app hal_mytest_hwservice:hwservice_manager { find };
+# allow platform_app hal_mytest:binder {call};
+
+
+hal_attribute(mytest);
+type hal_mytest_default, domain, mlstrustedsubject;
+hal_server_domain(hal_mytest_default, hal_mytest);
+type hal_mytest_default_exec, exec_type, vendor_file_type, file_type;
+init_daemon_domain(hal_mytest_default);
+
+#Allow hwbinder call form hal client to server
+binder_call(hal_mytest_client, hal_mytest_default_exec)
+
+#add hwservice related rules
+type hal_mytest_service, vendor_service, service_manager_type;
+type hal_mytest_hwservice, hwservice_manager_type, protected_hwservice;
+get_prop(hal_mytest, hwservicemanager_prop)
+add_service(hal_mytest_default, hal_mytest_service)
+add_hwservice(hal_mytest_server, hal_mytest_hwservice)
+allow hal_mytest_client hal_mytest_hwservice:hwservice_manager find;
+hal_client_domain(system_server, hal_mytest)
+hwbinder_use(hal_mytest);
+
+allow hal_mytest_default servicemanager:binder { call transfer };
+allow { platform_app shell } hal_mytest_hwservice:hwservice_manager { find };
+allow { platform_app shell } hal_mytest:binder {call};
8、编写一个测试模块,来测试一下aidl的hal是否正常运行
aidl目录下创建一个test_hal目录:
test_hal/
|-- Android.bp
`-- main.cpp
Android.bp
cc_binary {
name: "test-hal-mytest",
shared_libs: [
"android.hardware.mytest-V1-ndk",
"liblog",
"libbase",
"libcutils",
"libutils",
"libbinder_ndk",
],
srcs: [
"main.cpp",
],
}
主要就是需要引入 “android.hardware.mytest-V1-ndk”, 这个依赖库
main.cpp
#define LOG_TAG "Test-HAL"
#define LOG_NDEBUG 0
#include <iostream>
#include <log/log.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <aidl/android/hardware/mytest/IMyTest.h>
#include <stdio.h>
using aidl::android::hardware::mytest::IMyTest;
int main() {
printf("test hal mytest main 1\n");
std::shared_ptr<IMyTest> service = IMyTest::fromBinder(ndk::SpAIBinder(AServiceManager_getService("android.hardware.mytest.IMyTest/default")));
printf("test hal mytest service = %p\n",service.get());
ALOGE("Test hal MyTest");
if (service == nullptr) {
return -1;
}
::aidl::android::hardware::mytest::MyTestObj obj;
service->test(&obj);
printf("test hal mytest main test result %s %d \n",obj.key.c_str(),obj.value);
fflush(stdout);
return EXIT_FAILURE; // should not reach
}
9、device下面加入相关的程序进入编译到整机
device/nubia/nx563j/device.mk文件中加入如下:
PRODUCT_PACKAGES += \
android.hardware.mytest \
android.hardware.mytest.example \
test-hal-mytest \
10、测试部分
测试方法
1、先看看是否mytest的hal服务是否开机自启动了
2、执行test-hal-mytest看看是否输出正常
文章来源:https://www.toymoban.com/news/detail-826710.html
本文章对应视频手把手教你学framework:
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
私聊作者+v(androidframework007)
点击这里 https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw
视频:https://www.bilibili.com/video/BV1wc41117L4/
文章来源地址https://www.toymoban.com/news/detail-826710.html
到了这里,关于hal深入剖析之aidl实战-android framework车机车载手机系统开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!