Rk3588 Android12 AIDL 开发

AIDL (Android Interface Definition Language)HIDL (HAL Interface Definition Language) 都是 Android 系统中用于定义接口的工具,但它们有不同的用途和特性。

AIDL (Android Interface Definition Language)

  1. 用途

    • 主要用于应用程序之间的进程间通信 (IPC)。
    • 适用于定义应用程序组件(如 Activity 和 Service)之间的接口。

HIDL (HAL Interface Definition Language)

  1. 用途

    • 主要用于定义硬件抽象层 (HAL) 接口。
    • 适用于访问底层硬件功能,如摄像头、传感器等。

未来趋势

从 Android 13 开始,HIDL 已被弃用,建议使用 AIDL 来实现 HAL 接口⁴。这意味着未来的 Android 版本将更多地依赖 AIDL 来实现硬件抽象层的接口。

本文主要记录自己实现一个AIDL的过程

主要的架构逻辑

1.使能hidl-gen工具

source build/envsetup.sh
lunch rk3588_s-userdebug
make hidl-gen

2.建立自己的AIDL ,test目录 和ITest.hal,ITestWarpper.hal

1.mkdir vendor/rockchip/hardware/interfaces/test
2.mkdir vendor/rockchip/hardware/interfaces/test/1.0

3.新建ITest.hal文件
//vendor/rockchip/hardware/interfaces/test/1.0/ITest.hal
package rockchip.hardware.test@1.0;
import ITestWarpper;

interface ITest
{
        setTestWarpper(ITestWarpper testWarpper);

        GetString()generates (string printString);
};

4.新建ITestWarpper.hal文件 用于数据传递
//vendor/rockchip/hardware/interfaces/test/1.0/ITestWarpper.hal
package rockchip.hardware.test@1.0;
interface ITestWarpper
{
        GetString()generates (string printString);
};

生成编译文件vendor/rockchip/hardware/interfaces/test/1.0/Android.bp  

 do_makefiles_update rockchip.hardware:vendor/rockchip/hardware android.hardware:hardware/interfaces android.hidl:system/libhidl/transport

AIDL 的没有返回值都是VOID ,出参都是 generates (string printString);实现,类似C++的别名功能

生成对应的CPP和头文件

1.hidl-gen -o vendor/rockchip/hardware/test/1.0/defualt -Lc++-impl -rrockchip.hardware:vendor/rockchip/hardware -randroid.hidl:system/libhidl/transport rockchip.hardware  //生成C++ 和 H

2.hidl-gen -o vendor/rockchip/hardware/test/1.0/defualt -Landroidbp-impl -rrockchip.hardware:vendor/rockchip/hardware/ -randroid.hidl:system/libhidl/transport rockchip.hardware  //生成Android.dp

在defult 目录下生成对应的cpp文件和头文件,Android.bp

也可以使用我写的脚本生成对应的文件
./generate-source2.sh vendor/rockchip/hardware/interfaces/ test rockchip.hardware 

#! /bin/bash
# v1.0

if [ -z $1 ]; then
    echo "Please input path "
    exit 1
else
    LOC=$1
fi

if [ -z $2 ]; then
    echo "Please input module name"
    exit 1
else
    MODULE=$2
fi

if [ -z $3 ]; then
    echo "Please input package head"
    exit 1
else
    PACKAGE_HEAD=$3
fi


PACKAGE=$PACKAGE_HEAD.$MODULE@1.0
echo "You package is: $PACKAGE"

hidl-gen -o $LOC/$MODULE/1.0/defualt -Lc++-impl -r$PACKAGE_HEAD:$LOC \
            -randroid.hidl:system/libhidl/transport $PACKAGE
hidl-gen -o $LOC/$MODULE/1.0/defualt -Landroidbp-impl -r$PACKAGE_HEAD:$LOC \
            -randroid.hidl:system/libhidl/transport $PACKAGE

修改Test.cpp Test.h

// FIXME: your file license if you have one

#include "Test.h"
#include "log/log.h"
#define LOG_TAG "test1.0"
namespace rockchip::hardware::test::implementation {
sp<::rockchip::hardware::test::V1_0::ITestWarpper> mTestWarpper = nullptr;
hidl_string mDeviceId;
// Methods from ::rockchip::hardware::test::V1_0::ITest follow.
Return<void> Test::setTestWarpper(const sp<::rockchip::hardware::test::V1_0::ITestWarpper>& testWarpper) {
    // TODO implement
    mTestWarpper = testWarpper;
    return Void();
}

Test::Test(){
    ALOGD("@%s.",__FUNCTION__);
}
Test::~Test(){
    ALOGD("@%s",__FUNCTION__);
}
V1_0::ITest* HIDL_FETCH_ITest(const char* /* name */) {
    ALOGD("@%s",__FUNCTION__);
    return new Test();
}
// [&](const ::android::hardware::hidl_string &id
Return<void> Test::GetString(GetString_cb _hidl_cb) {
    ALOGD("@%s,mDeviceId:%s",__FUNCTION__,mDeviceId.c_str());
    // TODO implement
    if(mTestWarpper!=nullptr){
        mTestWarpper->GetString([&](const ::android::hardware::hidl_string &id){
            ALOGD("@%s,GetString mDeviceId:%s",__FUNCTION__,id.c_str());
            _hidl_cb(id);
        });

    }
    return Void();
}


// Methods from ::android::hidl::base::V1_0::IBase follow.

//ITest* HIDL_FETCH_ITest(const char* /* name */) {
    //return new Test();
//}
//
}  // namespace rockchip::hardware::test::implementation
// FIXME: your file license if you have one

