android
hidl simple example
easy16
2018. 6. 25. 17:03
http://devarea.com/android-hidl-and-project-treble/#.WzGVeaczaUk
위의 사이트의 tutorial을 직접 추가해봤음.
두 가지를 수정하니 내가 구성한 환경에서 돌아가는 것을 확인함.
- android.hardware.simple@2.0-impl.so을 sharelib으로 링크하는 경우, /vendor/lib/hw에 위치한 해당 so를 인식하지 못함.
- *-impl.so의 경우, framework에서 direct로 링크하여 쓰는 경우가 없음.
- 따라서 tutorial 내용과 다르게 getInstance 메소드 대신, HIDL_FETCH_ISimphw을 사용하여 위의 문제들을 모두 회피 가능.
- 굳이 HIDL_FETCH_ISimphw의 내용을 따라가보진 않았으나, 해당 함수 호출시, *-impl.so 를 링크하는 부분이 hidl의 어딘가에는 구현되어 있을거라 추측함.
1. add simple directory
mkdir -p hardware/interfaces/simple/2.0/default
2. create hal file
package android.hardware.simple@2.0;
interface ISimphw {
simpfn(int32_t valueIn) generates (int32_t valueRet);
};
3. use hidl-gen to make HAL files.
make hidl.sh
PACKAGE=android.hardware.simple@2.0 LOC=hardware/interfaces/simple/2.0/default/ HIDL_GEN=out/host/linux-x86/bin/hidl-gen # 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#./hidl.sh
check auto gen files
hardware/interfaces/simple/2.0/
├── ISimphw.hal
└── default //auto gen
├── Android.bp
├── Simphw.cpp
└── Simphw.h
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Android.bp
cc_library_shared {
name: "android.hardware.simple@2.0-impl",
relative_install_path: "hw",
proprietary: true,
srcs: [
"Simphw.cpp",
],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.simple@2.0",
"android.hidl.base@1.0",
],
}
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Simphw.cpp
#include "Simphw.h"
namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {
// Methods from ::android::hardware::simple::V2_0::ISimphw follow.
Return Simphw::simpfn(int32_t valueIn) {
// TODO implement
return int32_t {};
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
return new Simphw();
}
} // namespace implementation
} // namespace V2_0
} // namespace simple
} // namespace hardware
} // namespace android
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces/simple/2.0/default$ cat Simphw.h
#ifndef ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H #define ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H #include4. run below script to update android mk and bp export PATH=$PATH:/home/leej5/workspace/sapphire/out/host/linux-x86/bin/ ./hardware/interfaces/update-makefiles.sh#include #include namespace android { namespace hardware { namespace simple { namespace V2_0 { namespace implementation { using ::android::hardware::simple::V2_0::ISimphw; using ::android::hidl::base::V1_0::DebugInfo; using ::android::hidl::base::V1_0::IBase; 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 Simphw : public ISimphw { // Methods from ::android::hardware::simple::V2_0::ISimphw follow. Return simpfn(int32_t valueIn) override; // Methods from ::android::hidl::base::V1_0::IBase follow. }; extern "C" ISimphw* HIDL_FETCH_ISimphw(const char* name); } // namespace implementation } // namespace V2_0 } // namespace simple } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
simple/ ├── 2.0 │ ├── Android.bp │ ├── Android.mk │ ├── ISimphw.hal │ └── default │ ├── Android.bp │ ├── Simphw.cpp │ └── Simphw.h └── Android.bpleej5@LeeJ5:~/workspace/sapphire/hardware/interfaces$ cat simple/Android.bp
// This is an autogenerated file, do not edit.
subdirs = [
"2.0",
"2.0/default",
]
2.0/Android.bp
// This file is autogenerated by hidl-gen. Do not edit manually.
filegroup {
name: "android.hardware.simple@2.0_hal",
srcs: [
"ISimphw.hal",
],
}
genrule {
name: "android.hardware.simple@2.0_genc++",
tools: ["hidl-gen"],
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.simple@2.0",
srcs: [
":android.hardware.simple@2.0_hal",
],
out: [
"android/hardware/simple/2.0/SimphwAll.cpp",
],
}
genrule {
name: "android.hardware.simple@2.0_genc++_headers",
tools: ["hidl-gen"],
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.simple@2.0",
srcs: [
":android.hardware.simple@2.0_hal",
],
out: [
"android/hardware/simple/2.0/ISimphw.h",
"android/hardware/simple/2.0/IHwSimphw.h",
"android/hardware/simple/2.0/BnHwSimphw.h",
"android/hardware/simple/2.0/BpHwSimphw.h",
"android/hardware/simple/2.0/BsSimphw.h",
],
}
cc_library_shared {
name: "android.hardware.simple@2.0",
defaults: ["hidl-module-defaults"],
generated_sources: ["android.hardware.simple@2.0_genc++"],
generated_headers: ["android.hardware.simple@2.0_genc++_headers"],
export_generated_headers: ["android.hardware.simple@2.0_genc++_headers"],
vendor_available: true,
shared_libs: [
"libhidlbase",
"libhidltransport",
"libhwbinder",
"liblog",
"libutils",
"libcutils",
"android.hidl.base@1.0",
],
export_shared_lib_headers: [
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
"android.hidl.base@1.0",
],
}
2.0/Android.mk
# This file is autogenerated by hidl-gen. Do not edit manually.
LOCAL_PATH := $(call my-dir)
################################################################################
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.simple-V2.0-java
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
intermediates := $(call local-generated-sources-dir, COMMON)
HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
LOCAL_JAVA_LIBRARIES := \
android.hidl.base-V1.0-java \
#
# Build ISimphw.hal
#
GEN := $(intermediates)/android/hardware/simple/V2_0/ISimphw.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ISimphw.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-Ljava \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
android.hardware.simple@2.0::ISimphw
$(GEN): $(LOCAL_PATH)/ISimphw.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_JAVA_LIBRARY)
################################################################################
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.simple-V2.0-java-static
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
intermediates := $(call local-generated-sources-dir, COMMON)
HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
LOCAL_STATIC_JAVA_LIBRARIES := \
android.hidl.base-V1.0-java-static \
#
# Build ISimphw.hal
#
GEN := $(intermediates)/android/hardware/simple/V2_0/ISimphw.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ISimphw.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-Ljava \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
android.hardware.simple@2.0::ISimphw
$(GEN): $(LOCAL_PATH)/ISimphw.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
5. add empty files to hardware/interfaces/simple/2.0/default:
android.hardware.simple@2.0-service.rc
service.cpp
results
leej5@LeeJ5:~/workspace/sapphire/hardware/interfaces$ tree simple/ simple/ ├── 2.0 │ ├── Android.bp │ ├── Android.mk │ ├── ISimphw.hal │ └── default │ ├── Android.bp │ ├── Simphw.cpp │ ├── Simphw.h │ ├── android.hardware.simple@2.0-service.rc │ └── service.cpp └── Android.bp 2 directories, 9 files6.Implementing the HAL shared object: we need to add a new static function to return the service object (usually as a singleton) Simphw.h
#ifndef ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H #define ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H #includesimple/2.0/default/Simphw.cpp 수정#include #include namespace android { namespace hardware { namespace simple { namespace V2_0 { namespace implementation { using ::android::hardware::simple::V2_0::ISimphw; using ::android::hidl::base::V1_0::DebugInfo; using ::android::hidl::base::V1_0::IBase; 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 Simphw : public ISimphw { // Methods from ::android::hardware::simple::V2_0::ISimphw follow. Return simpfn(int32_t valueIn) override; }; extern "C" ISimphw* HIDL_FETCH_ISimphw(const char* name); } // namespace implementation } // namespace V2_0 } // namespace simple } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
#include "Simphw.h"
namespace android {
namespace hardware {
namespace simple {
namespace V2_0 {
namespace implementation {
// Methods from ::android::hardware::simple::V2_0::ISimphw follow.
Return Simphw::simpfn(int32_t valueIn) {
// TODO implement
return valueIn+100;
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
return new Simphw();
}
} // namespace implementation
} // namespace V2_0
} // namespace simple
} // namespace hardware
} // namespace android
Note that if you want to support pass-through mode, you need to uncomment the HIDL_FETCH_ISimphw function
In this example, we implemented the function as simple as possible (usually we will load the hardware module here)
The generated Android.bp file build a shared library with the implementation – android.hardware.simple@2.0-impl
Creating the Service
To host the library we need to create a simple executable:
service.cpp
#define LOG_TAG "android.hardware.simple@2.0-service" #includeWe create an instance of our implementation, Create a thread pool for the binder and register the current process as a service Note that the function regsiterAsService() is auto-generated by hidl-gen tool To make this service run automatically add init file: android.hardware.simple@2.0-service.rc#include #include "Simphw.h" using android::hardware::simple::V2_0::ISimphw; using android::hardware::simple::V2_0::implementation::Simphw; using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::sp; using android::hardware::defaultPassthroughServiceImplementation; int main() { return defaultPassthroughServiceImplementation (); }
service simphwserv /vendor/bin/hw/android.hardware.simple@2.0-service
class hal
user root
group root
seclabel u:r:su:s0
For testing purpose I set the security label to su , we need to set SE Linux rules (I wrote it in the init.te file):
./yours/sepolicy/block/init.te
allow init vendor_file:file { execute };
allow init su:process { transition };
To tell the build system to build the service add the following to Android.bp (in directory default)
cc_binary {
name: "android.hardware.simple@2.0-service",
defaults: ["hidl_defaults"],
proprietary: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
init_rc: ["android.hardware.simple@2.0-service.rc"],
shared_libs: [
"android.hardware.simple@2.0",
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
],
}
Add the following components to build/make/target/product/emulator.mk
vi build/make/target/product/emulator.mk
PRODUCT_PACKAGES += \
android.hardware.simple@2.0-impl \
android.hardware.simple@2.0-service \
leej5@LeeJ5:~/android/hardware/interfaces/simple$ mm -j16
results
leej5@LeeJ5:~/workspace/sapphire/out/target/product/sapphire_tch/system$ find . -name "*simple*" ./lib/android.hardware.simple@2.0.so leej5@LeeJ5:~/workspace/sapphire/out/target/product/sapphire_tch/vendor$ find . -name "*simple*" ./lib/hw/android.hardware.simple@2.0-impl.so ./etc/init/android.hardware.simple@2.0-service.rc ./bin/hw/android.hardware.simple@2.0-servicesapphire_tch:/ # lshal
All available passthrough implementations (all -impl.so files) Interface Server Clients android.hardware.audio.effect@2.0::I*/* N/A android.hardware.audio@2.0::I*/* N/A android.hardware.bluetooth@1.0::I*/* N/A android.hardware.boot@1.0::I*/* N/A android.hardware.drm@1.0::I*/* N/A android.hardware.graphics.allocator@2.0::I*/* N/A android.hardware.graphics.composer@2.1::I*/* N/A android.hardware.graphics.mapper@2.0::I*/* N/A android.hardware.keymaster@3.0::I*/* N/A android.hardware.light@2.0::I*/* N/A android.hardware.memtrack@1.0::I*/* N/A android.hardware.power@1.0::I*/* N/A android.hardware.renderscript@1.0::I*/* N/A android.hardware.simple@2.0::I*/* N/A android.hardware.soundtrigger@2.0::I*/* N/A android.hardware.thermal@1.0::I*/* N/A android.hardware.tv.cec@1.0::I*/* N/A android.hardware.tv.input@1.0::I*/* N/A android.hidl.memory@1.0::I*/* N/Asapphire_tch:/ # ps -A | grep simp root 7315 1 7180 3376 binder_thread_read a7bed514 S android.hardware.simple@2.0-service sapphire_tch:/ # lshal
All binderized services (registered services through hwservicemanager) Interface Server Clients android.frameworks.displayservice@1.0::IDisplayService/default 3573 3394 android.frameworks.schedulerservice@1.0::ISchedulingPolicyService/default 3780 3394 android.frameworks.sensorservice@1.0::ISensorManager/default 3780 3394 android.hardware.audio.effect@2.0::IEffectsFactory/default 3554 3658 3394 android.hardware.audio@2.0::IDevicesFactory/default 3554 3658 3394 android.hardware.bluetooth@1.0::IBluetoothHci/default 3555 3888 3394 android.hardware.boot@1.0::IBootControl/default 3396 3762 3394 android.hardware.configstore@1.0::ISurfaceFlingerConfigs/default 3556 3394 android.hardware.drm@1.0::ICryptoFactory/default 3557 3394 android.hardware.drm@1.0::ICryptoFactory/widevine 3558 3394 android.hardware.drm@1.0::IDrmFactory/default 3557 3663 3394 android.hardware.drm@1.0::IDrmFactory/widevine 3558 3663 3394 android.hardware.graphics.allocator@2.0::IAllocator/default 3559 3573 3394 android.hardware.graphics.composer@2.1::IComposer/default 3560 3573 3394 android.hardware.keymaster@3.0::IKeymasterDevice/default 3397 3662 3394 android.hardware.light@2.0::ILight/default 3561 3780 3394 android.hardware.media.omx@1.0::IOmx/default 3669 3666 3394 android.hardware.media.omx@1.0::IOmxStore/default 3669 3394 android.hardware.memtrack@1.0::IMemtrack/default 3562 3780 3394 android.hardware.power@1.0::IPower/default 3563 3780 3394 android.hardware.simple@2.0::ISimphw/default 7315 3394
as a simple test, make a binary project to vendor path. vendor/[yours]/simpleTest "servtest.cpp"
#define LOG_TAG "android.hardware.simple@2.0-service" #includeAndroid.bp#include #include #include #include #include #include #include using android::hardware::simple::V2_0::ISimphw; using android::sp; int main() { int res; android::sp ser = ISimphw::getService(); res = ser->simpfn(200); printf("val=%d\n",res); return 0; }
cc_binary {
name: "mysimptest",
defaults: ["hidl_defaults"],
proprietary: true,
srcs: ["servtest.cpp"],
shared_libs: [
"android.hardware.simple@2.0",
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
],
}
Add hal entry to the Manifest.xml file in my case~
add it here "/device/~~/treble.xml"
android.hardware.simple hwbinder 2.0 ISimphw default
# mysimptest
val=300
mysimptest.tgz