Android 9.0 HIDL接口添加


注:本文为个人学习记录,可能存在个别或多处错误,欢迎指正和讨论。

参考:
https://www.jianshu.com/p/ca6823b897b5
https://source.android.com/devices/architecture
进行学习。
android9.0 从driver到APP(2)–hardware

一、 接口描述文件创建

1.1 创建HIDL目录

mkdir -p hardware/interfaces/sample/1.0

1.2 创建接口描述文件sample.hal,

/*
 * Copyright (C) 2019 Alex
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.sample@1.0;

interface ISample {

    init();

    close();

    Read(vec<int32_t> val);

    Write(int32_t val);

    getVal(vec<int32_t> val);

    setVal(int32_t val);

};

1.3 生成HAL 相关文件

在Android根目录,使用hidl-gen工具生成HAL 相关文件

hidl-gen -o hardware/interfaces/sample/1.0/default -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sample@1.0

二 、更新Makefile

然后使用脚本来更新Makefile,自动生成 Android.bp

 ./hardware/interfaces/update-makefiles.sh

update-makefiles.sh脚本是SDK自带的。

目录结构:

./
├── Android.bp
├── default
│   ├── Sample.cpp
│   └── Sample.h
└── ISample.hal

在1.0的目录的Android.bp内容如下:

// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
    name: "android.hardware.sample@1.0",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "ISample.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}

三 、 service.cpp相关

3.1 service.cpp创建

在default目录创建 service.cpp
内容可以从其他文件夹中复制过来再修改:
改完之后的内容如下:

/*
 * Copyright (C) 2019 Alex
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "android.hardware.sample@1.0-service"

#include <android/hardware/sample/1.0/ISample.h>
#include <hidl/LegacySupport.h>

using android::hardware::sample::V1_0::ISample;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    return defaultPassthroughServiceImplementation<ISample>();
}

在default 目录创建一个

android.hardware.sample@1.0-service.rc

这个文件是自动启动的时候需要使用。

3.2 Android.bp

default目录没有自动生成Android.bp。
从其他地方拷贝个修改吧

cc_library_shared {
    name: "android.hardware.sample@1.0-impl",
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["Sample.cpp"],

    cflags: [
        "-Wall",
        "-Werror",
    ],

    shared_libs: [
        "liblog",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.hardware.sample@1.0",
    ],

}

cc_binary {
    proprietary: true,
    defaults: ["hidl_defaults"],
    relative_install_path: "hw",
    name: "android.hardware.sample@1.0-service",
    init_rc: ["android.hardware.sample@1.0-service.rc"],
    srcs: ["service.cpp"],

    cflags: [
        "-Wall",
        "-Werror",
    ],

    shared_libs: [
        "liblog",
        "libdl",
        "libutils",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "android.hardware.sample@1.0",
    ],

}

四 、client库代码修改

4.1 Sample.cpp代码修改

我们打开HIDL_FETCH的注释,让我们的HIDL使用Passthrough方式去实现
修改后的Sample.cpp:

/*
 * Copyright (C) 2019 Alex
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "android.hardware.sample@1.0-impl"

#include <log/log.h>

#include <hardware/hardware.h>
#include <hardware/sample.h>

#include "Sample.h"

namespace android {
namespace hardware {
namespace sample {
namespace V1_0 {
namespace implementation {


Sample::Sample(sample_module_t *module) : mModule(module) {
    if (mModule){
		if(mModule->sampleInit){
			mModule->sampleInit(mModule);
		}
	}
}

Sample::~Sample() {
	if (mModule){
		if(mModule->sampleClose){
			mModule->sampleClose(mModule);
		}
	}
    delete(mModule);
}


Return<void> Sample::read(read_cb _hidl_cb) {
	int32_t param =0;
	hidl_vec<int32_t> value;
	if(mModule->sampleRead){
		mModule->sampleRead(mModule,&param);
	}
	value.resize(1);
	value[0] = param;
	_hidl_cb(value);
    return Void();
}

Return<void> Sample::write(int32_t val) {
    if(mModule->sampleWrite){
		mModule->sampleWrite(mModule,val);
	}
    return Void();
}

Return<void> Sample::getVal(getVal_cb _hidl_cb) {
	int32_t param =0;
	hidl_vec<int32_t> value;
    if(mModule->sampleGetval){
		mModule->sampleGetval(mModule,&param);
	}
	value.resize(1);
	value[0] = param;
	_hidl_cb(value);
    return Void();
}

Return<void> Sample::setVal(int32_t val) {
     if(mModule->sampleSetval){
		mModule->sampleSetval(mModule,val);
	}   
    return Void();
}


// Methods from ::android::hidl::base::V1_0::IBase follow.

ISample* HIDL_FETCH_ISample(const char* /* name */) {
	const hw_module_t* hw_module = nullptr;
    sample_module_t* sample_module = nullptr;
    int err = hw_get_module(SAMPLE_HARDWARE_MODULE_ID, &hw_module);
    if (err) {
        ALOGE("hw_get_module %s failed: %d", SAMPLE_HARDWARE_MODULE_ID, err);
        return nullptr;
    }

    if (!hw_module->methods || !hw_module->methods->open) {
        sample_module = reinterpret_cast<sample_module_t*>(
            const_cast<hw_module_t*>(hw_module));
    } else {
        err = hw_module->methods->open(
            hw_module, SAMPLE_HARDWARE_MODULE_ID,
            reinterpret_cast<hw_device_t**>(&sample_module));
        if (err) {
            ALOGE("Passthrough failed to load legacy HAL.");
            return nullptr;
        }
    }
	
    return new Sample(sample_module);
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace sample
}  // namespace hardware
}  // namespace android

