HIDL --HelloWorld


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>();
}
這個service是注冊了INaruto接口文件里面的接口,作為binder server端,很簡單就一句話,因為我們使用了passthrough的模式,Android幫我們封裝了這個函數,不需要我們自己去addService啦。


創建test目錄,添加client.cpp文件和bp文件。
Android.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 只用來編寫代碼,編譯要在源碼工程中。
編寫Android.mk.
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;

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM