RK3576 Android14 增加HAL层的AIDL

 参考文章:

AIDL for HALs实战_hidl会被aidl代替-优快云博客

Android 11 创建自定义AIDL HAL-优快云博客

Native AIDL (与hal通信)_hidl转aidl-优快云博客

Android的自启动_android 自启动-优快云博客

1. 定义HAL接口

创建对应的模块目录:/hardware/interfaces/testtld/aidl/
创建aidl文件:

hardware/interfaces/testtld/aidl/android/hardware/testtld/IHelloTest.aidl

package android.hardware.testtld;

 
@VintfStability
interface IHelloTest {
    int getTestOne(in int event, in String name);
}

 注意: 每个类型定义都必须使用@VintfStability进行注释。

2. 配置Android.bp

创建Android.bp:/hardware/interfaces/testtld/aidl/Android.bp

package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "hardware_interfaces_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["hardware_interfaces_license"],
}

aidl_interface {
    name: "android.hardware.testtld",
    vendor_available: true,
    srcs: ["android/hardware/testtld/*.aidl"],
    stability: "vintf",
    owner: "tld",
    backend: {
        cpp: {
            enabled: true,
        },
       java: {
            sdk_version: "module_current",
        },        
        ndk: {
            enabled: true,
        },
    },

    frozen: false,

}

  注意: 将owner设置为组织名称,此处不用加versions_with_info属性,后面编译完会自动生成,frozen会自动变成true 。vendor_available属性一定不能改成vendor,不然so文件不会在system文件下生成,只是在vendor下就引用不到了。

backend: 服务的后端,AIDL支持四种后端,分别是C++/JAVA/NDK/RUST, 我们将使用NDK(谷歌推荐),这里都加上会生成相应接口代码,因为后面C++和JAVA要调用。

3. 编译模块

首先前版本没有这个接口,需要更新下API,在项目跟目录下执行:

source build/envsetup.sh
lunch your target ##需要根据自己的实际情况进行选择
m  android.hardware.testtld-update-api

 执行成功后会生出current目录。

source build/envsetup.sh
lunch your target ##需要根据自己的实际情况进行选择
mmm hardware/interfaces/testtld

再次执行命令,系统会生出1的目录,并在bp文件里的自动添加版本属性frozen变成true。

source build/envsetup.sh
lunch your target ##需要根据自己的实际情况进行选择
mm  android.hardware.testtld-freeze-api 

4. 实现HAL 接口

在aidl目录下添加default目录及实现代码 , 目录结构如下

default
    ├── Android.bp
    ├── HelloTest.h
    │── HelloTest.cpp
    └── service.cpp
    └── HelloTest-default.rc
    └── HelloTest-default.xml
      

aidl/default/HelloTest.h

#include <aidl/android/hardware/testtld/BnHelloTest.h>

namespace aidl {

namespace android {

namespace hardware {

namespace testtld {



class HelloTest  : public BnHelloTest {
public:
    ndk::ScopedAStatus getTestOne(int32_t in_event, const std::string& in_name, int32_t* _aidl_return);
};


}  // namespace testtld

}  // namespace hardware

}  // namespace android

}  // namespace aild

aidl/default/HelloTest.cpp

#define LOG_TAG "android.hardware.testtld-service"

#include <utils/Log.h>
#include <log/log.h>
#include <iostream>
#include <HelloTest.h>

namespace aidl {

namespace android {

namespace hardware {

namespace testtld {

ndk::ScopedAStatus HelloTest::getTestOne(int32_t in_event, const std::string& in_name, int32_t* _aidl_return) {
    ALOGD("======getTestOne====1");
    std::int32_t ret = in_event;
    std::string name = in_name;
    *_aidl_return = 2;
     ALOGD("======getTestOne====2===in_event:%d",ret);
    ALOGD("%s: this = %p, name = %s ", __FUNCTION__, this, name.c_str());
    return ndk::ScopedAStatus::ok();
}


}  // namespace testtld

}  // namespace hardware

}  // namespace android

}  // namespace aidl

aidl/default/service.cpp

#define LOG_TAG "android.hardware.testtld-service"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include "HelloTest.h"