#pragma once

#include <rockchip/hardware/test/1.0/ITest.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace rockchip::hardware::test::implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct Test : public V1_0::ITest {
    // Methods from ::rockchip::hardware::test::V1_0::ITest follow.
    Return<void> setTestWarpper(const sp<::rockchip::hardware::test::V1_0::ITestWarpper>& testWarpper) override;
    Return<void> GetString(GetString_cb _hidl_cb) override;
    Test();
    ~Test();
    // Methods from ::android::hidl::base::V1_0::IBase follow.

};

// FIXME: most likely delete, this is only for passthrough implementations
extern "C" V1_0::ITest* HIDL_FETCH_ITest(const char* name);

}  // namespace rockchip::hardware::test::implementation

添加一个开机服务 test/1.0/defualt下添加rc 和 xml文件和service.cpp

vendor/rockchip/hardware/interfaces/test/1.0/defualt/rockchip.hardware.test@1.0-service.rc
service test_server /vendor/bin/hw/rockchip.hardware.test@1.0-service
    class hal
    user system
    group system


vendor/rockchip/hardware/interfaces/test/1.0/defualt/rockchip.hardware.test@1.0-service.xml
<manifest version="1.0" type="device">
    <hal format="hidl">
        <name>rockchip.hardware.test</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
        <name>ITest</name>
            <instance>default</instance>
        </interface>
    </hal>
</manifest>

vendor/rockchip/hardware/interfaces/test/1.0/defualt/service.cpp
#define LOG_TAG "rockchip.hardware.test@1.0-service"

#include <rockchip/hardware/test/1.0/ITest.h>
#include <hidl/LegacySupport.h>
#include <binder/ProcessState.h>

using rockchip::hardware::test::V1_0::ITest;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

int main() {
    android::ProcessState::initWithDriver("/dev/vndbinder");
    return defaultPassthroughServiceImplementation<ITest>("default", /*maxThreads*/ 6);
}

修改test/1.0/defualt/Android.dp

// FIXME: your file license if you have one
//生成一个AIDL so
cc_library_shared {
    // FIXME: this should only be -impl for a passthrough hal.
    // In most cases, to convert this to a binderized implementation, you should:
    // - change '-impl' to '-service' here and make it a cc_binary instead of a
    //   cc_library_shared.
    // - add a *.rc file for this module.
    // - delete HIDL_FETCH_I* functions.
    // - call configureRpcThreadpool and registerAsService on the instance.
    // You may also want to append '-impl/-service' with a specific identifier like
    // '-vendor' or '-<hardware identifier>' etc to distinguish it.
    name: "rockchip.hardware.test@1.0-impl",
    relative_install_path: "hw",
    // FIXME: this should be 'vendor: true' for modules that will eventually be
    // on AOSP.
    proprietary: true,
    srcs: [
        "Test.cpp",
        "TestWarpper.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libutils",
        "liblog",
        "rockchip.hardware.test@1.0",
    ],
}
//生成一个服务进程

cc_binary {
    name: "rockchip.hardware.test@1.0-service",
    init_rc: ["rockchip.hardware.test@1.0-service.rc"],
    vintf_fragments: ["rockchip.hardware.test@1.0-service.xml"],
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
        srcs: ["service.cpp",
    ],
    cflags: ["-Werror", "-Wno-unused-parameter"],
    shared_libs: [
        "liblog",
        "libhardware",
        "libhidlbase",
        "libutils",
        "libcutils",
        "rockchip.hardware.test@1.0",
        "libbinder",
        "libhidlmemory",
    ],
}
device 下根据自己的代码加入编译
PRODUCT_PACKAGES += \   
    rockchip.hardware.test@1.0-service \
    rockchip.hardware.test@1.0-impl

到这里我们的AIDL添加结束

二.修改系统te,不然服务跑不起来

