Android P HAL层添加HIDL实例(详细实现步骤)

Android9 HAL Service 开发(1) 本文将介绍如何在Android P上简单增加绑定式的HAL Service,然后编写一个App直接调用HAL的接口,并使用 aosp_car_x86_64-userdebug 模拟器进行验证。 一 编写.hal文件 .hal的语言格式是C++和Java的结合体。 以hardware/interfaces 为根目录,在这个目录下创建 test/1.0 作为我们编写的服务的工作目录。 1.1 新建types.hal(定义结构体,复杂变量可在此定义) //types.hal package and.. 阅读详情

Android P HAL层添加HIDL实例

本文是参照 https://www.jianshu.com/p/b80865c61d8e 教程介绍实现,原理请参考原作者。

本文将介绍如何在P OS上添加HIDL详细实现过程,简单增加seLinux策略使得可以在system_service调用测试,并用模拟器emulator验证。

调用过程为 APP->TestManager->TestService->ITest.hal

实现过程

一 、hardware部分

1.1 编写 .hal

.hal的语言格式是C++和Java的结合体。

在 AOSP代码目录 hardware/interfaces/test/1.0/

新建 types.hal (非必要,用于定义结构体,复杂变量可在此定义)

//types.hal
package android.hardware.test@1.0;

struct TestID{
	int32_t id;
	string name;
};

struct TestEvent{
	int32_t what;
	string msg;
};

新建ITestCallback.hal (非必要,用于回调使用)

//ITestCallback.hal
package android.hardware.test@1.0;

interface ITestCallback {
   
   
    oneway onTestEvent(TestEvent event);
};

新建 ITest.hal (主接口)

//ITest.hal
package android.hardware.test@1.0;

interface ITest {
   
   
    init(TestID id);
    //无返回值
    helloWorld(string name) generates (string result);
    //变量类型string 不是String
    setCallback(ITestCallback callback) generates (bool res);
    //变量类型bool 不是boolean
    release();
};
1.2 使用hidl-gen生成变量

使用hidl-gen的前提是AOSP全编通过,如果之前全编通过可不用再次全编

source ./build/envsetup.sh
lunch aosp_car_x86_64-eng
make -j4
make hidl-gen -j4

设置临时变量

PACKAGE=android.hardware.test@1.0
LOC=hardware/interfaces/test/1.0/default

使用hidl-gen生成default目录 里的C++文件

hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE

使用hidl-gen生成default目录 里的Android.bp文件

hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE

使用update-makefiles.sh生成1.0目录下的Android.bp

./hardware/interfaces/update-makefiles.sh

在default目录创建

此时的目录结构为

├── 1.0
│   ├── default
│   │   ├── Android.bp
│   │   ├── Test.cpp
│   │   ├── Test.h
│   │   ├── TestCallback.cpp
│   │   └── TestCallback.h
│   ├── Android.bp
│   ├── ITest.hal
│   ├── ITestCallback.hal
│   └── types.hal

TestCallback.cpp和 TestCallback.h没用删掉,并修改default里的Android.bp 删掉TestCallback.cpp

1.3 实现.cpp
Test.h (由hidl-gen工具生成)

line 35 注释打开就是使用passthrough模式

#ifndef ANDROID_HARDWARE_TEST_V1_0_TEST_H
#define ANDROID_HARDWARE_TEST_V1_0_TEST_H

#include <android/hardware/test/1.0/ITest.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <utils/Thread.h>

namespace android {
namespace hardware {
namespace test {
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 Test : public ITest , public Thread{
    // Methods from ::android::hardware::test::V1_0::ITest follow.
    Return<void> init(const ::android::hardware::test::V1_0::TestID& id) override;
    Return<void> helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) override;
    Return<bool> setCallback(const sp<::android::hardware::test::V1_0::ITestCallback>& callback) override;
    Return<void> release() override;

    // Methods from ::android::hidl::base::V1_0::IBase follow.
    virtual bool threadLoop();
};

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

}  // namespace implementation
}  // namespace V1_0
}  // namespace test
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_TEST_V1_0_TEST_H


Test.cpp (由hidl-gen工具生成)

简单实现各个方法

