HIDL implementation-Android application layer app operation node (take gpio as an example)

In the previous chapter, we talked about how to use JNI to implement the Android application layer app operation node: https://blog.csdn.net/weixin_41486477/article/details/110791176

The previous chapter mentioned that the JNI method cannot be used if CTS certification is required, so this chapter sorts out how to build a Hidl to implement the Android application layer app operation node.

 

The driver and hal (testgpio.default.so) parts are equivalent to the part of JNI implementation. The following focuses on how to build hidl and call it in the framework.

 

1. Build hidl

Create new hardware\interfaces\testgpio\1.0\ITestgpio.hal, generate represents the generated function type, such as int32_t type.

package [email protected];

interface Itestgpio {
  set_gpio_up(int32_t gpio_index) generates (int32_t result);
  set_gpio_down(int32_t gpio_index) generates (int32_t result);
  testgpio_open()generates (int32_t result);
};

Generate catalog file with the help of hidl-gen tool:

1.执行make hidl-gen 先安装工具
2.依次执行
export [email protected]
export LOC=hardware/interfaces/testgpio/1.0/default/
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
./hardware/interfaces/update-makefiles.sh

The generated file is just a template and needs to be modified according to our needs

修改hardware\interfaces\testgpio\1.0\default\Testgpio.h

#ifndef ANDROID_HARDWARE_TESTGPIO_V1_0_TESTGPIO_H
#define ANDROID_HARDWARE_TESTGPIO_V1_0_TESTGPIO_H

#include <android/hardware/testgpio/1.0/ITestgpio.h>
#include <hidl/MQDescriptor.h>
#include <hardware/hardware.h>
#include <hidl/Status.h>
#include "hardware/testgpio.h"

namespace android {
namespace hardware {
namespace testgpio {
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 Testgpio : public ITestgpio {
	Testgpio();
    ~Testgpio();
    // Methods from ::android::hardware::testgpio::V1_0::ITestgpio follow.
    Return<int32_t> set_gpio_up(int32_t gpio_index) override;
    Return<int32_t> set_gpio_down(int32_t gpio_index) override;
    Return<int32_t> testgpio_open() override;
	
    private:
    int openHal();
	testgpio_device_t *mDevice;
	int ret;
    // Methods from ::android::hidl::base::V1_0::IBase follow.

};

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

}  // namespace implementation
}  // namespace V1_0
}  // namespace testgpio
}  // namespace hardware
}  // namespace android

#endif  

Modify hardware\interfaces\testgpio\1.0\default\Testgpio.cpp