添加文件device\rockchip\common\manifests\frameworks\rockchip.hardware.test@1.0-service.xml
<compatibility-matrix version="1.0" type="framework">
    <hal format="hidl" optional="true">
        <name>rockchip.hardware.test</name>
        <version>1.0</version>
        <interface>
            <name>ITest</name>
            <instance>default</instance>
        </interface>
    </hal>
</compatibility-matrix>

添加文件device\rockchip\common\sepolicy\vendor\hal_test.te
type hal_test_default, domain;
type hal_test_default_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(hal_test_default)

allow hal_test_default device:dir { read open};
allow hal_test_default camera_device:chr_file{ read  write open ioctl };
allow hal_test_default vndbinder_device:chr_file { read write open ioctl map};
allow hal_test_default hidl_base_hwservice:hwservice_manager add;
allow hal_test_default hal_test_hwservice:hwservice_manager {add find};
allow system_app hal_test_hwservice:hwservice_manager { find };
binder_call(system_app, hal_test_default)
binder_call(hal_test_default, system_app)
#binder_call(hal_test_default, platform_app)
binder_call(hal_test_default, hwservicemanager)
#binder_call(hal_test_default, hal_camera_default)
# Client
#allow cameraserver hal_test_hwservice:hwservice_manager { find };
#allow hal_camera_default hal_test_hwservice:hwservice_manager { find };
get_prop(hal_test_default, hwservicemanager_prop)


修改device\rockchip\common\sepolicy\vendor\hwservice_contexts
rockchip.hardware.tv.input::ITvInput                   u:object_r:hal_tv_input_hwservice:s0
+ rockchip.hardware.test::ITest                  u:object_r:hal_test_hwservice:s0

修改device\rockchip\common\sepolicy\vendor\hwservice.te
+type hal_test_hwservice, hwservice_manager_type;

三。写一个测试demo

添加cpp和h 生成一个so 

//添加packages/apps/libtest_bridge/data_bridge.h
// #include <jni.h>
#include <functional>
#include <string>
#include <time.h>

void init();
void deinit();

//添加packages/apps/libtest_bridge/data_bridge.cpp
#define APK_VERSION	"V1.3"
#define LOG_TAG "test_bridge"
//#define LOG_NDEBUG 0

#include <utils/Log.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utils/Log.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/v4l2-subdev.h>

#include "data_bridge.h"

#include <ui/Fence.h>
#include <ui/GraphicBufferMapper.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>

#include <utils/Singleton.h>

#define VIRTUAL_CAMERA
#define RGA_PROC 


#include <android/hardware_buffer_jni.h>
#include <vndk/hardware_buffer.h>

#include <condition_variable>


#ifdef RGA_PROC
#include <RockchipRga.h>
#include <im2d_api/im2d.h>
#include "im2d_api/im2d.hpp"
#include "im2d_api/im2d_common.h"
#endif

#define LOGE(msg,...)   ALOGE("%s(%d): " msg ,__FUNCTION__,__LINE__,##__VA_ARGS__)
#define LOGD(msg,...)   ALOGD("%s(%d): " msg ,__FUNCTION__,__LINE__,##__VA_ARGS__)
#define LOGV(msg,...)   ALOGV("%s(%d): " msg ,__FUNCTION__,__LINE__,##__VA_ARGS__)


using namespace std;
using namespace android;
#include <rockchip/hardware/test/1.0/ITest.h>
class FrameWarpperImp :public rockchip::hardware::test::V1_0::ITestWarpper{
    public:
    android::hardware::Return<void> GetString(GetString_cb _hidl_cb) {
    // TODO implement
        ::android::hardware::hidl_string deviceId = "hellow world";
        _hidl_cb(deviceId);
        return android::hardware::Void();
    }

    ~FrameWarpperImp(){
        ALOGD("%s",__FUNCTION__);
    }
    FrameWarpperImp(){
        ALOGD("%s",__FUNCTION__);
    }
};
FrameWarpperImp *frameWarpperImp;
void init()
{
    ::android::hardware::hidl_string testId;
    ALOGD("%s",__FUNCTION__);
    android::sp<rockchip::hardware::test::V1_0::ITest> client = rockchip::hardware::test::V1_0::ITest::getService();
    if(client.get()!= nullptr){        
        if (frameWarpperImp != nullptr)
        {
            client->setTestWarpper(nullptr);
            frameWarpperImp = nullptr;
        }        
        frameWarpperImp = new FrameWarpperImp();
        ALOGD("setFrameDecorator");
        client->setTestWarpper(frameWarpperImp);
        client->GetString([&](const ::android::hardware::hidl_string &id){
            testId = id;
            ALOGD("setFrameDecorator%s",testId.c_str());
        });
    }
}
void deinit(){
    ALOGD("%s",__FUNCTION__);
    android::sp<rockchip::hardware::test::V1_0::ITest> client = rockchip::hardware::test::V1_0::ITest::getService();
    ALOGE("client.get():%p",client.get());
    if(client.get()!= nullptr){
        ALOGD("setFrameDecorator nullptr");
        client->setTestWarpper(nullptr);
        //delete frameWarpperImp ;
        frameWarpperImp = nullptr;
    }
}

packages/apps/libtest_bridge/Android.bp

//生成一个libtest_bridge.so
cc_library_shared {
    name: "libtest_bridge",
    srcs: ["data_bridge.cpp"],
    header_libs: [
        "jni_headers",
    ],
    include_dirs: [
        "hardware/rockchip/librga",
    ],
    shared_libs: [
        "libbase",
        "libandroid",
        "liblog",
        "libutils",
        "libcutils",
        "libnativehelper",
        "libhidlbase",
        "libui",
        "librga",
//rga_proc        "librga",
        "rockchip.hardware.test@1.0",
    ],
    cflags: [
        "-Wall",
        "-Wno-error",
        "-Wextra",
        "-Wno-unused-parameter",
    ],
    sanitize: {
        scs: true,
    },
}
ndk_library {
    name: "libtest_bridge",
    symbol_file: "libtest_bridge.map.txt",
    first_version: "30",
}
prebuilt_etc {
    name: "public.libtest_bridge",
    src: "public.libtest_bridge.txt",
    filename_from_src: true,
}

//生成一个可执行文件test1.0_service
cc_binary {
    name: "test1.0_service",

    proprietary: true,
    relative_install_path: "hw",
        srcs: ["service.cpp",
    ],
    defaults: ["hidl_defaults"],
    vendor: true,
    sdk_version: "current",
    cflags: [
        "-Wall",
        "-Wno-error",
        "-Wextra",
        "-Wno-unused-parameter",
    ],
    shared_libs: [
        "liblog",
        "libtest_bridge",
    ],
}

添加文件packages\apps\libtest_bridge\libtest_bridge.map.txt
LIBDATA_BRIDGE {
  global:
    init;
  local:
    *;
};

添加文件packages\apps\libtest_bridge\public.libtest_bridge.txt
libtest_bridge.so nopreload

添加文件packages\apps\libtest_bridge\service.cpp
#define LOG_TAG "rockchip.hardware.test@1.0-service"
#include "data_bridge.h"


int main() {
    init();
}

编译完成后将系统的test1.0_service 推到 data/loal/tmp

执行./test1.0_service 

09-05 07:08:06.633  2892  2892 D data_bridge: init
09-05 07:08:06.634  2892  2892 D data_bridge: FrameWarpperImp
09-05 07:08:06.634  2892  2892 D data_bridge: setFrameDecorator
09-05 07:08:06.635   454   454 D test1.0 : @GetString,mDeviceId:
09-05 07:08:06.635   454   454 D test1.0 : @operator(),GetString mDeviceId:
09-05 07:08:06.636  2892  2892 D data_bridge: setFrameDecoratorhellow world

本文章只做自己学习记录

### 关于ArcGIS License Server无法启动的解决方案 当遇到ArcGIS License Server无法启动的情况,可以从以下几个方面排查并解决问题: #### 1. **检查网络配置** 确保License Server所在的计算机能够被其他客户端正常访问。如果是在局域网环境中部署了ArcGIS Server Local,则需要确认该环境下的网络设置是否允许远程连接AO组件[^1]。 #### 2. **验证服务状态** 检查ArcGIS Server Object Manager (SOM) 的运行情况。通常情况下,在Host SOM机器上需将此服务更改为由本地系统账户登录,并重启相关服务来恢复其正常工作流程[^2]。 #### 3. **审查日志文件** 查看ArcGIS License Manager的日志记录,寻找任何可能指示错误原因的信息。这些日志可以帮助识别具体是什么阻止了许可服务器的成功初始化。 #### 4. **权限问题** 确认用于启动ArcGIS License Server的服务账号具有足够的权限执行所需操作。这包括但不限于读取/写入特定目录的权利以及与其他必要进程通信的能力。 #### 5. **软件版本兼容性** 保证所使用的ArcGIS产品及其依赖项之间存在良好的版本匹配度。不一致可能会导致意外行为完全失败激活license server的功能。 #### 示例代码片段:修改服务登录身份 以下是更改Windows服务登录凭据的一个简单PowerShell脚本例子: ```powershell $serviceName = "ArcGISServerObjectManager" $newUsername = ".\LocalSystemUser" # 替换为实际用户名 $newPassword = ConvertTo-SecureString "" -AsPlainText -Force Set-Service -Name $serviceName -StartupType Automatic New-ServiceCredential -ServiceName $serviceName -Account $newUsername -Password $newPassword Restart-Service -Name $serviceName ``` 上述脚本仅作为示范用途,请依据实际情况调整参数值后再实施。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmbbPdx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值