using aidl::android::hardware::testtld::HelloTest;
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<HelloTest> helloTest = ndk::SharedRefBase::make<HelloTest>();
    const std::string desc = HelloTest::descriptor + "/default"s;

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

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

    return EXIT_FAILURE;  // should not reached
}

aidl/default/Android.bp

cc_binary {
    name: "android.hardware.testtld-service",
    init_rc: ["HelloTest-default.rc"],
    vintf_fragments: ["HelloTest-default.xml"],
    relative_install_path: "hw",
    vendor: true,
    srcs: [
        "service.cpp",
        "HelloTest.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder",
        "libbinder_ndk",
        "libutils",
        "liblog",
        "libcutils",
        "libutils",
        "libdl",
        "android.hardware.testtld-V1-ndk",
    ],
    cflags: [
        "-Wall",
        "-Werror",
    ],
}

到  /hardware/interfaces/testtld/ 下,运行:

source build/envsetup.sh
lunch your target ##需要根据自己的实际情况进行选择
mm -j8
或者根目录下执行
mmm /hardware/interfaces/testtld -j8

将会在 /out/target/product/rk3576_u/vendor/bin/hw 目录生成如下文件:

android.hardware.testtld-service

5. 编写服务启动的rc脚本

aidl/default/HelloTest-default.rc

service android.hardware.testtld-service /vendor/bin/hw/android.hardware.testtld-service
    class hal
    user system
    group system

6. 声明VINTF AIDL 接口

aidl/default/HelloTest-default.xml

<manifest version="1.0" type="device">
    <hal format="aidl">
        <name>android.hardware.testtld</name>
        <version>1</version>
        <fqname>IHelloTest/default</fqname>
    </hal>
</manifest>

7. 将模块加入系统中

/device/rockchip/common/device.mk

# test AIDL
PRODUCT_PACKAGES += \
    android.hardware.testtld \
    android.hardware.testtld-service

8. 将模块添加到兼容性矩阵中

# 查看对应的API级别文件对应的兼容矩阵文件
# device/rockchip/common/manifests/compatibility_matrix_level_34.xml
# device/rockchip/common/manifests/manifest_level_34.xml
hardware/interfaces/compatibility_matrices/compatibility_matrix.8.xml
    <hal format="aidl" optional="true">
        <name>android.hardware.testtld</name>
        <version>1</version>
        <interface>
            <name>IHelloTest</name>
            <instance>default</instance>
        </interface>
    </hal>

 9.解决Selinux权限

hwservice.te

type hal_hellotest_hwservice, hwservice_manager_type, protected_hwservice;

hwservice_contexts

android.hardware.testtld::IHelloTest                                      u:object_r:hal_hellotest_hwservice:s0

file_contexts

/vendor/bin/hw/android\.hardware\.testtld-service     u:object_r:hal_hellotest_exec:s0

hal_hellotest.te

type hal_hellotest, domain;
type hal_hellotest_exec, vendor_file_type, exec_type, file_type;
init_daemon_domain(hal_hellotest)

 29.0.ignore.cil 按需求修改忽略文件,增加如下内容

    hal_hellotest_exec
    hal_hellotest_hwservice

修改的目录为如下:

system/sepolicy/prebuilts/api/34.0/private/compat/29.0/29.0.ignore.cil

system/sepolicy/prebuilts/api/34.0/private/compat/30.0/30.0.ignore.cil

system/sepolicy/prebuilts/api/34.0/private/compat/30.0/30.0.ignore.cil

system/sepolicy/prebuilts/api/34.0/private/compat/32.0/32.0.ignore.cil

system/sepolicy/prebuilts/api/34.0/private/compat/33.0/33.0.ignore.cil

system/sepolicy/prebuilts/api/34.0/private/file_contexts

system/sepolicy/prebuilts/api/34.0/private/hal_hellotest.te

system/sepolicy/prebuilts/api/34.0/private/hal_hellotest.te

system/sepolicy/prebuilts/api/34.0/private/hwservice.te

system/sepolicy/prebuilts/api/34.0/private/hwservice_contexts

system/sepolicy/private/compat/29.0/29.0.ignore.cil

system/sepolicy/private/compat/30.0/30.0.ignore.cil

system/sepolicy/private/compat/31.0/31.0.ignore.cil

system/sepolicy/private/compat/32.0/32.0.ignore.cil

system/sepolicy/private/compat/33.0/33.0.ignore.cil

