目录
1. 编写hal文件并编译
2. 实现Hidl Interface
3. 编写hdil service
4. 配置manifest.xml
5. hidl client端调用
5.1 实现java调用hidl service的例子
5.2 实现C++ 调用hidl service的例子
6. github地址
本文以LED为例在aosp上添加HIDL,以熟悉整个过程。
在hardware/interfaces/目录下创建led文件夹和基版本1.0,这个版本号分为两部分,major.minor。major版本不变得话,只能添加api,不能修改。
创建ILed.hal和types.hal
hardware/interfaces/led/1.0/ILed.hal
package [email protected];
interface ILed
{
//get led status
get() generates (LedStatus result);
//set led status
set(LedStatus val) generates(int32_t ret);
getBrightnessRange() generates(bool ret,BrightnessRange range);
setBrightnessValue(vec range) generates(bool ret);
on() ;
off() ;
};
hardware/interfaces/led/1.0/types.hal
package [email protected];
enum LedStatus : uint32_t {
LED_ON,
LED_OFF,
LED_BAD_VALUE,
};
struct BrightnessRange {
uint32_t min;
uint32_t max;
};
添加完后,执行hardware/interfaces/update-makefiles.sh 会自动生成编译编译脚本,然后在
hardware/interfaces/led/1.0/ 路径下执行mm,会生成所需要得hidl库,接下来我们需要实现hidl interface,供client调用。
首先实现ILed interface的子类ledImpl 得头文件和对应得cpp。
hardware/interfaces/led/1.0/default/ledImpl.h
#ifndef ANDROID_HARDWARE_LED_V1_0_LED_H
#define ANDROID_HARDWARE_LED_V1_0_LED_H
#include
#include
#include
namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {
using ::android::hardware::led::V1_0::LedStatus;
using ::android::hardware::led::V1_0::BrightnessRange;
using ::android::hardware::led::V1_0::ILed;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
struct ledImpl : public ILed {
public:
ledImpl();
Return get() override ;
Return set(LedStatus val) override;
Return on() override;
Return off() override;
Return getBrightnessRange(getBrightnessRange_cb _hidl_cb) override;
Return setBrightnessValue(const hidl_vec& range) override;
private:
LedStatus state;
};
extern "C" ILed* HIDL_FETCH_ILed(const char* name);
} // namespace implementation
} // namespace V1_0
} // namespace led
} // namespace hardware
} // namespace android
#endif //ANDROID_HARDWARE_LED_V1_0_LED_H
hardware/interfaces/led/1.0/default/ledImpl.cpp
#define LOG_TAG "LedService"
#include
#include "ledImpl.h"
namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {
ledImpl::ledImpl() {
state = LedStatus::LED_BAD_VALUE;
ALOGE("ledImpl Init status:%d", state);
}
Return ledImpl::on() {
state = LedStatus::LED_ON;
ALOGE("ledImpl on status:%d", state);
return Void();
}
Return ledImpl::off() {
state = LedStatus::LED_OFF;
ALOGE("ledImpl off status:%d", state);
return Void();
}
Return ledImpl::get() {
return state;
}
Return ledImpl::set(LedStatus val) {
if(val == LedStatus::LED_OFF || val == LedStatus::LED_ON)
state = val;
else
return -1;
return 0;
}
Return ledImpl::getBrightnessRange(getBrightnessRange_cb _hidl_cb)
{
ALOGE("ledImpl getBrightnessRange ");
BrightnessRange range;
range.max = 100;
range.min = 1;
_hidl_cb(true,range);
return Void();
}
Return ledImpl::setBrightnessValue(const hidl_vec& range)
{
ALOGE("ledImpl getBrightnessValue ");
auto iter = range.begin();
ALOGE("ledImpl getBrightnessValue range.begin: %d",*iter);
iter = range.end();
ALOGE("ledImpl getBrightnessValue range.end: %d",*iter);
ALOGE("ledImpl getBrightnessValue range.size: %zu",range.size());
return true;
}
ILed* HIDL_FETCH_ILed(const char * /*name*/) {
ALOGE("ledImpl HIDL_FETCH_ILed ");
return new ledImpl();
}
} // namespace implementation
} // namespace V1_0
} // namespace led
} // namespace hardware
} // namespace android
hardware/interfaces/led/1.0/default/Android.bp
cc_library_shared {
name: "[email protected]",
defaults: ["hidl_defaults"],
srcs: ["ledImpl.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libhardware",
"liblog",
"libutils",
"[email protected]",
],
}
cc_binary {
name: "[email protected]",
init_rc: ["[email protected]"],
srcs: ["service.cpp",
"ledImpl.cpp"],
shared_libs: [
"liblog",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"[email protected]",
],
}
接下来,使用相应功能填写存根并设置守护进程。可以使用passthrough方式和binder方式,示例:
hardware/interfaces/led/1.0/default/service.cpp
#define LOG_TAG "[email protected]"
#include
#include
#include "ledImpl.h"
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::implementation::ledImpl;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
int main() {
#if 0
// Passthrough dlopen so方式
return defaultPassthroughServiceImplementation();
#else
// Binder 方式
sp service = new ledImpl();
configureRpcThreadpool(1, true /*callerWillJoin*/);
if(android::OK != service->registerAsService())
return 1;
joinRpcThreadpool();
#endif
}
add the code to the manifest.xm 以至于hwservicemanager 查找到指定的hidl service
About HIDL configures
device/
android.hardware.led
hwbinder //hwbinder 或者passthrough (直通模式)
1.0
ILed
default
hidl service运行后,可以通过C++和Java两种方式调用,非常方便,通过java直接访问,就省去了jni。
将以下内容添加到 Android.mk 中:
LOCAL_JAVA_LIBRARIES += android.hardware.led-V1.0-java
/*
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.led-V1.0-java-static
*/
或将以下内容添加到 Android.bp 中:
shared_libs: [
/* … */
"android.hardware.led-V1.0-java",
],
该库还存在静态版:android.hardware.led-V1.0-java-static。
将以下内容添加到您的 Java 文件中:
import android.hardware.led.V1_0.ILed;
...
// retry to wait until the service starts up if it is in the manifest
ILed server = ILed.getService(/* retry */); // throws NoSuchElementException if not available
server.on();
首先将 HAL 库添加到 makefile 中:
Make:LOCAL_SHARED_LIBRARIES += [email protected]
Soong:shared_libs: [ …, [email protected] ]
接下来,添加 HAL 头文件:
#include
…
// in code:
sp client = ILed::getService();
client->on();
下面是我的Demo clinet
#define LOG_TAG "LED_CLINET"
#include
#include
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::LedStatus;
using android::hardware::led::V1_0::BrightnessRange;
using android::hardware::hidl_vec;
using android::sp;
int main(){
// BrightnessRange range;
sp service = ILed::getService();
if( service == nullptr ){
ALOGE("Can't find ILed service...");
return -1;
}
ALOGE("ILed ON");
service->on();
ALOGE("ILed OFF");
service->off();
ALOGE("ILed set");
service->set(LedStatus::LED_ON);
ALOGE("ILed get");
LedStatus ret = service->get();
ALOGE("ILed get: %d",ret);
service->getBrightnessRange([](bool ret1,BrightnessRange range){
ALOGE("ILed getBrightnessRange ret: %d",ret1);
ALOGE("ILed getBrightnessRange Max: %d",range.max);
ALOGE("ILed getBrightnessRange Min: %d",range.min);
});
int32_t array[] = {5, 6, 7};
hidl_vec hv1 = std::vector(array, array + 3);
bool ret2 = service->setBrightnessValue(hv1);
ALOGE("ILed getBrightnessValue bool: %d",ret2);
return 0;
}
需要看代码的可以去我的github,里面有相关的hidl代码,和C++调用示例
gitHub地址链接