在Android 8.0之后版本上添加Hidl Service

1. 编写hal文件并编译

    在hardware/interfaces/目录下创建led文件夹和基版本1.0,这个版本号分为两部分,major.minor。major版本不变得话,只能添加api,不能修改。

创建ILed.hal和types.hal

hardware/interfaces/led/1.0/ILed.hal


 
 
  1. package android.hardware.led@ 1.0;
  2. interface ILed
  3. {
  4. //get led status
  5. get() generates (LedStatus result);
  6. //set led status
  7. set(LedStatus val) generates(int32_t ret);
  8. getBrightnessRange() generates( bool ret,BrightnessRange range);
  9. setBrightnessValue(vec<int32_t> range) generates( bool ret);
  10. on() ;
  11. off() ;
  12. };
 
 
 

hardware/interfaces/led/1.0/types.hal


 
 
  1. package android.hardware.led@ 1.0;
  2. enum LedStatus : uint32_t {
  3. LED_ON,
  4. LED_OFF,
  5. LED_BAD_VALUE,
  6. };
  7. struct BrightnessRange {
  8. uint32_t min;
  9. uint32_t max;
  10. };

添加完后,执行hardware/interfaces/update-makefiles.sh 会自动生成编译编译脚本,然后在

hardware/interfaces/led/1.0/ 路径下执行mm,会生成所需要得hidl库,接下来我们需要实现hidl interface,供client调用。

 

2. 实现Hidl Interface

首先实现ILed interface的子类ledImpl 得头文件和对应得cpp。

hardware/interfaces/led/1.0/default/ledImpl.h


 
 
  1. #ifndef ANDROID_HARDWARE_LED_V1_0_LED_H
  2. #define ANDROID_HARDWARE_LED_V1_0_LED_H
  3. #include <android/hardware/led/1.0/ILed.h>
  4. #include <hidl/Status.h>
  5. #include <hidl/MQDescriptor.h>
  6. namespace android {
  7. namespace hardware {
  8. namespace led {
  9. namespace V1_0 {
  10. namespace implementation {
  11. using ::android::hardware::led::V1_0::LedStatus;
  12. using ::android::hardware::led::V1_0::BrightnessRange;
  13. using ::android::hardware::led::V1_0::ILed;
  14. using ::android::hardware::hidl_array;
  15. using ::android::hardware::hidl_string;
  16. using ::android::hardware::hidl_vec;
  17. using ::android::hardware::Return;
  18. using ::android::hardware::Void;
  19. using ::android::sp;
  20. struct ledImpl : public ILed {
  21. public:
  22. ledImpl();
  23. Return<LedStatus> get() override ;
  24. Return< int32_t> set(LedStatus val) override;
  25. Return< void> on() override;
  26. Return< void> off() override;
  27. Return< void> getBrightnessRange(getBrightnessRange_cb _hidl_cb) override;
  28. Return< bool> setBrightnessValue( const hidl_vec< int32_t>& range) override;
  29. private:
  30. LedStatus state;
  31. };
  32. extern "C" ILed* HIDL_FETCH_ILed(const char* name);
  33. } // namespace implementation
  34. } // namespace V1_0
  35. } // namespace led
  36. } // namespace hardware
  37. } // namespace android
  38. #endif //ANDROID_HARDWARE_LED_V1_0_LED_H