system/sepolicy/private/file_contexts

system/sepolicy/private/hal_hellotest.te

system/sepolicy/private/hwservice.te

system/sepolicy/private/hwservice_contexts

10.调用测试

整体进行编译,更设备镜像查看,通过adb shell 查看服务是否启动,有就成功了,执行命令service list 查看服务列表多新增的如下:

android.hardware.testtld.IHelloTest/default: [android.hardware.testtld.IHelloTest]

查看vendor/bin/hw/目录下会有android.hardware.testtld-service

so 库文件目录

/system/lib64/android.hardware.testtld-V1-ndk.so 

调用是基于framework层的CPP和JAVA调用

JNI的CPP调用需要引入生成的文件,文件地址

frameworks/base/services/core/jni/Android.bp


cc_defaults {
    name: "libservices.core-libs",
    shared_libs: [
        ........
        "libbinder_ndk",
        "android.hardware.testtld-V1-ndk",
        ........
    ],

调用文件frameworks/base/services/core/jni/com_android_server_SystemTestJni.cpp

#define LOG_TAG "SystemTestJniCpp"
#include <cutils/log.h>
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <jni.h>
#include <linux/netlink.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/socket.h>
#include <pthread.h>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <aidl/android/hardware/testtld/IHelloTest.h>
#include <binder/Binder.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <utils/RefBase.h>
#include <android-base/properties.h>
#include <future>
#include <unistd.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>

using aidl::android::hardware::testtld::IHelloTest;
using ::ndk::ScopedAStatus;
using ::ndk::SharedRefBase;

namespace android {
static JavaVM *g_VM;
static jobject g_obj;

static void nativeSetTestOne(JNIEnv *env, jobject obj, jint flag) {
    ALOGD("----run nativeTestOne----flag:%d", flag);
    //通过ServiceManager获得aidl服务
    ndk::SpAIBinder binder(
                AServiceManager_checkService("android.hardware.testtld.IHelloTest/default"));
    if (binder.get() == nullptr) {
        ALOGE("---- AIDL is not present---");
    } else {
            ALOGE("---- AIDL is  present---");
            std::string mName="def";
            std::int32_t in_event =456 ;
            int32_t* aidl_return = new int32_t;
            IHelloTest::fromBinder(binder)->getTestOne(in_event,mName,aidl_return);
            ALOGD("------success to get IHelloTest service----aidl_return:%d", static_cast<int>(*aidl_return));
    }
}

JNI的JAVA调用需要引入生成的文件,文件地址

frameworks/base/services/core/Android.bp

    static_libs: [
        ....
        "android.hardware.testtld-V1-java", // AIDL
        .....
    ],

调用文件frameworks/base/services/core/java/com/android/server/SystemTestJni.java

package com.android.server;
import android.os.ServiceManager;
import android.content.Context;
import android.os.RemoteException;
import android.util.Slog;
import android.app.SystemTestManager;
import android.hardware.testtld.IHelloTest;

public class SystemTestJni {
    private final String TAG = "SystemTestJni";
    private SystemTestManager mManager;
    public static native void nativeSetTestOne(int flag);

    public SystemTestJni() {

    }
        public void setTestOne(int flag) throws RemoteException {
            try {
                Slog.d(TAG, "------setTestOne--------flag:" + String.valueOf(flag));
                nativeSetTestOne(flag);
                try {
                    Slog.d(TAG, "----Trying to get AIDL service----");
                    ///通过ServiceManager获得aidl服务
                    IHelloTest serviceAidl =
                    IHelloTest.Stub.asInterface(
                                    ServiceManager.getService("android.hardware.testtld.IHelloTest/default"));
                    if (serviceAidl != null) {
                        Slog.d(TAG, "-----success to get IHelloTest AIDL service--111---");
                        int result = serviceAidl.getTestOne(123,"abc");
                        Slog.d(TAG, "-----success to get IHelloTest AIDL service-result:" + result);
                    }
                } catch (Exception eAidl) {
                    Slog.e(TAG, "-----Failed to get IHelloTest AIDL service-----", eAidl);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

APP 调用 

app的libs引入jar包android.hardware.testtld-V1-java.jar,导入方式implementaion ,同时引入framework.jar方式compileOnly。

jar位置:out/soong/.intermediates/hardware/interfaces/testtld/aidl/vandroid.hardware.testtld-V1-java/android_common/javac目录下

调用代码同Framework  的JNI 的JAVA调用一致

 
package xxxxxx;
import android.util.Log;
import android.os.ServiceManager;
import android.hardware.testtld.IHelloTest;

public class Test{

        public void setTestOne()   {
     
               try {
                Log.d(TAG, "------setTestOne--------flag:" + String.valueOf(flag));
                nativeSetTestOne(flag);
                try {
                    Log.d(TAG, "----Trying to get AIDL service----");
                    ///通过ServiceManager获得aidl服务
                    IHelloTest serviceAidl =
                    IHelloTest.Stub.asInterface(
                                    ServiceManager.getService("android.hardware.testtld.IHelloTest/default"));
                    if (serviceAidl != null) {
                        Log.d(TAG, "-----success to get IHelloTest AIDL service--111---");
                        int result = serviceAidl.getTestOne(123,"abc");
                       Log.d(TAG, "-----success to get IHelloTest AIDL service-result:" + result);
                    }
                } catch (Exception eAidl) {
                    Log.e(TAG, "-----Failed to get IHelloTest AIDL service-----", eAidl);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

再需要补充APP调用权限,修改hellotest.tet添加下面内容即可或者关闭SELinux。

allow hal_hellotest servicemanager:binder { call transfer };
allow {  platform_app system_app shell } hal_hellotest_hwservice:hwservice_manager { find };
allow {  platform_app system_app untrusted_app_29 shell } hal_hellotest:binder {call};

<think>嗯,用户想在RK3576芯片的Android 14系统里添加HAL服务,需要方法和示例代码。首先,我得回忆一下AndroidHAL结构。HAL(硬件抽象)是连接Android框架和硬件驱动的重要部分,它允许厂商在不修改上代码的情况下实现硬件支持。 根据用户提供的引用,之前不同RK芯片的Android版本都有HAL的实现。比如引用3中提到RK3399 Android7.1的Camera HAL通过回填函数获取HDMI输入,引用4则展示了RK3399 Android8.1添加LED HAL的示例代码。这说明RK平台的HAL开发有一定的延续性,但不同Android版本可能有差异。 现在用户的问题是针对RK3576Android 14Android 14可能引入了新的HAL要求或接口变化,所以需要确认最新的HAL接口规范。用户需要具体的步骤和代码示例,所以应该从创建HAL模块、实现接口、注册服务、配置编译等方面入手。 首先,HAL模块通常以共享库的形式存在,代码放在hardware目录下。例如,引用4中的LED HAL在hardware/libhardware/modules/led下,包含Android.mk和C源文件。Android 14可能改用Soong构建系统,所以需要编写Android.bp文件,而不是Android.mk。但用户提供的引用中有Android.mk的例子,可能需要考虑兼容性或转换到新的构建系统。 然后,HAL的实现需要遵循HIDL或AIDL接口,这取决于Android版本。Android 8.0及以上推荐使用HIDL,而Android 11开始支持AIDL。但用户提到的是Android 14,可能更倾向于AIDL。不过根据引用1,RK3568 Android11的相机HAL3使用HAL接口,可能还是HIDL。需要确认RK3576 Android14的具体要求。 假设使用HIDL,步骤大致如下: 1. 定义HIDL接口文件(.hal)。 2. 实现HIDL接口,创建HAL服务。 3. 注册HAL服务到hwservicemanager。 4. 配置构建文件,编译生成共享库。 5. 添加SELinux策略,确保权限正确。 比如,引用4中的LED HAL示例,可能对应到HIDL的实现。但代码示例中的led_hal.c使用了传统的HAL模块结构(hw_module_t),这在Android 8.1中可能仍适用,但在Android 14可能需要更新为HIDL或AIDL形式。所以可能需要调整实现方式。 此外,引用2中的光感适配HAL调用显示HAL代码在hardware/rockchip/sensor目录下,可能涉及传感器相关的实现。因此,添加新的HAL服务可能需要类似的目录结构,并在device.mk中配置编译。 现在,用户需要具体的示例代码。根据引用4的示例,可能需要创建类似的目录结构,编写HAL模块的C代码,并配置构建文件。但在Android 14中,构建系统可能有所变化,比如使用Android.bp而非Android.mk。同时,服务注册可能需要使用hwservicemanager,而不是传统的hw_module_t。 可能的步骤: 1. 在hardware/rockchip/hardware/myhal目录下创建HAL模块。 2. 编写HIDL接口定义文件。 3. 实现HIDL接口,生成服务端代码。 4. 编写启动脚本或init.rc来注册服务。 5. 配置SELinux权限。 例如,对于自定义的myhal服务,定义IMyHal.hal,然后生成代码框架,实现接口,并在HAL的初始化过程中注册服务。同时,在设备启动时启动该服务。 可能遇到的问题包括权限配置、SELinux策略阻止服务访问,或者构建系统未包含新模块。需要参考现有RK平台的HAL实现,如相机、传感器等模块的结构。 总结来说,步骤应包括创建HAL接口实现、配置构建系统、注册服务、处理权限,并提供测试方法。示例代码需要根据Android 14HAL要求调整,可能使用HIDL或AIDL,并确保与RK3576的BSP兼容。</think>在RK3576 Android14系统中增加HAL服务的实现可分为以下步骤,以自定义"myhal"服务为例: ### 一、HAL服务实现步骤 1. **创建HAL接口定义** ```java // hardware/interfaces/myhal/1.0/IMyHal.hal package vendor.rockchip.hardware.myhal@1.0; interface IMyHal { // 示例接口方法 getVersion() generates (string version); setValue(int32_t val) generates (bool success); }; ``` 2. **生成HIDL代码框架** ```bash hidl-gen -o hardware/interfaces/myhal/1.0/default/ -Lc++-impl -rvendor.rockchip.hardware:hardware/interfaces myhal@1.0 hidl-gen -o hardware/interfaces/myhal/1.0/default/ -Landroidbp-impl -rvendor.rockchip.hardware:hardware/interfaces myhal@1.0 ``` 3. **实现HAL服务核心逻辑** ```cpp // hardware/rockchip/hardware/myhal/1.0/default/MyHal.cpp #include <vendor/rockchip/hardware/myhal/1.0/IMyHal.h> class MyHal : public IMyHal { public: Return<void> getVersion(getVersion_cb _hidl_cb) override { _hidl_cb("1.0.0-rk3576"); return Void(); } Return<bool> setValue(int32_t val) override { // 实际硬件操作代码 return true; } }; extern "C" IMyHal* HIDL_FETCH_IMyHal(const char* /* name */) { return new MyHal(); } ``` ### 二、配置编译系统 1. **Android.bp构建配置** ```python // hardware/rockchip/hardware/myhal/1.0/default/Android.bp cc_library_shared { name: "vendor.rockchip.hardware.myhal@1.0-impl", relative_install_path: "hw", proprietary: true, srcs: ["MyHal.cpp"], shared_libs: [ "libhidlbase", "libhidltransport", "vendor.rockchip.hardware.myhal@1.0", ], } ``` 2. **服务注册配置** ```xml <!-- device/rockchip/rk3576/manifest.xml --> <hal format="hidl"> <name>vendor.rockchip.hardware.myhal</name> <transport>hwbinder</transport> <version>1.0</version> <interface> <name>IMyHal</name> <instance>default</instance> </interface> </hal> ``` ### 三、SELinux策略配置 ```te # device/rockchip/sepolicy/vendor/hal_myhal.te type hal_myhal_default, domain; type hal_myhal_default_exec, exec_type, vendor_file_type; init_daemon_domain(hal_myhal_default) allow hal_myhal_default hwservicemanager:binder { call transfer }; ``` ### 四、服务启动控制 ```rc # device/rockchip/rk3576/init.rk3576.rc service vendor.myhal /vendor/bin/hw/vendor.rockchip.hardware.myhal@1.0-service class hal user system group system seclabel u:r:hal_myhal_default:s0 ``` ### 五、应用调用示例 ```java // 应用JNI接口 IMyHal service = IMyHal.getService(); String version = service.getVersion(); ``` ### 注意事项 1. HIDL接口版本需与Android 14的Treble兼容性要求匹配[^1] 2. RK3576的BSP需要包含HIDL基础支持库 3. 硬件操作需与内核驱动接口对齐,如通过sysfs或ioctl交互[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值