Android 8.0以降にHidl Serviceを追加

9351 ワード

目次
1.halファイルを作成してコンパイルする
2.Hidl Interfaceの実現
3.hdilサービスの作成
4.manifestを構成する.xml
  5. hidlクライアント側呼び出し
5.1 java呼び出しhidlサービスを実現する例
5.2 C++呼び出しhidlサービスを実現する例
6.githubアドレス
本明細書では、プロセス全体を熟知するために、LEDを例にaospにHIDLを追加する.
1.halファイルを作成してコンパイルする
hardware/interfaces/ディレクトリの下にledフォルダとベースバージョン1.0を作成します.このバージョン番号は2つの部分に分かれています.major.minor.majorバージョンが変わらなければapiを追加するしかなく、変更できません.
ILedを作成します....hal
hardware/interfaces/led/1.0/ILed.hal
package [email protected];
 
interface ILed
{
  //get led status 
  get() generates (LedStatus result);
  
  
  //set led status 
  set(LedStatus  val) generates(int32_t  ret);
  
  getBrightnessRange() generates(bool ret,BrightnessRange range);
  
  setBrightnessValue(vec range) generates(bool ret);
  
  on() ;
  
  off() ;
 
};
 

hardware/interfaces/led/1.0/types.hal
package [email protected];


enum LedStatus : uint32_t {
	LED_ON,
	LED_OFF,
	LED_BAD_VALUE,
};


struct BrightnessRange {
    uint32_t min;
 
    uint32_t max;
};

追加が完了したらhardware/interfaces/update-makefilesを実行します.shはコンパイルスクリプトを自動的に生成し、
hardware/interfaces/led/1.0/パスでmmを実行すると、必要なhidlライブラリが生成されます.次に、client呼び出しのためにhidl interfaceを実装する必要があります.
 
2.Hidl Interfaceの実現
まずILed interfaceのサブクラスledImplヘッダファイルと対応するcppを実現する.
hardware/interfaces/led/1.0/default/ledImpl.h
#ifndef ANDROID_HARDWARE_LED_V1_0_LED_H
#define ANDROID_HARDWARE_LED_V1_0_LED_H
#include 

#include 

#include 




namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {

using ::android::hardware::led::V1_0::LedStatus;
using ::android::hardware::led::V1_0::BrightnessRange;
using ::android::hardware::led::V1_0::ILed;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
	
	
struct ledImpl : public ILed {
	public:
		ledImpl();
		Return  get() override ;
		Return set(LedStatus val) override;
		Return on() override;
		Return off() override;
		Return getBrightnessRange(getBrightnessRange_cb _hidl_cb) override;
		Return setBrightnessValue(const hidl_vec& range) override;
	private:
		LedStatus state;
};
	
extern "C" ILed* HIDL_FETCH_ILed(const char* name);
}  // namespace implementation
}  // namespace V1_0
}  // namespace led
}  // namespace hardware
}  // namespace android

#endif //ANDROID_HARDWARE_LED_V1_0_LED_H
hardware/interfaces/led/1.0/default/ledImpl.cpp
#define LOG_TAG "LedService"

#include 
#include "ledImpl.h"

namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {

ledImpl::ledImpl() {
	state = LedStatus::LED_BAD_VALUE;
	ALOGE("ledImpl Init status:%d", state);
}

Return ledImpl::on() {
	state = LedStatus::LED_ON;
	ALOGE("ledImpl on status:%d", state);
    return Void();
}

Return ledImpl::off() {
	state = LedStatus::LED_OFF;
	ALOGE("ledImpl off status:%d", state);	
    return Void();
}

Return  ledImpl::get() {
	return state;
}
Return ledImpl::set(LedStatus val) {
	if(val == LedStatus::LED_OFF || val == LedStatus::LED_ON)
		state = val;
	else
		return -1;
	return 0;
}

Return ledImpl::getBrightnessRange(getBrightnessRange_cb _hidl_cb)
{
	ALOGE("ledImpl getBrightnessRange ");
	BrightnessRange range;
	range.max = 100;
	range.min = 1;
	_hidl_cb(true,range);
	return Void();
	
}
  
Return ledImpl::setBrightnessValue(const hidl_vec& range)
{
	ALOGE("ledImpl getBrightnessValue ");
	auto iter = range.begin();
	ALOGE("ledImpl getBrightnessValue range.begin: %d",*iter);
	iter = range.end();
	ALOGE("ledImpl getBrightnessValue range.end: %d",*iter);
	ALOGE("ledImpl getBrightnessValue range.size: %zu",range.size());
	return true;
}

ILed* HIDL_FETCH_ILed(const char * /*name*/) {
	ALOGE("ledImpl HIDL_FETCH_ILed ");	
    return new ledImpl();
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace led
}  // namespace hardware
}  // namespace android

