简述
当你在Android系统中使用不同的硬件设备(例如摄像头、传感器、音频设备等)时,你需要与硬件抽象层(HAL
)进行通信。 HAL
是一个中间层,它充当了硬件和应用程序之间的桥梁。但是,由于硬件设备的不同,HAL接口在不同的硬件之间也会有所不同。这就是Android HAL
接口定义语言(HIDL
)的用武之地。
HIDL
允许开发人员为每个硬件设备定义自己的接口。这些接口定义了硬件设备的功能和特性,包括输入参数、返回值和异常。使用这些接口,应用程序可以直接与硬件设备通信,而无需了解特定的硬件细节。在Android
中,HIDL
被广泛用于与HAL
进行通信。
在Android Project Treble
被提出,在android O
中被全面的推送,设计 HIDL
这个机制的目的,主要目的是把框架(framework
)与 HAL
进行隔离,使得框架部分可以直接被覆盖、更新,而不需要重新对 HAL
进行编译。
HIDL
实际上是用于进行进程间通信(Inter-process Communication,IPC
)的。进程间的通信可以称为 Binder
化(Binderized
)。对于必须连接到进程的库,也可以使用 passthough
模式(但在Java中不支持)。
编写代码
在Aosp
代码目录中创建目录 hardware/interfaces/stksensor/1.0
(有关1.0
版本相关的,可以查看官网的版本管理概念),
1、新建文件IStksensor.hal
package android,hardware.stksensor@1.0;
improt IStksensorCallBack;
interface IStksensor {
setCallBack(IStksensorCallBack callback);
write(string data) generates (bool res);
init() generates (MyResult result);
};
2、创建UDT
(用户自定义类型),types.hal
package android.hardware.stksensor@1.0;
enum ResultCode : int32_t {
UNKNOWN = -1,
ERROR = 0,
OK = 1,
};
struct MyResult{
ResultCode resultCode;
string msg;
};
3、新建文件回调文件IStksensorCallBack.hal
package android.hardware.stksensor@1.0;
interface IStksensorCallBack {
passData(uint32_t data) generates (MyResult result);
};
使用hidl-gen生成相关文件
在终端执行以下命令,设置临时变量
PACKAGE=android.hardware.stksensor@1.0
LOC=hardware/interfaces/stksensor/1.0/default
在AOSP
源码根目录执行hidl-gen
生成default
目录里的c++
文件
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
在AOSP
源码根目录执行hidl-gen
生成default
目录里的Android.bp
文件
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
在AOSP
源码根目录执行./hardware/interfaces/update-makefiles.sh
会生成hardware/interfaces/stksensor/1.0/
目录里的Android.bp
文件
实现接口代码
修改hardware/interfaces/stksensor/1.0/default/Stksensor.cpp
,这边实现单纯是打印日志
// FIXME: your file license if you have one
#include "Stksensor.h"
#include <log/log.h>
namespace android::hardware::stksensor::implementation {
// Methods from ::android::hardware::stksensor::V1_0::IStksensor follow.
Return<void> Stksensor::setCallBack(const sp<::android::hardware::stksensor::V1_0::IStksensorCallBack>& callback) {
// TODO implement
ALOGE("stksensor service have called the funtion of setCallBack");
return Void();
}
Return<::android::hardware::stksensor::V1_0::ResultCode> Stksensor::write(const hidl_string& data) {
// TODO implement
ALOGE("stksensor service have called the funtion of write");
return ::android::hardware::stksensor::V1_0::ResultCode {};
}
Return<void> Stksensor::init(init_cb _hidl_cb) {
// TODO implement
ALOGE("stksensor service have called the funtion of init");
return Void();
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
//IStksensor* HIDL_FETCH_IStksensor(const char* /* name */) {
//return new Stksensor();
//}
//
} // namespace android::hardware::stksensor::implementation
添加启动服务
1、在hardware/interfaces/stksensor/1.0/default/
创建service.cpp
#define LOG_TAG "android.hardware.stksensor@1.0-service"
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardwara::stksensor::V1_0::IStksensor;
using android::hardware::stksensor::V1_0::implementation::Stksensor;
using namespace android;
int main() {
configureRpcThreadpool(1, true);
sp<IStksensor> service = new Stksensor();
status_t status = service->registerAsService("stksensor");
if (status != OK) {
ALOGE("Error registering stksensor as service: %d", status);
return status;
}
ALOGE("Ok to registering stksensor as service");
joinRpcThreadpool();
return 1;
}
2、在hardware/interfaces/stksensor/1.0/default/
创建android.hardware.stksensor@1.0-service.rc
启动脚本
service stksensor-hal-1-0 /vendor/bin/hw/android.hardware.stksensor@1.0-service
class hal
user system
group system
3、在hardware/interfaces/stksensor/1.0/default/
创建android.hardware.stksensor@1.0-service.xml
的vintf
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.stksensor</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IStksensor</name>
<instance>stksensor</instance>
</interface>
</hal>
</manifest>
修改编译脚本
1、再修改hardware/interfaces/stksensor/1.0/default/Android.bp
// FIXME: your file license if you have one
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: "android.hardware.stksensor@1.0-impl",
relative_install_path: "hw",
// FIXME: this should be 'vendor: true' for modules that will eventually be
// on AOSP.
proprietary: true,
srcs: [
"Stksensor.cpp",
"StksensorCallBack.cpp",
],
shared_libs: [
"libhidlbase",
"libutils",
"android.hardware.stksensor@1.0",
],
}
cc_binary {
name: "android.hardware.stksensor@1.0-service",
relative_install_path: "hw",
defaults: ["hidl_defaults"],
proprietary: true,
init_rc: ["android.hardware.stksensor@1.0-service.rc"],
vintf_fragments: ["android.hardware.stksensor@1.0-service.xml"],
srcs: [
"SerialPort.cpp",
"service.cpp",
],
shared_libs: [
"libbase",
"liblog",
"libdl",
"libutils",
"libhardware",
"libhidlbase",
"libhidltransport",
"android.hardware.stksensor@1.0",
],
}
2、在device/$your_company/$SOC/device.mk
添加
PRODUCT_PACKAGES += \
android.hardware.stksensor@1.0-service \
android.hardware.stksensor@1.0-impl
现在stksensor
目录结构
stksensor/
└── 1.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── android.hardware.stksensor@1.0-service.rc
│ ├── android.hardware.stksensor@1.0-service.xml
│ ├── service.cpp
│ ├── StksensorCallBack.cpp
│ ├── StksensorCallBack.h
│ ├── Stksensor.cpp
│ └── Stksensor.h
├── IStksensorCallBack.hal
├── IStksensor.hal
└── types.hal
注意:会报一些avc
权限 ,需要自己添加