hardware/interfaces/led/1.0/default/ledImpl.cpp
 
 

 
 
  1. #define LOG_TAG "LedService"
  2. #include <log/log.h>
  3. #include "ledImpl.h"
  4. namespace android {
  5. namespace hardware {
  6. namespace led {
  7. namespace V1_0 {
  8. namespace implementation {
  9. ledImpl::ledImpl() {
  10. state = LedStatus::LED_BAD_VALUE;
  11. ALOGE( "ledImpl Init status:%d", state);
  12. }
  13. Return< void> ledImpl::on() {
  14. state = LedStatus::LED_ON;
  15. ALOGE( "ledImpl on status:%d", state);
  16. return Void();
  17. }
  18. Return< void> ledImpl::off() {
  19. state = LedStatus::LED_OFF;
  20. ALOGE( "ledImpl off status:%d", state);
  21. return Void();
  22. }
  23. Return<LedStatus> ledImpl::get() {
  24. return state;
  25. }
  26. Return< int32_t> ledImpl:: set(LedStatus val) {
  27. if(val == LedStatus::LED_OFF || val == LedStatus::LED_ON)
  28. state = val;
  29. else
  30. return -1;
  31. return 0;
  32. }
  33. Return< void> ledImpl::getBrightnessRange(getBrightnessRange_cb _hidl_cb)
  34. {
  35. ALOGE( "ledImpl getBrightnessRange ");
  36. BrightnessRange range;
  37. range.max = 100;
  38. range.min = 1;
  39. _hidl_cb( true,range);
  40. return Void();
  41. }
  42. Return< bool> ledImpl::setBrightnessValue( const hidl_vec< int32_t>& range)
  43. {
  44. ALOGE( "ledImpl getBrightnessValue ");
  45. auto iter = range.begin();
  46. ALOGE( "ledImpl getBrightnessValue range.begin: %d",*iter);
  47. iter = range.end();
  48. ALOGE( "ledImpl getBrightnessValue range.end: %d",*iter);
  49. ALOGE( "ledImpl getBrightnessValue range.size: %zu",range.size());
  50. return true;
  51. }
  52. ILed* HIDL_FETCH_ILed(const char * /*name*/) {
  53. ALOGE( "ledImpl HIDL_FETCH_ILed ");
  54. return new ledImpl();
  55. }
  56. } // namespace implementation
  57. } // namespace V1_0
  58. } // namespace led
  59. } // namespace hardware
  60. } // namespace android

hardware/interfaces/led/1.0/default/Android.bp


 
 
  1. cc_library_shared {
  2.     name: "android.hardware.led@1.0-impl",
  3.    defaults: [ "hidl_defaults"],
  4.    srcs: [ "ledImpl.cpp"],
  5.    shared_libs: [
  6.         "libhidlbase",
  7.         "libhidltransport",
  8.         "libhardware",
  9.         "liblog",
  10.         "libutils",
  11.         "android.hardware.led@1.0",
  12.   ],
  13. }
  14. cc_binary {
  15.     name: "android.hardware.led@1.0-service",
  16.    init_rc: [ "android.hardware.led@1.0-service.rc"],
  17.    srcs: [ "service.cpp",
  18.       "ledImpl.cpp"],
  19.    shared_libs: [
  20.         "liblog",
  21.         "libhardware",
  22.         "libhidlbase",
  23.         "libhidltransport",
  24.         "libutils",
  25.         "android.hardware.led@1.0",
  26.   ],
  27. }

3. 编写hdil service

  接下来,使用相应功能填写存根并设置守护进程。可以使用passthrough方式和binder方式,示例:

hardware/interfaces/led/1.0/default/service.cpp


 
 
  1. #define LOG_TAG "android.hardware.led@1.0-service"
  2. #include <android/hardware/led/1.0/ILed.h>
  3. #include <hidl/LegacySupport.h>
  4. #include "ledImpl.h"
  5. using android::hardware::led::V1_0::ILed;
  6. using android::hardware::led::V1_0::implementation::ledImpl;
  7. using android::hardware::defaultPassthroughServiceImplementation;
  8. using android::hardware::configureRpcThreadpool;
  9. using android::hardware::joinRpcThreadpool;
  10. using android::sp;
  11. int main() {
  12. #if 0
  13. // Passthrough   dlopen so方式
  14.     return defaultPassthroughServiceImplementation<Iled>();
  15. #else
  16. // Binder 方式
  17.  sp<ILed> service = new ledImpl();
  18.  configureRpcThreadpool( 1, true /*callerWillJoin*/);
  19.     if(android::OK !=  service->registerAsService())
  20.       return 1;
  21.    joinRpcThreadpool();
  22. #endif
  23. }