#include "Testgpio.h"
#include <utils/Log.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "Testgpio.h"
namespace android {
namespace hardware {
namespace testgpio {
namespace V1_0 {
namespace implementation {
	
static testgpio_device_t* testgpio_device;
// Methods from ::android::hardware::testgpio::V1_0::ITestgpio follow.

Testgpio::Testgpio() {
    //sInstance = this; // keep track of the most recent instance
    ret = openHal();
    if (!ret) {
        ALOGE("Can't open HAL module");
    }
}

Testgpio::~Testgpio() {
    ALOGV("~Testgpio()");
    if (mDevice == nullptr) {
        ALOGE("No valid device");
        return;
    }
    int err;
    if (0 != (err = mDevice->common.close(
            reinterpret_cast<hw_device_t*>(mDevice)))) {
        ALOGE("Can't close fingerprint module, error: %d", err);
        return;
    }
    mDevice = nullptr;
}

Return<int32_t> Testgpio::set_gpio_up(int32_t gpio_index) {
    // TODO implement
    return testgpio_device->set_gpio_up(testgpio_device,gpio_index);
}

Return<int32_t> Testgpio::set_gpio_down(int32_t gpio_index) {
    // TODO implement
    return testgpio_device->set_gpio_down(testgpio_device,gpio_index);
}

Return<int32_t> Testgpio::testgpio_open() {
    // TODO implement
    return testgpio_device->testgpio_open(testgpio_device);
}

int Testgpio::openHal() {
    int err;

    hw_module_t* module;
	hw_device_t* device;

	ALOGE("testgpio,native testgpioOpen ...");

	/* 1. hw_get_module */
    err = hw_get_module(TESTGPIO_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

    if (err == 0) {
		/* 2. get device : module->methods->open */
	    err = module->methods->open(module, NULL, &device);
	    if (err == 0) {
			/* 3. call testgpio_open */
	        testgpio_device = (testgpio_device_t *)device;
			return testgpio_device->testgpio_open(testgpio_device);
	    } else {
		ALOGE("testgpio,open faitestgpio ...");
	        return -1;
    	}
    }else{
	ALOGE("testgpio,get_module faitestgpio ...");
   }
	
    return -1;	
}

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

//ITestgpio* HIDL_FETCH_ITestgpio(const char* /* name */) {
    //return new Testgpio();
//}
//
}  // namespace implementation
}  // namespace V1_0
}  // namespace testgpio
}  // namespace hardware
}  // namespace android

添加hardware\interfaces\testgpio\1.0\default\service.cpp


#define LOG_TAG "[email protected]"

#include <android/log.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <android/hardware/testgpio/1.0/ITestgpio.h>
#include "Testgpio.h"

using android::hardware::testgpio::V1_0::ITestgpio;
using android::hardware::testgpio::V1_0::implementation::Testgpio;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

int main() {
	sp<ITestgpio> service = new Testgpio();
    configureRpcThreadpool(1, true /*callerWillJoin*/);
    if (::android::OK != service->registerAsService()) {
            return 1;
    }
    joinRpcThreadpool();

    return 0; // should never get here
}

Add rc file hardware\interfaces\testgpio\1.0\default\[email protected]

service vendor.testgpio_hal /vendor/bin/hw/[email protected]
    # "class hal" causes a race condition on some devices due to files created
    # in /data. As a workaround, postpone startup until later in boot once
    # /data is mounted.
    class late_start
    user system
    group system input
    writepid /dev/cpuset/system-background/tasks

hardware\interfaces\testgpio\1.0\default\Android.bp

cc_binary  {
    name: "[email protected]",
    defaults: ["hidl_defaults"],
    init_rc: ["[email protected]"],
    vendor: true,
    relative_install_path: "hw",
    // FIXME: this should be 'vendor: true' for modules that will eventually be
    // on AOSP.
    proprietary: true,
    srcs: [
        "Testgpio.cpp",
		"service.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
		"libcutils",
        "liblog",
        "libhidlbase",
        "libhardware",
        "[email protected]",
    ],
}

hardware\interfaces\testgpio\1.0\Android.bp


// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "[email protected]",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "ITestgpio.hal",
    ],
    interfaces: [
        "[email protected]",
    ],
    gen_java: true,
}


 

Enter the hardware\interfaces\testgpio\1.0\ directory, execute mma, need to generate

out\target\product\XXXXXX\vendor\bin\hw\[email protected]

out\target\product\XXXXXX\vendor\lib(64)\hw\[email protected]

The rc file can be included in the compilation with the help of copy_file.

How to call the framework

The main changes are in frameworks\base\services\core\java\com\android\server\TestgpioService.java

package com.android.server;

import android.util.Config;
import android.util.Log;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import android.hardware.testgpio.V1_0.ITestgpio;  //引入hidl的包
import android.hardware.testgpio.ITestgpioService;

public final class TestgpioService extends ITestgpioService.Stub {

