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;