4. 配置manifest.xml

  add the code to the manifest.xm 以至于hwservicemanager 查找到指定的hidl service

   About HIDL configures

   device/<vendorxxx>/<devicexxx>/manifest.xml


 
 
  1. <hal format="hidl">
  2.     <name>android.hardware.led </name>
  3.     <transport>hwbinder </transport>  //hwbinder 或者passthrough (直通模式)  
  4.     <version>1.0 </version>
  5.     <interface>
  6.     <name>ILed </name>
  7.     <instance>default </instance>
  8.     </interface>
  9.   </hal>

  5. hidl client端调用

  hidl service运行后,可以通过C++和Java两种方式调用,非常方便,通过java直接访问,就省去了jni。

 5.1 实现java调用hidl service的例子

  将以下内容添加到 Android.mk 中:


 
 
  1.  LOCAL_JAVA_LIBRARIES += android.hardware.led-V1.0-java
  2. /*
  3.  LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.led-V1.0-java-static
  4. */

  或将以下内容添加到 Android.bp 中:


 
 
  1.  shared_libs: [
  2.   /* … */
  3.   "android.hardware.led-V1.0-java",
  4. ],

  该库还存在静态版:android.hardware.led-V1.0-java-static。

  将以下内容添加到您的 Java 文件中:


 
 
  1.   import android.hardware.led.V1_0.ILed;
  2. ...
  3.   // retry to wait until the service starts up if it is in the manifest
  4.   ILed server = ILed.getService( /* retry */); // throws NoSuchElementException if not available
  5.  server.on();

 

5.2 实现C++ 调用hidl service的例子

 首先将 HAL 库添加到 makefile 中:


 
 
  1.  Make:LOCAL_SHARED_LIBRARIES += android.hardware.led@1. 0
  2.  Soong:shared_libs: [ …, android.hardware.led@1. 0 ]

 接下来,添加 HAL 头文件:


 
 
  1.   #include <android/hardware/led/1.0/ILed.h>
  2.  …
  3.   // in code:
  4.  sp<ILed> client = ILed::getService();
  5.  client->on();

下面是我的Demo clinet


 
 
  1.  #define LOG_TAG "LED_CLINET"
  2. #include <android/hardware/led/1.0/ILed.h>
  3. #include <log/log.h>
  4. using android::hardware::led::V1_0::ILed;
  5. using android::hardware::led::V1_0::LedStatus;
  6. using android::hardware::led::V1_0::BrightnessRange;
  7. using android::hardware::hidl_vec;
  8. using android::sp;
  9. int main(){
  10. // BrightnessRange range;
  11. sp <ILed> service = ILed::getService();
  12. if( service == nullptr ){
  13. ALOGE("Can't find ILed service...");
  14. return -1;
  15. }
  16. ALOGE("ILed ON");
  17. service->on();
  18. ALOGE("ILed OFF");
  19. service->off();
  20. ALOGE("ILed set");
  21. service->set(LedStatus::LED_ON);
  22. ALOGE("ILed get");
  23. LedStatus ret = service->get();
  24. ALOGE("ILed get: %d",ret);
  25. service->getBrightnessRange([](bool ret1,BrightnessRange range){
  26. ALOGE("ILed getBrightnessRange ret: %d",ret1);
  27. ALOGE("ILed getBrightnessRange Max: %d",range.max);
  28. ALOGE("ILed getBrightnessRange Min: %d",range.min);
  29. });
  30. int32_t array[] = {5, 6, 7};
  31. hidl_vec <int32_t> hv1 = std::vector <int32_t>(array, array + 3);
  32. bool ret2 = service->setBrightnessValue(hv1);
  33. ALOGE("ILed getBrightnessValue bool: %d",ret2);
  34. return 0;
  35. }

6. github地址

 需要看代码的可以去我的github,里面有相关的hidl代码,和C++调用示例

gitHub地址链接

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值