HIDL --HelloWorld
https://source.android.com/devices/architecture/hidl/interfaces
https://www.jianshu.com/p/fd73ab98e423
https://www.jianshu.com/p/ca6823b897b5
mkdir -p hardware/interfaces/naruto/1.0/default
创建接口文件。
vim hardware/interfaces/naruto/1.0/INaruto.hal
package android.hardware.naruto@1.0; interface INaruto { helloWorld(string name) generates (string result); };
项目目录下生成hidl-gen后
# PACKAGE=android.hardware.naruto@1.0 # LOC=hardware/interfaces/naruto/1.0/default/ # make hidl-gen -j64 # hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE # hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
自动生成 Android,mk, Android.bp
default 目录会生成.cpp和.h 文件
制作service
touch hardware/interfaces/naruto/1.0/default/service/android.hardware.naruto@1.0-service.rc touch hardware/interfaces/naruto/1.0/default/service/service.cpp
./hardware/interfaces/update-makefiles.sh
mmm hardware/interfaces/naruto/1.0/default/
会生成一个android.hardware.naruto@1.0-impl.so, 生成在/vendor/lib64/hw/
会生成一个android.hardware.naruto@1.0.so, 生成在/system/lib64/
实现service
我们知道,HIDL的实现有两种方式,一种是Binderized模式,另一种是Passthrough模式,我们看到上面有两行注释掉的代码,看来这个代码是关键,来选择实现方式是Binderized还是Passthrough。
我们这里使用Passthrough模式来演示,其实大家后面尝试这两种方式后会发现其实这两种本质是一样的,目前大部分厂商使用的都是Passthrough来延续以前的很多代码,但是慢慢的都会被改掉的,所以我们来打开这个注释。
实现接口
Naruto.h
# ifndef ANDROID_HARDWARE_NARUTO_V1_0_NARUTO_H # define ANDROID_HARDWARE_NARUTO_V1_0_NARUTO_H # include <android/hardware/naruto/1.0/INaruto.h> # include <hidl/MQDescriptor.h> # include <hidl/Status.h> namespace android { namespace hardware { namespace naruto { namespace V1_0 { namespace 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 Naruto : public INaruto { // Methods from INaruto follow. Return<void> helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) override; // Methods from ::android::hidl::base::V1_0::IBase follow. }; // FIXME: most likely delete, this is only for passthrough implementations extern "C" INaruto* HIDL_FETCH_INaruto(const char* name); } // namespace implementation } // namespace V1_0 } // namespace naruto } // namespace hardware } // namespace android # endif // ANDROID_HARDWARE_NARUTO_V1_0_NARUTO_H
Naruto.cpp
# include "Naruto.h" namespace android { namespace hardware { namespace naruto { namespace V1_0 { namespace implementation { // Methods from INaruto follow. Return<void> Naruto::helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) { // TODO implement char buf[100]; ::memset(buf, 0x00, 100); ::snprintf(buf, 100, "Hello World, %s", name.c_str()); hidl_string result(buf); _hidl_cb(result); return Void(); } // Methods from ::android::hidl::base::V1_0::IBase follow. INaruto* HIDL_FETCH_INaruto(const char* /* name */) { return new Naruto(); } } // namespace implementation } // namespace V1_0 } // namespace naruto } // namespace hardware } // namespace android
service.cpp 定义了hal服务启动时候进行的操作,两个文件具体内容如下。
rc文件
service naruto_hal_service /vendor/bin/hw/android.hardware.naruto@1.0-service class hal user system group system
service.cpp
# define LOG_TAG "android.hardware.naruto@1.0-service" # include <android/hardware/naruto/1.0/INaruto.h> # include <hidl/LegacySupport.h> using android::hardware::naruto::V1_0::INaruto; using android::hardware::defaultPassthroughServiceImplementation; int main() { return defaultPassthroughServiceImplementation<INaruto>(); }
创建test目录,添加client.cpp文件和bp文件。
cc_binary { name: "android.hardware.naruto.client", defaults: ["hidl_defaults"], proprietary: true, relative_install_path: "hw", srcs: ["client.cpp"], shared_libs: [ "libhidlbase", "libhidltransport", "libutils", "liblog", "android.hardware.naruto@1.0", ], }
client.cpp
# include <android/hardware/naruto/1.0/INaruto.h> # include <hidl/Status.h> # include <hidl/LegacySupport.h> # include <utils/misc.h> # include <hidl/HidlSupport.h> # include <stdio.h> using android::hardware::naruto::V1_0::INaruto; using android::sp; using android::hardware::hidl_string; int main() { android::sp<INaruto> service = INaruto::getService(); if(service == nullptr) { printf("Failed to get service\n"); return -1; } service->helloWorld("JayZhang", [&](hidl_string result) { printf("%s\n", result.c_str()); }); return 0; }
执行./hardware/interfaces/update-makefiles.sh 更新编译范围,把test 和service 加到编译中。
执行mmm hardware/interfaces/naruto/1.0 编译生成客户端服务端可执行程序。
在manifest文件里添加追加
vendor接口的定义,不然在client端是没法拿到service的,在相应的manifest.xml里面加入:
<hal format="hidl"> <name>android.hardware.naruto</name> <transport>hwbinder</transport> <version>1.0</version> <interface> <name>INaruto</name> <instance>default</instance> </interface> </hal>
一个终端启动service,一个终端执行client。
HIDL注册回调的实现。
在demo的基础上,增加一个Callback回调接口。client端 实现回调接口。
INaruto.hal
package android.hardware.naruto@1.0; import INarutoCallback; interface INaruto { helloWorld(string name) generates (string result); init() generates(); release() generates(); setCallback(INarutoCallback cb)generates(); };
INarutoCallback.hal
package android.hardware.naruto@1.0;
interface INarutoCallback {
oneway onNotify(HalEvent event);
};
types.hal
package android.hardware.naruto@1.0;
struct HalEvent{
int32_t value;
};
client.cpp
# include <android/hardware/naruto/1.0/INaruto.h> # include <android/hardware/naruto/1.0/types.h> # include <android/hardware/naruto/1.0/INarutoCallback.h> # include <hidl/Status.h> # include <hidl/LegacySupport.h> # include <utils/misc.h> # include <hidl/HidlSupport.h> # include <stdio.h> using android::hardware::naruto::V1_0::INaruto; using android::sp; using android::hardware::hidl_string; using android::hardware::naruto::V1_0::INarutoCallback; using android::hardware::naruto::V1_0::HalEvent; using android::hardware::Void; using android::hardware::Return; class myNarutoCallback:public INarutoCallback{ public: myNarutoCallback(){} ~myNarutoCallback(){} Return<void>onNotify(const HalEvent &event){ printf("onNotify,value = %d\n",event.value); return Void(); } }; int main() { android::sp<INaruto> service = INaruto::getService(); if(service == nullptr) { printf("Failed to get service\n"); return -1; } service->helloWorld("JayZhang", [&](hidl_string result) { printf("%s\n", result.c_str()); }); sp<myNarutoCallback>callback = new myNarutoCallback(); printf("Failed to callback\n"); service->setCallback(callback); printf(" to callback\n"); ::sleep(10); return 0; }
Naruto.cpp
#include "Naruto.h" namespace android { namespace hardware { namespace naruto { namespace V1_0 { namespace implementation { static sp<INarutoCallback> mCallback = nullptr; static bool mExit = false; static void threadLoop(){ static int32_t count =0; HalEvent event; while(!mExit){ ::sleep(1); event.value = count++; if(mCallback != nullptr){ mCallback->onNotify(event); } } printf("threadloop exit"); } // Methods from INaruto follow. Return<void> Naruto::helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) { // TODO implement char buf[100]; ::memset(buf, 0x00, 100); ::snprintf(buf, 100, "Hello World, %s", name.c_str()); hidl_string result(buf); _hidl_cb(result); return Void(); } Return<void> Naruto::init() { // TODO implement return Void(); } Return<void> Naruto::release() { // TODO implement return Void(); } Return<void> Naruto::setCallback(const sp<INarutoCallback>& cb) { // TODO implement printf("Naruto11111111111:: setCallback:done"); mCallback = cb; if(mCallback != nullptr) { printf("setCallback:done"); threadLoop(); } printf("Naruto222222222222:: setCallback:done"); return Void(); } // Methods from ::android::hidl::base::V1_0::IBase follow. INaruto* HIDL_FETCH_INaruto(const char* /* name */) { return new Naruto(); } } // namespace implementation } // namespace V1_0 } // namespace naruto } // namespace hardware } // namespace android
-----------
使用java 做client, c++做service端。
编译hidl,为了方便eclipse或者Android Studio调用接口函数,需要编译出classes.jar包
如图:
将class.jar 导入新建的android studio 工程,直接拖到libs,然后右键,选择add as library
然后加入如下代码。
再将代码copy到源码工程中,android studio 只用来编写代码,编译要在源码工程中。
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_JAVA_LIBRARIES += dsv-platformadapter \ LOCAL_STATIC_ANDROID_LIBRARIES := \ android-support-v4 \ android-support-design \ android.hardware.naruto-V1.0-java \ // 加入库。 LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, app) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/src/main/res LOCAL_PACKAGE_NAME := HIDLdemo LOCAL_CERTIFICATE := platform LOCAL_VENDOR_MODULE := true #LOCAL_DEX_PREOPT := false LOCAL_MANIFEST_FILE := /app/src/main/AndroidManifest.xml LOCAL_PROGUARD_ENABLED := disabled ifeq (,$(findstring android-support-v7-appcompat,$(LOCAL_STATIC_JAVA_LIBRARIES))) $(info ****************************** RvcSupportService **************************************) LOCAL_RESOURCE_DIR += frameworks/support/v7/appcompat/res LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat LOCAL_AAPT_FLAGS += --auto-add-overlay LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat endif include packages/services/Car/car-support-lib/car-support.mk include $(BUILD_PACKAGE)
编译通过。 如果不能通过,可能是版本兼容问题,我这里使用的是继承Activity,继承AppCompatActivity就会出错。
把它install 到车机。
安装失败,是因为我们做了策略,允许安装属性打开,执行下面命令。再次执行install ,安装成功。
setprop persist.sys.installed_enable true 后再尝试(设置后不需要重启)
验证:
启动service,
关闭selinux, setenforce 0;再次启动app。
启动java client。 java App会运行不起来。
支持的类型可以是struct,struct {struct } vector<> vector<vector <> > enum,float,int,bool, a[], string
下图是一个支持数据类型的例子,不支持map
https://source.android.google.cn/devices/architecture/hidl-java/types#array-vect
package android.hardware.ygy@1.0; enum WifiStatusCode : uint32_t { SUCCESS, ERROR_UNKNOWN }; struct test1 { uint32_t rxUnicastCnt; string name; uint64_t active; uint64_t total; bool isOnline; float ddd; //map<int,int> ss; vec<vec<uint32_t> >driverFwLocalWakeCntPerType; vec<vec<string> >driverFwLocalWakeCntPerType1; vec<bool> ddssdf; }; struct test2{ int32_t signalStrength; int32_t bitErrorRate; }; struct test3 { uint32_t dbm; uint32_t ecio; test2 dd; }; typedef int32_t Rssi; /** * Mac Address type. 6 octets representing physical address of a device. */ typedef uint8_t[6] MacAddress; /** * SSID type. 32 octets representing the network. */ typedef uint8_t[32] Ssid; /** * BSSID type. 6 octets representing the physical address of an AP. */ typedef MacAddress Bssid; /** * TimeStamp in milliseconds (ms). */ typedef uint64_t TimeStampInMs;