#define LOG_TAG "Test_cpp"
#include "Test.h"
#include <log/log.h>

namespace android {
namespace hardware {
namespace test {
namespace V1_0 {
namespace implementation {
	
pthread_t pthread;
sp<ITestCallback> mCallback = nullptr;
std::string mName;
int32_t mID;
bool mExit;

// Methods from ::android::hardware::test::V1_0::ITest follow.
Return<void> Test::init(const ::android::hardware::test::V1_0::TestID& id) {
    mExit = false;
	mName = id.name;
	mID = id.id;
	ALOGD("init:");
	run("test_thread");
    return Void();
}

Return<void> Test::helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) {
	ALOGD("helloWorld:");
	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<bool> Test::setCallback(const sp<::android::hardware::test::V1_0::ITestCallback>& callback) {
	mCallback = callback;
	bool res = false;
    if(mCallback != nullptr) {
        ALOGD("setCallback: done");
		res = true;
    }
    return res;
}

Return<void> Test::release() {
	mExit = true;
	ALOGD("release:");
    return Void();
}

bool Test::threadLoop(){
     static int32_t count = 0;
     TestEvent event;
     while(!mExit) {
         ::sleep(1);
		 event.msg = mName;
         event.what = count ++;
         if(mCallback != nullptr) {
             mCallback->onTestEvent(event);
         }
     }
     ALOGD("threadLoop: exit");
	 return false;
}

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

//ITest* HIDL_FETCH_ITest(const char* /* name */) {
    //return new Test();
//}
//
}  // namespace implementation
}  // namespace V1_0
}  // namespace test
}  // namespace hardware
}  // namespace android

添加启动service

新建android.hardware.test@1.0-service.rc 启动脚本

service test_hal_service /vendor/bin/hw/android.hardware.test@1.0-service
    class hal
    user system
    group system

新建service.cpp 这里使用绑定式 直通式为注释部分

#define LOG_TAG "android.hardware.test@1.0-service"
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <android/hardware/test/1.0/ITest.h>

#include <hidl/LegacySupport.h>
#include "Test.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::test::V1_0::implementation::Test;
//using android::hardware::defaultPassthroughServiceImplementation;
//passthrough mode

int main() {
	configureRpcThreadpool(4, true);

    Test test;
    auto status = test.registerAsService();
    CHECK_EQ(status, android::OK) << "Failed to register test HAL implementation";

    joinRpcThreadpool();
    return 0;  // joinRpcThreadpool shouldn't exit
 //   return defaultPassthroughServiceImplementation<ITest>();
 //passthrough mode
}

修改Android.bp

cc_binary {
    name: "android.hardware.test@1.0-service",
    relative_install_path: "hw",
    defaults: ["hidl_defaults"],
    proprietary: true,
    init_rc: ["android.hardware.test@1.0-service.rc"],
    srcs: [
		   "Test.cpp",
	       "service.cpp",
	      ],
    shared_libs: [
		"libbase",      
        "liblog",
        "libdl",
        "libutils",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "android.hardware.test@1.0",
    ],
}

调用 update-makefiles.sh更新一下

当前目录结构为

├── 1.0
│   ├── default
│   │   ├── Android.bp
│   │   ├── Test.cpp
│   │   ├── Test.h
│   │   ├── android.hardware.test@1.0-service.rc
│   │   └── service.cpp
│   ├── Android.bp
│   ├── ITest.hal
│   ├── ITestCallback.hal
│   └── types.hal

单编试一下 ,出错请检查代码请参考附录解决办法。

mmm ./hardware/interfaces/test/1.0

[外链图片转存失败(img-pGZeVrJ7-1563157041998)(C:\Users\GW00175635\AppData\Roaming\Typora\typora-user-images\1562749332399.png)]

1.4 VNDK相关

在目录aosp\build\make\target\product\vndk 里

28.txt 和 current.txt 按照字母顺序新增

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

二、device部分

由于此次要使用emulator验证,并且lunch的是aosp_car_x86_64-eng

所以在device找到下面目录aosp\device\generic\car\common\manifest.xml

其他device要在对应的目录找到manifest

在manifest.xml添加

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

