android 12 的 aidl for HAL 开发示例

说明:aidl for HAL 这种机制,可以自动生成java代码,app调用可以获取中间过程的jar包,结合反射调用 ServiceManager.getService 方法,直接获取 HAL 服务,不再需要费力在framework层添加代码,方便快捷。

  1. 定义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);
}
  1. 创建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,
        }
   },
}
  1. 编译

mmm hardware/interfaces/test/

  1. 编译报错,根据提示重新编译生成 aidl api

m android.hardware.test-update-api

  1. 生成成功后重新编译

mmm hardware/interfaces/test/

编译成功

  1. 实现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
  1. 添加服务

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;
}
  1. 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
  1. 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>
  1. 编译脚本

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",  
    ],
}
  1. 参与编译

device\xxx\xxx\project.mk

cpp 复制代码
PRODUCT_PACKAGES += \
    android.hardware.test \
    android.hardware.test-service
  1. 模块添加到兼容性矩阵中

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>
  1. 解决selinux的问题

参考:Android12 AIDL native层实现_android native aidl-CSDN博客

  1. 编译,烧录

  2. 测试:

开机后,先看看服务是否起来 adb shell "service list | grep test"

C++ 测试在这里忽略,参考:Android12 AIDL native层实现_android native aidl-CSDN博客

  1. 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 上跑通了。