说明:aidl for HAL 这种机制,可以自动生成java代码,app调用可以获取中间过程的jar包,结合反射调用 ServiceManager.getService 方法,直接获取 HAL 服务,不再需要费力在framework层添加代码,方便快捷。
- 定义aidl接口
hardware/interfaces/test/aidl/android/hardware/test/ITest.aidl
java
package android.hardware.test;
@VintfStability
interface ITest {
String getMsg();
void setMsg(in String msg);
}
- 创建Android.bp
hardware/interfaces/test/aidl/Android.bp
java
aidl_interface {
name: "android.hardware.test",
vendor: true,
srcs: ["android/hardware/test/*.aidl"],
stability: "vintf",
owner: "test",
backend: {
cpp: {
enabled: true,
},
java: {
platform_apis: true,
},
ndk: {
enabled: true,
}
},
}
- 编译
mmm hardware/interfaces/test/
- 编译报错,根据提示重新编译生成 aidl api
m android.hardware.test-update-api
- 生成成功后重新编译
mmm hardware/interfaces/test/
编译成功
- 实现HAL接口
hardware/interfaces/test/aidl/default/Test.h
cpp
#pragma once
#include <aidl/android/hardware/test/BnTest.h>
namespace aidl {
namespace android {
namespace hardware {
namespace test{
class Test: public BnTest {
public:
//String getMsg();
ndk::ScopedAStatus getMsg(std::string* _aidl_return);
//void setMsg(in String msg);
ndk::ScopedAStatus setMsg(const std::string& msg);
private:
std::string message = "";
};
} // namespace test
} // namespace hardware
} // namespace android
} // namespace aidl
hardware/interfaces/test/aidl/default/Test.cpp
cpp
#define LOG_TAG "Test"
#include <utils/Log.h>
#include <iostream>
#include "Test.h"
namespace aidl {
namespace android {
namespace hardware {
namespace test{
ndk::ScopedAStatus Test::getMsg(std::string* _aidl_ret) {
*_aidl_ret = message;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Test::setMsg(const std::string& msg) {
message = msg;
return ndk::ScopedAStatus::ok();
}
} // namespace test
} // namespace hardware
} // namespace android
} // namespace aidl
- 添加服务
hardware/interfaces/test/aidl/default/main.cpp
cpp
#define LOG_TAG "Test"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include "Test.h"
using aidl::android::hardware::test::Test;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
ABinderProcess_startThreadPool();
std::shared_ptr<Test> test = ndk::SharedRefBase::make<Test>();
const std::string desc = std::string() + Test::descriptor + "/default";
if (test != nullptr) {
if(AServiceManager_addService(test->asBinder().get(), desc.c_str()) != STATUS_OK) {
return -1;
}
} else {
return -1;
}
ABinderProcess_joinThreadPool();
return EXIT_FAILURE;
}
- init rc
hardware/interfaces/test/aidl/default/android.hardware.test-service.rc
cpp
service android.hardware.test-service /vendor/bin/hw/android.hardware.test-service
interface aidl android.hardware.test.ITest/default
class hal
user system
group system
- manifest
hardware/interfaces/test/aidl/default/android.hardware.test-service.xml
cpp
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.test</name>
<version>1</version>
<interface>
<name>ITest</name>
<instance>default</instance>
</interface>
</hal>
</manifest>
- 编译脚本
hardware/interfaces/test/aidl/default/Android.bp
cpp
cc_binary {
name: "android.hardware.test-service",
vendor: true,
relative_install_path: "hw",
init_rc: ["android.hardware.test-service.rc"],
vintf_fragments: ["android.hardware.test-service.xml"],
srcs: [
"Test.cpp",
"main.cpp",
],
shared_libs: [
"liblog",
"libbase",
"libbinder_ndk",
"android.hardware.test-V1-ndk_platform",
],
}
- 参与编译
device\xxx\xxx\project.mk
cpp
PRODUCT_PACKAGES += \
android.hardware.test \
android.hardware.test-service
- 模块添加到兼容性矩阵中
hardware/interfaces/compatibility_matrices/compatibility_matrix.x.xml
hardware/interfaces/compatibility_matrices/compatibility_matrix.current.xml
cpp
<hal format="aidl" optional="true">
<name>android.hardware.test</name>
<version>1</version>
<interface>
<name>ITest</name>
<instance>default</instance>
</interface>
</hal>
- 解决selinux的问题
参考:Android12 AIDL native层实现_android native aidl-CSDN博客
-
编译,烧录
-
测试:
开机后,先看看服务是否起来 adb shell "service list | grep test"
C++ 测试在这里忽略,参考:Android12 AIDL native层实现_android native aidl-CSDN博客
- java 测试
取出 out\soong\.intermediates\hardware\interfaces\test\aidl\android.hardware.test-V1-java\android_common\javac下的jar包,放到android工程里边。
由于android.os.ServiceManager是个隐藏类,我们用反射
cpp
public static IBinder getService(String name) {
try {
Class<?> c = Class.forName("android.os.ServiceManager");
Method getService = c.getMethod("getService", String.class);
return (IBinder) getService.invoke(c, name);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
java 测试代码:
cpp
IBinder binder = getService("android.hardware.test.ITest/default");
ITest test = ITest.Stub.asInterface(binder);
Log.d("TestHal", "binder: " + test);
try {
test.setMsg("test message");
String msg = test.getMsg();
Log.d("TestHal", "HAL message: " + msg);
} catch (Exception e) {
e.printStackTrace();
}
>> 为什么 getService 是 android.hardware.test.ITest/default 这个可以用 service list | grep test 获取。
这是在 aidl 服务实现时候 add service 时候传入的:
const std::string desc = std::string() + Test::descriptor + "/default";
>> 另外 selinux 的解决,可以参考:
SELinux 权限问题调试_audit(0.0:343): avc: denied { create }-CSDN博客
>> 在apk导入framework.jar的方式调用 ServiceManager
在 libs 同级目录下创建 libsconly 把 framework.jar 放入,build.gradle 添加:
compileOnly fileTree(dir: 'libsconly', include: ['*.jar'])
sync 之后就可以使用 android.os.ServiceManager 的静态方法了。
参考:RK3568 Android11 增加HAL层的AIDL_android hal aidl-CSDN博客
感谢参考文献的各位,算是在 Android 12 上跑通了。