4.2 Sample.h

#ifndef ANDROID_HARDWARE_SAMPLE_V1_0_SAMPLE_H
#define ANDROID_HARDWARE_SAMPLE_V1_0_SAMPLE_H

#include <android/hardware/sample/1.0/ISample.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace android {
namespace hardware {
namespace sample {
namespace V1_0 {
namespace implementation {
	
using ::android::hardware::sample::V1_0::ISample;
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 Sample : public ISample {
	
	Sample(sample_module_t* module);
    ~Sample();
    // Methods from ::android::hardware::sample::V1_0::ISample follow.
    Return<void> read(read_cb _hidl_cb) override;
    Return<void> write(int32_t val) override;
    Return<void> getVal(getVal_cb _hidl_cb) override;
    Return<void> setVal(int32_t val) override;

    // Methods from ::android::hidl::base::V1_0::IBase follow.
  private:
    sample_module_t* mModule;
};

// FIXME: most likely delete, this is only for passthrough implementations
 extern "C" ISample* HIDL_FETCH_ISample(const char* name);

}  // namespace implementation
}  // namespace V1_0
}  // namespace sample
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_SAMPLE_V1_0_SAMPLE_H

五 、测试代码

测试中先不用关注rc文件和selinux的权限问题,用root权限去手动起service,然后跑测试程序
测试代码如下:

# include <android/hardware/sample/1.0/ISample.h>
# include <hidl/Status.h>
# include <hidl/LegacySupport.h>
# include <utils/misc.h>
# include <hidl/HidlSupport.h>
# include <stdio.h>

using android::hardware::sample::V1_0::ISample;
using android::sp;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using std::vector;
using ISampleV1_0 = ::android::hardware::sample::V1_0::ISample;
static sp<ISampleV1_0> gSampleHalV1_0 = nullptr;

int main(int /* argc */, char** /* argv */)
{
	int val_write = 0;
	int val_read = 0;
	hidl_vec<int32_t> vec_val;
	
	auto cb = [&vec_val](hidl_vec<int32_t> val) {
		vec_val = val;
	};
    gSampleHalV1_0 = ISampleV1_0::getService();
    if(gSampleHalV1_0 == nullptr) {
        printf("Failed to get service\n");
        return -1;
    }

	val_write = 1024;
    gSampleHalV1_0->write(val_write);
	gSampleHalV1_0->read(cb);
	val_read = vec_val[0];
	printf("[gSampleHalV1_0]: read: %d \n",val_read);
    
	val_write = 2048;
    gSampleHalV1_0->setVal(val_write);
	gSampleHalV1_0->getVal(cb);
	val_read = vec_val[0];
	printf("[gSampleHalV1_0]: getVal: %d \n",val_read);
	
    return 0;
}


六 、运行测试用例的问题解决

6.1 android.hardware.sample@1.0-service 运行中的问题

尝试拷贝

android.hardware.sample@1.0.so
android.hardware.sample@1.0-adapter-helper.so

到system分区,发现是只读的,remount不成功。
修改dts文件,把system也改为可读的,方便调试。
android.hardware.sample@1.0.so
android.hardware.sample@1.0-adapter-helper.so库拷贝到路径:

/system/lib64/

android.hardware.sample@1.0-service复制到

/vendor/bin/hw

测试程序HalSampleV1_0FuncTest 随便路径。

错误1:

 LINK EXECUTABLE "/vendor/bin/hw/android.hardware.sample@1.0-service": library "android.hardware.sample@1.0.so" not found

提示找不到库文件,
尝试修改txt文件:

build/make/target/product/vndk/28.txt
build/make/target/product/vndk/current.txt

增加:

VNDK-core: android.hardware.sample@1.0.so

问题解决。

root权限下运行

# vendor/bin/hw/android.hardware.sample@1.0-service &

打印log:

[1] 1225
console:/ # sample_init[42]:   start
[  434.875720] open sample dev done!
sample_init[61]:   success!

6.2 运行测试用例中的问题

运行测试程序:

HalSampleV1_0FuncTest

打印log:

Failed to get service

manifest文件里添加vendor接口的定义:
临时修改out目录的:
vendor/manifest.xml
增加:

    </hal>
	    <hal format="hidl">
        <name>android.hardware.sample</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ISample</name>
            <instance>default</instance>
        </interface>
    </hal>

复制到板子上的

 /vendor/manifest.xml

运行测试程序:

HalSampleV1_0FuncTest

打印log:

sample_write[109]: start
write [  175.727455] SAMPLE_IOTEST_SETVAL!
1024
sample_read[86]: start
[[  175.733711] SAMPLE_IOTEST_GETVAL!
gSampleHalV1_0]: read: 1024
sample_set_val[130]: start
set_val 2048
sample_get_val[152]: start
get value = 2048
[gSampleHalV1_0]: getVal: 2048

执行正确,结束。
疑惑:manifest.xml 的修改尝试过使用 passthrough的配置,跑不起来,不知道差别在哪里?

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值