在car.mk添加 启动 test service

# Auto modules
PRODUCT_PACKAGES += \
   ……
	android.hardware.test@1.0-service

三、SELinux部分——hal service

根据其他博主的文章搜集了一些SELinux的知识点进行补充:
对应sepolicy, Google 也设定了不同的存放目录, 以便进行分离, 以Google 默认的sepolicy 为例. /system/sepolicy

public: android 和 vendor 共享的sepolicy 定义, 通常情况下, 意味着vendor 开发者可能为此新增一些权限. 一般system/vendor 共用的一些类型和属性的定义, neverallow 限制等会存放于此.

private: 通常意义上的仅限于system image 内部的使用, 不对vendor 开放. 这个只会编译到system image 中.

vendor: 它仅仅能引用public 目录下的相关定义, 这个只会编译到vendor image 中. 但它依旧可以对system image 里面的module 设定sepolicy(对应module 需要在public 下进行声明); 在很大程度上绕过了Google GTS 约束测试.

mapping: 为兼容老版本的sepolicy 而导入, 只有在system image version > vendor version 的时候, 才可能被用到. 即包括两方面, 新版本增加的type , 新版本移除的type, 以及老版本public, 新版本private 等变化的设定, 以兼容老版本.

9.0上Android 安全策略再次加强,hal service需要修改selinux配置

lunch为 aosp_car_x86_64-eng 对应的car device目录下没有BoardConfig.mk,也没有对应的sepolicy

所以只能修改系统的sepolicy

目录为aosp\system\sepolicy

该目录下有vendor public private(注意public 下的修改同样也要修改到prebuilts\api\28.0 下的对应文件,否则编译会报错) 位置找不到参考audiocontrol的位置 或者比较熟悉的hal模块

3.1 vendor 目录

file_contexts 添加

/(vendor|system/vendor)/bin/hw/android\.hardware\.test@1\.0-service          u:object_r:hal_test_default_exec:s0
#file_contexts文件保存系统中所有文件的安全上下文定义,每行前半部分是文件的路径,后面是它的安全上下文的定义(hal_test_default_exec)

新建 hal_test_default.te
在TE中,所有的东西都被抽象成类型。进程,抽象成类型;资源,抽象成类型。属性,是类型的集合。所以,TE规则中的最小单位就是类型。

#定义一个 名字为 hal_test_default 的type
#TYPE是定义主体和客体所属的类型,对于进程而言,它的类型也称为domian。
#通常主体的type具有domian属性,因此,我们也把主体的type称为domain,将domain设置为hal_test_default的属性,表明zygote是用来描述进程的安全上下文的。

# Set a new domain called hal_test_default
type hal_test_default, domain;
# Set your domain as server domain of hal_xxx in which define by AOSP already
hal_server_domain(hal_test_default, hal_test)

# Set your exec file type
type hal_test_default_exec, exec_type, vendor_file_type, file_type;
# Setup for domain transition
init_daemon_domain(hal_test_default)

3.2 public 目录

attributes 添加

hal_attribute(test);

hwservice.te 添加

type hal_test_hwservice, hwservice_manager_type;

新建 hal_test.te

# HwBinder IPC from client to server, and callbacks
binder_call(hal_test_client, hal_test_server)
binder_call(hal_test_server, hal_test_client)

add_hwservice(hal_test_server, hal_test_hwservice)

allow hal_test_client hal_test_hwservice:hwservice_manager find;

将以上修改同步到aosp\system\sepolicy\prebuilts\api\28.0\public

3.3 private 目录

hwservice_contexts 添加

android.hardware.test::ITest                                    u:object_r:hal_test_hwservice:s0

private/compat/26.0/26.0.ignore.cil 添加

hal_test_hwservice

private/compat/27.0/27.0.ignore.cil 添加

hal_test_hwservice

将以上修改同步到aosp\system\sepolicy\prebuilts\api\28.0\private

四 、客户端实现

4.1 system_service 实现
4.1.1 TestManager端

在目录aosp\frameworks\base\core\java\android\os里 新建test目录

创建ITestService.aidl 对应hal层 四个功能