hardware/interfaces/led/1.0/default/Android.bp
cc_library_shared {
    name: "[email protected]",
    defaults: ["hidl_defaults"],
    srcs: ["ledImpl.cpp"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhardware",
        "liblog",
        "libutils",
        "[email protected]",
    ], 
}

cc_binary {
    name: "[email protected]",
    init_rc: ["[email protected]"],
    srcs: ["service.cpp",
      "ledImpl.cpp"],

    shared_libs: [
        "liblog",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "[email protected]",
    ], 

}

3.hdilサービスの作成
次に、対応する機能を使用してルートを記入し、デーモンプロセスを設定します.passthrough方式とbinder方式を使用できます.例:
hardware/interfaces/led/1.0/default/service.cpp

 #define LOG_TAG "[email protected]"

#include 
#include 
#include "ledImpl.h"
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::implementation::ledImpl;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;


int main() {
#if 0 
// Passthrough   dlopen so  
    return defaultPassthroughServiceImplementation(); 
#else
// Binder   
  sp service = new ledImpl();
  configureRpcThreadpool(1, true /*callerWillJoin*/);
    if(android::OK !=  service->registerAsService())
      return 1; 
    joinRpcThreadpool();
#endif
}

4.manifestを構成する.xml
  add the code to the manifest.xmはhwservicemanagerが指定したhidl serviceを検索するまで
   About HIDL configures
   device///manifest.xml
 
    android.hardware.led
    hwbinder  //hwbinder   passthrough (    )  
    1.0
    
     ILed
     default
    
   

  5. hidlクライアント側呼び出し
hidlサービスが実行されると、C++とJavaの2つの方法で呼び出すことができ、非常に便利でjavaで直接アクセスすることでjniを省くことができます.
5.1 java呼び出しhidlサービスを実現する例
次の内容をAndroidに追加します.mk:
 LOCAL_JAVA_LIBRARIES += android.hardware.led-V1.0-java

/*
 LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.led-V1.0-java-static
*/

または以下の内容をAndroidに追加します.bp:
  shared_libs: [
   /* … */
   "android.hardware.led-V1.0-java",
  ],

このライブラリには静的版:androidも存在する.hardware.led-V1.0-java-static.
Javaファイルに次の内容を追加します.
  import android.hardware.led.V1_0.ILed;
  ...
  // retry to wait until the service starts up if it is in the manifest
  ILed server = ILed.getService(/* retry */); // throws NoSuchElementException if not available
  server.on();

 
5.2 C++呼び出しhidlサービスを実現する例
まず、makefileにHALライブラリを追加します.
  Make:LOCAL_SHARED_LIBRARIES += [email protected]
  Soong:shared_libs: [ …, [email protected] ]

次に、HALヘッダファイルを追加します.
  #include 
  …
  // in code:
  sp client = ILed::getService();
  client->on();

次は私のDemo clinetです
 #define LOG_TAG "LED_CLINET"
#include 
#include 

using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::LedStatus;
using android::hardware::led::V1_0::BrightnessRange;
using android::hardware::hidl_vec;
using android::sp;


int main(){
	// BrightnessRange range;
	sp service = ILed::getService();
	if( service == nullptr ){
		ALOGE("Can't find ILed service...");
		return -1;
	}
	ALOGE("ILed ON");
	service->on();
	
	ALOGE("ILed OFF");
	service->off();
	
	ALOGE("ILed set");
	service->set(LedStatus::LED_ON);

	ALOGE("ILed get");
	LedStatus ret = service->get();
	ALOGE("ILed get: %d",ret);
	
	service->getBrightnessRange([](bool ret1,BrightnessRange range){
		ALOGE("ILed getBrightnessRange ret: %d",ret1);
		ALOGE("ILed getBrightnessRange Max: %d",range.max);
		ALOGE("ILed getBrightnessRange Min: %d",range.min);
	});
	int32_t array[] = {5, 6, 7};
	hidl_vec hv1 = std::vector(array, array + 3);
	bool ret2 = service->setBrightnessValue(hv1);
	ALOGE("ILed getBrightnessValue bool: %d",ret2);
	return 0;
}

6.githubアドレス
コードを見る必要があるのは私のgithubに行って、中には関連するhidlコードがあって、C++呼び出しの例があります
gitHubアドレスリンク