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;

 

 

 

posted @ 2020-08-05 20:33  于光远  阅读(2819)  评论(1编辑  收藏  举报