// ITestManager.aidl
package android.os
Android9 Audio模块Hal加载流程及修改方法 摘要:在Android9中Audio模块调用Hal一般有两种路径: 1.通过AudioFlinger调用到Hal,这是众多原生接口走的路径,一般我们不会在这里增加方法,但是会修改这里面的方法 2.因为是车机,所以可以通过CarAudioService.java直接跳过JNI和Native直接到达Hal,完成一些需要硬件支持的工作,一般我们会将新增的非原生方法增加到这里面,所谓自定义Hal指的就是在这里面新增的接口 一、通过AudioFlinger调用Hal的流程 以AudioRecord.java中的. 阅读详情

相关推荐

android R的一些selinux配置经验分享

android R的selinux配置

qq_27629673的博客 3216

Android SELinux

宏,将domain域和(hal_xxx_client )属性关联,system_server作为Hal服务客户端示例:hal_client_domain(system_server, hal_foo)宏,将domain域和(hal_xxx_server )属性关联,A HAL server关联域示例:hal_server_domain(my_hal_domain, hal_foo)示例,hal服务服务端属性。

shuizhizhiyin的专栏 1831

Android HIDL学习 - HelloWord入门(整理1)

Android HIDL学习(整理1)概述入手准备实例应用1.HIDL接口文件定义2. 生成HAL相关文件3. 实现HAL服务端的共享库4. Hal server端启动注册程序5.HIDL Client端测试程序6.测试实例 概述 HAL 接口定义语言(简称 HIDL,发音为“hide-l”)是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)HIDL 允许指定类型和方法调用(会汇集到接口和软件包中)。从更广泛的意义上来说,HIDL 是用于在可以独立编译的代码库之间进行通信的系统。 HID

sevenjoin的博客 9782

Android R(11)创建自定义HIDL接口--ICustomHardware()

创建自定义HIDL接口–ICustomHardware 1.定义包名 package flagstaff.hardware.custom_hardware@1.0;   HIDL的定义风格总体和cpp是相似的,此处的package也就对应cpp的命名空间,如果是使用cpp来实现后端,那么接口对应的命名空间如下 using flagstaff::hardware::custom_hardware::V1_0::ICustomHardware;   在HIDL接口中,包名的定义规则如下 <packag

flagstaff's blogs 2819

Android P HAL添加HIDL实例

default 是新生成的目录,Test.cpp和Test.h是新生成的两个文件,打开Test.h文件,去掉// extern "C" IGunder* HIDL_FETCH_ITest(const char* name);5.在hardware/interfaces/test/1.0/default目录下新建service.cpp跟android.hardware.test@1.0-service.rc,其中android.hardware.test@1.0-service.rc是程序的入口函数。

xiaowang_lj的博客 908

3.安卓访问驱动-service

文章目录一.前言二.实现过程2.1 编写.hal文件2.2 实现cpp.h文件三. 实现server端的共享库四.实现server端的进程五.HIDL-Client端代码测试5.1 创建测试文件hello.cpp5.2 Android.mk5.3 修改manifest5.4 将生成物推进机器里面5.5 手动执行sevice 一.前言 HIDL 读作 hide-l,全称是 Hardware Interface Definition Language,是一种接口定义语言,它在 Android Project

weixin_43824344的博客 1352

01.HIDL新手入门

Android 架构 - HIDL Android的安全机制(SEANDROID) linux IO 几种穿透模式解析 AndroidO Treble架构分析1 JNI详解---从不懂到理解 JNI战(一):JNI HelloWorld android 自定义驱动(第三篇:HIDL服务端) HIDL 使用方式 ANDROID P HAL添加HIDL实例 ANDROID SEPOLICY简要记 /system/hwservicemanag

chylovecsd的博客 248

Android HIDL 实例

前言: 从Android HIDL 详解一文得知HIDL 使用passthrough 模式,为了与原来的HAL 版本兼容。除了passthrough 模式,还有一种binderized模式。本文通过HIDL 中的Helloworld 进行实例分析,进一步了解HIDL 使用。 本文source code 基于Android P。 Step 1 确定环境 Android HIDL 编程......

私房菜 2万+

Android P之Camera HAL3流程分析(0)

