Native AIDL (与hal通信)

Native AIDL (与hal通信)

一、AIDL文件的编写与编译
    // FIXME: license file, or use the -l option to generate the files with the header.

package vendor.symbol.hardware.xxxxx;

import vendor.symbol.hardware.xxxxx.IxxxxxControlDevicexxxxxControlDevice;

@VintfStability
interface IxxxxxControlDevice {
    // Adding return type to method instead of out param int xxxxxCloseRet since there is only one return value.
    int closexxxxx();

    // Adding return type to method instead of out param int xxxxxDeviceConfigureRet since there is only one return value.
    int xxxxxDeviceConfigure();

    // Adding return type to method instead of out param int getVersionRet since there is only one return value.
    int getVersion();

    // FIXME: AIDL does not allow boolean to be an out parameter.
    // Move it to return, or add it to a Parcelable.
    /**
     * supporting control APIs go here
     */
    void sendCmd(in byte[] inputCmd, in int len, out vendor.symbol.hardware.xxxxx.cb cb);
}
    package vendor.symbol.hardware.xxxxx;

    @VintfStability
    parcelable IxxxxxControlDevicexxxxxControlDevice {
            int iFd;
            }
    package vendor.symbol.hardware.xxxxx;

    @VintfStability
    parcelable cb {
            boolean success;
            byte[] resp;
            }
  • 这里的aidl 文件和上层的写法有点类似具体可以参考官方链接:
  • https://source.android.google.cn/docs/core/architecture/aidl/aidl-language?hl=zh-cn
  • 这里需要注意的是有hidl转aidl的需求:
  • 1、hidl2aidl 是hidl转aidl的工具 它的位置在 system/tools/hidl/hidl2aidl/Android.bp 只需要把它编译出来就可以用
  • 2、hidl2aidl使用 :
    hidl2aidl -o 输出路径 -r hidl包名:hidl包根目录(即/1.0的上层目录) hidl包名@要转换的hidl版本
  • hidl包名@要转换的hidl版本即为 和hal文件同级的bp文件的hidl_interface 里的name,最后就是文件路径,所在路径,要与包名匹配。
  • 上面不管是我们自己写,或者转换hidl 就得到了我们需要的 aidl 文件接下来添加编译文件
  •   aidl_interface {
      name: "vendor.symbol.hardware.xxxxx",
      vendor_available: true,
      srcs: ["vendor/symbol/hardware/xxxxx/*.aidl"],
      stability: "vintf",
      backend: {
          cpp: {//zsg 这里会生成对应的.h .cpp文件供底层调用,我们如果想用jni调用so去使用aidl服务的话就需要enabled: true,
              // FIXME should this be disabled?
              // prefer NDK backend which can be used anywhere
              enabled: true,
          },
          java: {//zsg 这里会生成上层的接口,上层生成后不必在servicemanager里注册可以直接使用
              sdk_version: "module_current",
          },
      },
      versions: ["1"],
    

}


  • bp编译文件需要注意: versions: [“1”] 不是我们手动添加了,可以用命令
  • 先使用 make aidl包名-update-api 会生成 文件夹aidl_api/current
  • make aidl包名-freeze-api 会生成versions
  • 最后编译aidl模块就会生成对应的.h .cpp 以及 so库 vendor.symbol.hardware.xxxxx-V1-ndk_platform
    这个so库包含了这些生成的.h .cpp ,我们通过jni去使用aidl服务的话需要引用它.
    ===============================================================================
二、编写实现AIDL服务的模块, 创建一个文件夹 这里叫default
  • 1、 bp 编译文件
  •   cc_binary {
      name: "vendor.symbol.hardware.xxxxx-service",
      relative_install_path: "hw",
      defaults: ["hidl_defaults"],
      vendor: true,
      init_rc: ["vendor.symbol.hardware.xxxxx-service.rc"],
      vintf_fragments: ["vendor.symbol.hardware.xxxxx-service.xml"],
      srcs: ["service.cpp",
             "xxxxxControlDevice.cpp",
             "xxxxxdrv.c",
      ],
      //local_include_dirs: [
       //    "../hardware",
      //],
    
      shared_libs: [
          "liblog",
          "libbinder_ndk",
          "libbase",
          "libdl",
          "libhidlbase",
          "libutils",
          "libhardware",
          "vendor.symbol.hardware.xxxxx-V1-ndk_platform",
      ],
    

}
use_current = true

