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