目录 参考文献 注册CameraProvider服务 注册cameraserver服务 类和服务调用 参考文献 [Android O] Camera 服务启动流程简析[Android O] HAL3 之 Open Camera2 流程(零)—— 概览[Android O] HAL3 之 Open Camera2 流程(一)—— 从 App 到 CameraService[Android...

Vincentywj的博客 1万+

Android HIDL概述与绑定模式的实现

Android HIDL 介绍与示例

lzz214的博客 2753

HIDL概述

HIDL背景 Treble 是 Google Android 团队的一项重大项目,意在 Android 操作系统框架在架构方面的一项重大改变,旨在让制造商以更低的成本更轻松、更快速地将设备更新到新版 Android 系统Android 7.x 及更早版本中没有正式的供应商接口,因此设备制造商必须更新大量 Android 代码才能将设备更新到新版 Android 系统: 图1 Treble ...

u013357557的专栏 2万+

android HAL 教程(含实例

  http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html   Android Hal 分析                            &nbsp.

Neil驱动的博客 7258

嵌入式践教程--Android HAL自定义HAL代码教程

HIDL接口定义 创建hidl目录 在aosp中的hardware/interfaces目录下创建自己的hal目录 mkdir -p hardware/interfaces/qmiller/1.0/default 创建hal文件 在我们刚才创建的hardware/interfaces/qmiller/1.0/目录下新建IQmiller.hal文件,传入string name,返回string类型的result。 package android.hardware.qmiller@1.0; ...

转载和创作优秀的博客 1425

安卓HAL开发指南

安卓HAL开发指南 1、介绍 HIDL的全称是HAL interface definition language(硬件抽象接口定义语言),在此之前Android 有AIDL,架构在Android binder 之上,用来定义Android 基于Binder通信的Client 与Service之间的接口。HIDL也是类似的作用,只不过定义的是Android Framework与Android HAL实现之间的接口。 2、实现方式 2.1 旧版 传统HAL Android 7.x和更早的版本中,hal

qq_38226902的博客 1万+

Android-HALHIDL分析使用总结

Android-HALHIDL分析使用总结 HAL接口定义语言(简称HIDL)适用于指定HAL和其用户之间的接口的一种接口描述语言(IDL),HIDL允许指定类型和方法调用。 HIDL旨在用于进程间通信(IPC)。进程之间的通信经过Binder化。对于必须与进程相关联的代码库,还可以使用直通模式。 HIDL可指定数据结构和方法签名,这些内容会整理归类到接口中,而接口会汇集到软件包中。 尽管HIDL具有一系不同的关键字,C++和JAVA程序员对HIDL的语法并不陌生。此外,HIDL还是用JAVA样式和注

转载和创作优秀的博客 3932

android添加hidl服务,HIDL  |  Android 开源项目  |  Android Open Source Project

HAL 接口定义语言(简称 HIDL,发音为“hide-l”)是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)HIDL 允许指定类型和方法调用(会汇集到接口和软件包中)。从更广泛的意义上来说,HIDL 是用于在可以独立编译的代码库之间进行通信的系统HIDL 旨在用于进程间通信 (IPC)。进程之间的通信采用 Binder 机制。对于必须与进程相关联的代码库,还可以使用直通模...

weixin_30999669的博客 507

Android系统HAL分析 (1)-- HAL的架构分析

Android 系统的硬件访问服务通常运行在 SystemServer 中,而使用这些硬件访问服务的应用程序运行在另外的进程中,即应用程序需要通过进程间通信机制来访问这些硬件访问服务。Android 系统提供了一种高效的进程间通信机制——Binder 进程间通信机制,应用程序就是通过它来访问运行在 SystemServer 中的硬件访问服务的。Binder 进程间通信机制要求提供服务的一方必须实现一个具有跨进程访问能力的服务接口,以便使用服务的一方可以通过这个服务接口来访问它。

Android系统工程师--小馬佩德罗 7714
上一篇: 百度语音唤醒错误解决一例 params :{"error":11,"desc":"Wakeup exception","sub_error":11004}
下一篇: Logutil日志工具
赶快去学习
博客等级 码龄12年 102粉丝 12原创
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值