這部份就是 binderized 模式需要用到 service 相關的設定了,
假如是單純使用 passthrough 模式的話,就不需要。
因為我沒有特別實作這部份,所以要是想做的話可以先當參考,
有錯誤還請見諒和不吝告知小弟弟,
感謝各位大大。
其實當 IHelloworld.hal
創建完成,
就可以創建對應的 HIDL 實現代碼( impl 和 service),
而 hidl-gen
也提供了默認生成的方式,
詳細看 HIDL (4) hidl-gen 的 update-files.sh,
執行後最終生成的文件為:
├── default
│ ├── Android.bp
│ ├── HelloWorld.cpp
│ └── HelloWorld.h
先來看下 HelloWorld.h
:
1 #ifndef ANDROID_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H
2 #define ANDROID_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H
3
4 #include <android/hardware/helloworld/1.0/IHelloWorld.h>
5 #include <hidl/MQDescriptor.h>
6 #include <hidl/Status.h>
7
8 namespace android {
9 namespace hardware {
10 namespace helloworld {
11 namespace V1_0 {
12 namespace implementation {
13
14 using ::android::hardware::hidl_array;
15 using ::android::hardware::hidl_memory;
16 using ::android::hardware::hidl_string;
17 using ::android::hardware::hidl_vec;
18 using ::android::hardware::Return;
19 using ::android::hardware::Void;
20 using ::android::sp;
21
22 struct HelloWorld : public IHelloWorld {
23 // Methods from ::android::hardware::helloworld::V1_0::IHelloWorld follow.
24 Return<void> justTest(const hidl_string& name, justTest_cb _hidl_cb) override;
25 Return<void> justTest1(::android::hardware::helloworld::V1_0::HelloTest name) override;
26
27 // Methods from ::android::hidl::base::V1_0::IBase follow.
28
29 };
30
31 // FIXME: most likely delete, this is only for passthrough implementations
32 // extern "C" IHelloWorld* HIDL_FETCH_IHelloWorld(const char* name);
33
34 } // namespace implementation
35 } // namespace V1_0
36 } // namespace helloworld
37 } // namespace hardware
38 } // namespace android
39
40 #endif // ANDROID_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H
如果是要用 passthrough 模式,則需要打開 HIDL_FETCH_IHelloWorld()
函數的註釋,
並且在 -impl
的 C++ 文件中實現,
例如這裡需要在 HelloWorld.cpp
中實現該函數,
詳細可以看 nfc 或 tv 等模塊中實現。
再來看下 HelloWorld.cpp
:
1 #include "HelloWorld.h"
2
3 namespace android {
4 namespace hardware {
5 namespace helloworld {
6 namespace V1_0 {
7 namespace implementation {
8
9 // Methods from ::android::hardware::helloworld::V1_0::IHelloWorld follow.
10 Return<void> HelloWorld::justTest(const hidl_string& name, justTest_cb _hidl_cb) {
11 // TODO implement
12 return Void();
13 }
14
15 Return<void> HelloWorld::justTest1(::android::hardware::helloworld::V1_0::HelloTest name) {
16 // TODO implement
17 return Void();
18 }
19
20
21 // Methods from ::android::hidl::base::V1_0::IBase follow.
22
23 //IHelloWorld* HIDL_FETCH_IHelloWorld(const char* /* name */) {
24 //return new HelloWorld();
25 //}
26 //
27 } // namespace implementation
28 } // namespace V1_0
29 } // namespace helloworld
30 } // namespace hardware
31 } // namespace android
這裡就是實現的地方,
其中使用 passthrough 的時候需要打開 HIDL_FETCH_IHelloWorld()
函數。
這時候新增一個 service.cpp
檔案如下:
1 #define LOG_TAG "android.hardware.helloworld@1.0-service"
2
3 #include <android/hardware/helloworld/1.0/IHelloWorld.h>
4
5 #include <hidl/LegacySupport.h>
6 #include "HelloWorld.h"
7
8 // Generated HIDL files
9 using android::hardware::helloworld::V1_0::IHelloWorld;
10 using android::hardware::helloworld::V1_0::implementation::HelloWorld;
11
12 using android::hardware::defaultPassthroughServiceImplementation;
13 using android::hardware::configureRpcThreadpool;
14 using android::hardware::joinRpcThreadpool;
15
16 int main() {
17 #if 0
18 return defaultPassthroughServiceImplementation<IHelloWorld>();
19 #else
20 sp<IHelloWorld> service = new HelloWorld();
21 configureRpcThreadpool(1, true /*callerWillJoin*/);
22 if(android::OK != service->registerAsService())
23 return 1;
24 joinRpcThreadpool();
25 #endif
26 }
Android.bp
是為了編譯 HIDL 實現部分的代碼生成的默認編譯文件,
可以根據實際的情況修改:
1 cc_library_shared {
2 // FIXME: this should only be -impl for a passthrough hal.
3 // In most cases, to convert this to a binderized implementation, you should:
4 // - change '-impl' to '-service' here and make it a cc_binary instead of a
5 // cc_library_shared.
6 // - add a *.rc file for this module.
7 // - delete HIDL_FETCH_I* functions.
8 // - call configureRpcThreadpool and registerAsService on the instance.
9 // You may also want to append '-impl/-service' with a specific identifier like
10 // '-vendor' or '-<hardware identifier>' etc to distinguish it.
11 name: "android.hardware.helloworld@1.0-impl",
12 relative_install_path: "hw",
13 // FIXME: this should be 'vendor: true' for modules that will eventually be
14 // on AOSP.
15 proprietary: true,
16 srcs: [
17 "HelloWorld.cpp",
18 ],
19 shared_libs: [
20 "libhidlbase",
21 "libhidltransport",
22 "libutils",
23 "android.hardware.helloworld@1.0",
24 ],
25 }
如果其他模塊需要 so 則需要 share lib,
如果不需要刻意直接編譯 service,
修改後的 Android.bp
如下:
1 cc_binary {
2 name: "android.hardware.helloworld@1.0-service",
3 defaults: ["hidl_defaults"],
4 relative_install_path: "hw",
5 vendor: true,
6 init_rc: ["android.hardware.helloworld@1.0-service.rc"],
7 srcs: [
8 "HelloWorld.cpp",
9 "service.cpp"
10 ],
11 shared_libs: [
12 "liblog",
13 "libhidlbase",
14 "libhidltransport",
15 "libutils",
16 "libhardware",
17 "android.hardware.helloworld@1.0",
18 ],
19 }
注意:
-impl
為實現的庫文件,-service
為服務端的庫文件;hw
;system/lib64
下,system/lib64
下;vendor
下,vendor
下;在實現了 serivce 和 impl 代碼後需要添加 rc 文件,
文件名為 android.hardware.helloworld@1.0-service.rc
:
1 service helloworld-hal-1-0 /vendor/bin/hw/android.hardware.helloworld@1.0-service
2 class hal
3 user system
4 group system
需要注意的是,
在應用起來之前需要使能 service,一般有兩種方式:
一個是通過 rc 中的 service name,直接 start;
另外一種是通過 SELINUX 中添加 te 文件,設置 domain 信息。
對於 SELINUX 配置,這裡暫不分析,詳細看 SELINUX 相關文章。
App 其他的代碼這裡不做展示,主要來看調用的地方:
private void test() {
IHelloWorld service = null;
try {
service = IHelloWorld.getService(true);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (service == null) {
Log.e(TAG, "test failed, service is null...");
return;
}
try {
service.justTest1((byte)123);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Android.mk
為:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := TestHIDLClient
#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_STATIC_JAVA_LIBRARIES := \
android.hardware.helloworld-V1.0-java
include $(BUILD_PACKAGE)
之後你運行自己寫的 client 端應用,
就可以看到類似下面的 log 啦!
I android_os_HwBinder: HwBinder: Starting thread pool for default::android.hardware.helloworld@1.0::IHelloWorld
... ...
D HelloWorldImpl: justTest1, name = 123
HIDL C++ | Android Open Source Project
Implementing the Service | Android Open Source Project