     private String TAG = "TestgpioService";
     private ITestgpio mDaemon;
     public TestgpioService(Context context){
		 try {
			 mDaemon = ITestgpio.getService(true);//get service,参数必须为true,不然获取不到
			 } catch (RemoteException e) {
				 e.printStackTrace();
				 }
	}
@Override
    public int setUp(int gpio_index){
		Log.i("TestgpioPlatform", "Testgpio Up");
		try{
			mDaemon.set_gpio_up(gpio_index);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return 0;
	}

    public int setDown(int gpio_index){
		Log.i("TestgpioPlatform", "Testgpio Down");
		try{
			mDaemon.set_gpio_down(gpio_index);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return 0;
	}
}

在frameworks/base/services/core/Android.bp

@@ -44,6 +44,7 @@ java_library_static {
         "android.hardware.vibrator-V1.0-java",
         "android.hardware.configstore-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
 +		 "android.hardware.testgpio-V1.0-java",   //引用hidl库
         "vendor.qti.hardware.servicetracker-V1.0-java",
     ],
 }

Three. Other configuration

1. Configure manifest.xml, there are three places in total, MTK platform should be two

device/qcom/product/manifest.xml

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


device/qcom/common/vendor_framework_compatibility_matrix.xml

<hal format="hidl" optional="true">
        <name>android.hardware.testgpio</name>
        <version>1.0</version>
        <interface>
            <name>ITestgpio</name>
            <instance>default</instance>
        </interface>
</hal>

hardware/interfaces/compatibility_matrices/compatibility_matrix.1.xml

<hal format="hidl" optional="true">
        <name>android.hardware.testgpio</name>
        <version>1.0</version>
        <interface>
            <name>ITestgpio</name>
            <instance>default</instance>
        </interface>
</hal>

2. After adding hidl

分别在
build/make/target/product/vndk/28.txt
build/make/target/product/vndk/current.txt
严格按照字母排列顺序添加:

VNDK-core: [email protected]

Four. Problems encountered during debugging

1.StartService fail

12-09 08:27:19.285  1252  1252 I SystemServer: StartTestgpioService
12-09 08:27:19.290  1252  1252 E SystemServer: Failure starting TestgpioService
12-09 08:27:19.290  1252  1252 E SystemServer: java.util.NoSuchElementException
12-09 08:27:19.290  1252  1252 E SystemServer: 	at android.os.HwBinder.getService(Native Method)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at android.os.HwBinder.getService(HwBinder.java:91)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at android.hardware.testgpio.V1_0.ITestgpio.getService(ITestgpio.java:48)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at android.hardware.testgpio.V1_0.ITestgpio.getService(ITestgpio.java:52)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.server.TestgpioService.<init>(TestgpioService.java:19)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:1377)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.server.SystemServer.run(SystemServer.java:443)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.server.SystemServer.main(SystemServer.java:302)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at java.lang.reflect.Method.invoke(Native Method)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
12-09 08:27:19.290  1252  1252 E SystemServer: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)
12-09 08:27:19.290  1252  1252 D SystemServerTiming: StartTestgpioService took to complete: 5ms

 In TestgpioService.java, mDaemon = ITestgpio.getService(true);//get service, the parameter must be true, otherwise it cannot be obtained

2. The [email protected] service cannot start automatically after booting

You can first execute the following commands under adb shell to manually start the service and verify the function first

cd vendor/bin/hw

./[email protected]  &

Configure the se label of the bin service, even if the seliunx permission has been turned off, as long as the label is configured, other selinux permissions can be debugged when the selinux permission has been turned off.

diff --git a/device/qcom/sepolicy/private/file_contexts b/device/qcom/sepolicy/private/file_contexts
index 1c3e9eb..7cdda39 100755
--- a/device/qcom/sepolicy/private/file_contexts
+++ b/device/qcom/sepolicy/private/file_contexts
@@ -74,3 +74,4 @@
 /data/dpm(/.*)?                                 u:object_r:dpmd_data_file:s0
 /data/misc/qvr(/.*)?                            u:object_r:qvrd_data_file:s0
 /data/misc/mirrorlinkserver(/.*)?               u:object_r:mirrorlink_data_file:s0
+/(vendor|system/vendor)/bin/hw/android\.hardware\.testgpio@1\.0-service       u:object_r:hal_testgpio_exec:s0


新增  /device/qcom/sepolicy/private/hal_testgpio.te
@@ -0,0 +1,5 @@
+type hal_testgpio, domain;
+hal_server_domain(hal_testgpio, hal_fingerprint)//这里hal_fingerprint是我为了快速调试,随便加的系统中已经有的,改成自己的
+
+type hal_testgpio_exec, exec_type, vendor_file_type, file_type;
+init_daemon_domain(hal_testgpio)

3. Error when compiling: VNDK library list has been changed

a.使用 diff 比较 build\make\target\product\vndk\28.txt 和 current.txt 两个文件是否相同,如果不相同,请修改至相同。
b.如果上面两个文件相同,但是仍然报错的话。请查看out/target/product/product_name/obj/PACKAGING/vndk_intermediates/libs.txt文件与上面两个文件是否相同。
如果libs.txt文件与current.txt不相同的话,可能你修改了hardware/interfaces/**/*.bp文件,使用git status查看。

结论:必须保证28.txt、current.txt和 libs.txt 是相同的,如果不相同,则会编译出错。

4. Cannot openHal

添加构造函数,调用openHal

Testgpio::Testgpio() {
    //sInstance = this; // keep track of the most recent instance
    ret = openHal();
    if (!ret) {
        ALOGE("Can't open HAL module");
    }
}

 

Guess you like

Origin blog.csdn.net/weixin_41486477/article/details/110948162