* vendor.symbol.hardware.xxxxx-service.rc :
* ```java
    service xxxxx_aidl_service /vendor/bin/hw/vendor.symbol.hardware.xxxxx-service
    class hal
    user system
    group system

on property:ro.boot.xxxxxx=true
    start xxxxx_aidl_service
  • rc 文件利用rc文件启动aidl服务
  • vendor.symbol.hardware.xxxxx-service.xml :
    <manifest version="1.0" type="device" optional="true">
    <hal format="aidl">
        <name>vendor.symbol.hardware.xxxxx</name>
        <version>1</version>
        <interface>
            <name>IxxxxxControlDevice</name>
            <instance>default</instance>
        </interface>
    </hal>
</manifest>

  • Framework Compatibility Matrix (FCM,兼容性矩阵) FCM指定了msi与vendor间的兼容关系
  • 除了在这里添加外还需要在vendor_framework_compatibility_matrix.xml 里添加:
  •   <hal format="aidl" optional="true">
          <name>vendor.symbol.hardware.xxxxx</name>
          <version>1</version>
          <interface>
              <name>IxxxxxControlDevice</name>
              <instance>default</instance>
          </interface>
      </hal>
    

2、 initrc 启动服务后在服务中注册服务到servicemanager,然后并且实现aidl接口

  • service.cpp:
#define LOG_TAG "vendor.symbol.hardware.xxxxx-service"
#include "xxxxxControlDevice.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>


using aidl::vendor::symbol::hardware::xxxxx::xxxxxControlDevice;

int main() {
	ALOGD("xxxxx main");
    ABinderProcess_setThreadPoolMaxThreadCount(0);
    std::shared_ptr<xxxxxControlDevice> ser = ndk::SharedRefBase::make<xxxxxControlDevice>(); //zsg 这里xxxxxControlDevice会实现aidl生成的.h文件实现接口

    if (!ser) {
        ALOGE("EXIT_FAILURE");
        return EXIT_FAILURE;
    }
    const std::string instance = std::string() + xxxxxControlDevice::descriptor + "/default";
    binder_status_t status = AServiceManager_addService(ser->asBinder().get(), instance.c_str());//zsg 这里将服务注册到ServiceManager
    if (status != STATUS_OK) {
        ALOGE("Failed to add service as AIDL service");
        return -1;
    } else {
        ALOGE("Service Registered");
    }
    ABinderProcess_joinThreadPool();


	return EXIT_FAILURE;

}
    

3、具体实现的文件:
xxxxxControlDevice.h

#ifndef VENDOR_SYMBOL_HARDWARE_xxxxx_V1_0_xxxxxCONTROLDEVICE_H
#define VENDOR_SYMBOL_HARDWARE_xxxxx_V1_0_xxxxxCONTROLDEVICE_H

#include <aidl/vendor/symbol/hardware/xxxxx/BnxxxxxControlDevice.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <hardware/hardware.h>
#include "xxxxxdrv.h"
#include <log/log.h>
#include <android/log.h>

namespace aidl {
namespace vendor {
namespace symbol {
namespace hardware {
namespace xxxxx {

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;
using ::android::hidl::base::V1_0::IBase;



struct xxxxxControlDevice : public BnxxxxxControlDevice {
public:
   xxxxxControlDevice();
   ~xxxxxControlDevice();

    //zsg 这里就是实现的对应接口,在这里声明,会在cpp 中实现
    // Methods from ::vendor::symbol::hardware::xxxxx::V1_0::IxxxxxControlDevice follow.
  ndk::ScopedAStatus closexxxxx(int32_t* _aidl_return) ;
  ndk::ScopedAStatus xxxxxDeviceConfigure(int32_t* _aidl_return) ;
  ndk::ScopedAStatus getVersion(int32_t* _aidl_return) ;
  ndk::ScopedAStatus sendCmd(const std::vector<uint8_t>& in_inputCmd, int32_t in_len, ::aidl::vendor::symbol::hardware::xxxxx::cb* out_cb);

    static IxxxxxControlDevice* getInstance(void);

    //zsg 这里是像hal层调用,hal则会调用最后的驱动
    // Methods from ::android::hidl::base::V1_0::IBase follow.
private:
    static xxxxx_control_device_t* openHal();
    xxxxx_control_device_t *mDevice;
    static xxxxxControlDevice* sInstance;

};

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

}  // namespace xxxxx
}  // namespace hardware
}  // namespace symbol
}  // namespace vendor
}  // namespace aidl
#endif  // VENDOR_SYMBOL_HARDWARE_xxxxx_V1_0_xxxxxCONTROLDEVICE_H

xxxxxControlDevice.cpp

#include "xxxxxControlDevice.h"
#include <hardware/hardware.h>
#include "xxxxxdrv.h"
#include <android/log.h>

#include <inttypes.h>
#include <unistd.h>

namespace aidl {
namespace vendor {
namespace symbol {
namespace hardware {
namespace xxxxx {

xxxxxControlDevice::xxxxxControlDevice() {
    mDevice = openHal();//zsg 直接在构造函数中去获得底层设备
    if (!mDevice) {
        ALOGE("Can't open xxxxx HAL module");
    }
    else {
        ALOGD("xxxxx Implementation : xxxxx HAL module Passed");
    }
}

xxxxxControlDevice::~xxxxxControlDevice() {
    ALOGV("~xxxxxControlDevice()");
    if (mDevice == nullptr) {
        ALOGE("No valid xxxxx device");
        return;
    }

    int err;
    if (0 != (err = mDevice->common.close(
            reinterpret_cast<hw_device_t*>(mDevice)))) {
       ALOGE("Can't close xxxxx module, error: %d", err);
       return;
    }
    mDevice = nullptr;
}

xxxxx_control_device_t* xxxxxControlDevice::openHal(){
    xxxxx_control_device_t* xxxxxDevice;
    const hw_module_t* hwModule = NULL;

    //zsg 这里的hw_get_module 就会调用到对应的so库最后控制驱动设备
    int ret = hw_get_module(xxxxx_HARDWARE_MODULE_ID, (const struct hw_module_t**)&hwModule);
    if (ret == 0) {
          ret = hwModule->methods->open(hwModule, xxxxx_HARDWARE_MODULE_ID,
             reinterpret_cast<hw_device_t**>(&xxxxxDevice));
         if (ret != 0x01) {
              ALOGE("xxxxx OPEN  %s failed: %d", xxxxx_HARDWARE_MODULE_ID,  ret);
        } else {
             ALOGD("xxxxx OPEN  %s passed: %d", xxxxx_HARDWARE_MODULE_ID,  ret);
        }
    } else {
         ALOGE("hw_get_module %s failed: %d", xxxxx_HARDWARE_MODULE_ID, ret);
    }

    if (ret == 0x01) {
         return xxxxxDevice;
    } else {
          ALOGE(" xxxxx failed to load HAL.");
         return nullptr;
    }
}


// Methods from ::vendor::symbol::hardware::xxxxx::V1_0::IxxxxxControlDevice follow.
ndk::ScopedAStatus xxxxxControlDevice::sendCmd(const std::vector<uint8_t>& inputCmd, int32_t len, ::aidl::vendor::symbol::hardware::xxxxx::cb* out_cb) {
    // TODO implement
    uint8_t recv_buff[xxxxx_RECV_BUF_SIZE];
    int32_t recv_len = len;

    ALOGD("xxxxx, ++++ xxxxxControlDevice::sendCmd +++");

    if( mDevice == nullptr) {
        //_hidl_cb(false, {});
        out_cb->success = false;
        out_cb->resp = {};
        return ndk::ScopedAStatus::ok();
    }

    recv_len =  mDevice->send_cmd(mDevice, inputCmd.data(), inputCmd.size(), recv_buff);

    if (recv_len < 1) {
         //_hidl_cb(false, {});
         out_cb->success = false;
         out_cb->resp = {};
         return ndk::ScopedAStatus::ok();
    }

    hidl_vec<uint8_t> respVec;
    respVec.setToExternal((uint8_t*)recv_buff, recv_len);
    respVec.resize(recv_len);
    //_hidl_cb(true, respVec);
    out_cb->success = true;
    out_cb->resp = respVec;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus xxxxxControlDevice::getVersion(int32_t* _aidl_return) {
    // TODO implement
    *_aidl_return = int32_t {};

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus xxxxxControlDevice::xxxxxDeviceConfigure(int32_t* _aidl_return) {
    // TODO implement
    *_aidl_return = mDevice->xxxxx_device_configure(mDevice);
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus xxxxxControlDevice::closexxxxx(int32_t* _aidl_return) {
    // TODO implement
    ALOGV("~xxxxxControlDevice()");
    if (mDevice == nullptr) {
        ALOGE("No valid xxxxx device");
        *_aidl_return =  0;
        return ndk::ScopedAStatus::ok();
    }

    int ret = 0;
    if(mDevice != nullptr)
        *_aidl_return = mDevice->xxxxx_close(mDevice);
    
    return ndk::ScopedAStatus::ok();

}



//
}  // namespace xxxxx
}  // namespace hardware
}  // namespace symbol
}  // namespace vendor
}  // namespace aidl

对应的部分so中hal代码 hw_module_t,即最后调用到xxxxx_device_open方法:
写了这么多就是为了最终调用到这里,即对应的hal 模块,去控制驱动设备:

static struct hw_module_methods_t xxxxxdrv_module_methods = {
    .open  =  xxxxx_device_open,
};
····················
·····················
··························
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 0,
    .version_minor = 1,
    .id = xxxxx_HARDWARE_MODULE_ID, //zsg 外面是通过这个id调用到这里
    .name = "xxxxx Module",
    .author = "Kavya Babu.",
    .methods = &xxxxxdrv_module_methods,
};
三、现在如果我们需要用jni去调用这个服务,即从底层去获取服务,控制设备:
  • 1、bp 编译文件:

cc_library_shared {

name: "libserial_xxxxx",
//${warning "=======zsgzsgzsg====cc_library_shared=====================name is:${name}"}

srcs: [
    "com_symbol_jni_xxxxx.cpp",
    "Onload.cpp",
],

//include_dirs: KERNEL_HEADERS + JNI_H_INCLUDE + ["libnativehelper/include/nativehelper/"],

header_libs: ["jni_headers"],

 include_dirs: [
    "system/core/include",
    "hardware/libhardware/include",
],

shared_libs: [
    "libcutils",
    "libutils",
    "libhardware",
    "liblog",
    "libnativehelper",
    "libhidlbase",
    "libbinder",
    "libbinder_ndk",
    "vendor.symbol.hardware.xxxxx-V1-ndk_platform", //zsg aidl 自动生成的so库
],

host_ldlibs: ["-llog"],

}

  • jni部分代码,这里就是主要的获取aidl 服务的地方:
  • 这样所有的代码就通了
    static jint xxxxx_device_open(JNIEnv* env, jclass clazz)
    {
        struct hw_module_t *hw_xxxxx_module = NULL;
        jint retVal = (jint)INVALID_HANDLE;

        pthread_mutex_lock(&openMutex);

        //zsg 通过ServiceManager获得aidl服务
        ndk::SpAIBinder binder(
                   AServiceManager_checkService("vendor.symbol.hardware.xxxxx.IxxxxxControlDevice/default"));

        if (binder.get() == nullptr) {
            ALOGE("IxxxxxControlDevice AIDL is not present");
        } else {
            xxxxxDevice = IxxxxxControlDevice::fromBinder(binder);
        }

        if(xxxxxDevice != nullptr) {
           ALOGD("[xxxxx JNI]: >> configure before service \r\n");
           int32_t _aidl_return;
           xxxxxDevice->xxxxxDeviceConfigure(&_aidl_return);
           if((i_fdIoctl = open(xxxxx_DRIVER_FILE, O_RDWR)) < 0){
               ALOGE("[xxxxx JNI]:\
                   xxxxx NODE absent %s",
                    strerror(errno));
               goto xxxxxERROR;
           }
           retVal = (jint)SUCCESS;
           g_OpenCounter_jni++;
           goto xxxxxERROR;
        } else {
            ALOGD("[xxxxx JNI]: >> getservice failed\n");
        }

    xxxxxERROR:
        pthread_mutex_unlock(&openMutex);
        ALOGD("[xxxxx JNI]: >>  xxxxx_device_open i_fdIoctl=%d ,\
                     g_OpenCounter_jni = %d\r\n",i_fdIoctl, g_OpenCounter_jni);
        return retVal;
    }
    
    ....................................
    ..........................................
    .....................................................
    
    //zsg jni注册方法
        int register_com_symbol_xxxxx(JNIEnv* env)
    {
        ALOGD("[xxxxx JNI]: >register_com_symbol_xxxxx >>>>>\n");
        jclass clazz = env->FindClass("com/symbol/xxxxx/xxxxx");

        return env->RegisterNatives(clazz ,method_table,NELEM(method_table));
    }

Onload.cpp:

#include <nativehelper/JNIHelp.h>
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"

namespace android {
int register_com_symbol_xxxxx(JNIEnv* env);
};

using namespace android;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;


    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("JNI_OnLoad:: xxxxx :: === CrGetEnv failed!");
        return result;
    }
    ALOG_ASSERT(env, "hardbg: JNI_OnLoad -> Could not retrieve the env!");

    register_com_symbol_xxxxx(env);

    return JNI_VERSION_1_4;
}
  • 上层代码获取服务方法:

IxxxxxChargeManager.Stub.asInterface(ServiceManager.waitForDeclaredService(“vendor.xxxxx.hardware.zcm.IxxxxxChargeManager/default”));

四、SeLinux部分:

xxxxx_aidl.te:

type hal_xxxxxaidl_default, domain;
type vendor_xxxxx_device, dev_type;
type sysfs_xxxxx, fs_type, sysfs_type;

type hal_xxxxxaidl_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_xxxxxaidl_default)

allow hal_xxxxxaidl_default hal_xxxxxaidl_service:service_manager add;
allow hal_xxxxxaidl_default kmsg_device:chr_file { getattr write open };

allow hal_xxxxxaidl_default servicemanager:binder { call transfer };

allow hal_xxxxxaidl_default vendor_xxxxx_device:chr_file { read write ioctl open };

file_contexts

//zsg 这里生成的bin文件是hal_xxxxxaidl_default_exec 类型
//运行起来的进程是hal_xxxxxaidl_default 类型
/(vendor|system/vendor)/bin/hw/vendor\.symbol\.hardware\.xxxxx-service u:object_r:hal_xxxxxaidl_default_exec:s0

service.te

type hal_xxxxxaidl_service, vendor_service, service_manager_type;

service_contexts

vendor.symbol.hardware.xxxxx.IxxxxxControlDevice/default                            u:object_r:hal_xxxxxaidl_service:s0

system_app.te

allow system_app hal_xxxxxaidl_default:binder call;
allow system_app vendor_xxxxx_device:chr_file { read write ioctl open };
allow system_app sysfs_xxxxx:file { read open };

https://blog.csdn.net/weixin_60253080/article/details/127810200
https://blog.csdn.net/qq_40731414/article/details/126823262

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值