HIDL Hal 开发笔记3----Binderized HALs 实例分析

目录

  • 一、整体框架
  • 二、HAL 层服务端实现
  • 三、Framework 层客户端实现

Binderized HALs 实例分析

一、整体框架

对于Binderized HALs,HAL 层以进程的形式存在,内部有一个HwBinder服务端对象,对外提供HwBinder远程调用服务。Framework 通过HwBinder远程调用到 HAL 中的函数,这些函数直接访问具体的驱动。


在源码下device/google/coral/vibrator/目录下,是 Google 为 pixel4、pixel4 xl 实现的振动器 HAL,其类型就是 Binderized HALs。本文分析其具体实现


二、HAL 层服务端实现

HAL 层表现为一个进程:

进程对应的代码位于device/google/coral/vibrator

整体结构如下:

我们从 Android.bp 下手:

cc_defaults{name:"android.hardware.vibrator@1.3-defaults.coral",defaults:["hidl_defaults"],relative_install_path:"hw",shared_libs:["libhidlbase","libcutils","libhidltransport","liblog","libhwbinder","libutils","libhardware","android.hardware.vibrator@1.0","android.hardware.vibrator@1.1","android.hardware.vibrator@1.2","android.hardware.vibrator@1.3",],}cc_defaults{name:"PtsVibratorHalFloralDefaults",defaults:["android.hardware.vibrator@1.3-defaults.coral"],static_libs:["android.hardware.vibrator@1.3-impl.coral"],test_suites:["general-tests","pts",],multilib:{lib32:{suffix:"32",},lib64:{suffix:"64",},},}cc_library{name:"android.hardware.vibrator@1.3-impl.coral",defaults:["android.hardware.vibrator@1.3-defaults.coral"],srcs:["Hardware.cpp","Vibrator.cpp",],export_include_dirs:["."],vendor_available:true,}cc_binary{name:"android.hardware.vibrator@1.3-service.coral",defaults:["android.hardware.vibrator@1.3-defaults.coral"],init_rc:["android.hardware.vibrator@1.3-service.coral.rc"],vintf_fragments:["android.hardware.vibrator@1.3-service.coral.xml"],srcs:["service.cpp"],static_libs:["android.hardware.vibrator@1.3-impl.coral"],proprietary:true,}

一个共享库android.hardware.vibrator@1.3-impl.coral,一个 native 可执行程序android.hardware.vibrator@1.3-service.coral

  • android.hardware.vibrator@1.3-impl.coral共享库中 :
  • Hardware.cpp 中对振动器驱动的访问包装成了两个对象HwApi HwCal
  • Vibrator.cpp 链接了android.hardware.vibrator@1.3库,内部有一个 Vibrator类,继承自android.hardware.vibrator@1.3库中 IVibrator,IVibrator 是由hardware/interfaces/vibrator/1.3/IVibrator.hal编译出来的。Vibrator 类是一个HwBinder服务端类,对外提供了调用振动器的接口,内部实现是通过调用HwApi HwCal对象的成员函数实现的。
  • android.hardware.vibrator@1.3-service.coral可执行程序:
status_tregisterVibratorService(){sp<Vibrator>vibrator=newVibrator(std::make_unique<HwApi>(),std::make_unique<HwCal>());returnvibrator->registerAsService();}intmain(){configureRpcThreadpool(1,true);status_tstatus=registerVibratorService();if(status!=OK){returnstatus;}joinRpcThreadpool();}

实现上很简单:

  • 向 HwServiceManager 注册 Vibrator
  • 配置 HwBinder 线程

具体振动器的操作细节就不看了,这不是我们的重点。


三、Framework 层客户端实现

对于客户端,我们只要知道 Hal 对外提供的接口即可,这个接口由hardware/interfaces/vibrator/1.3/IVibrator.hal描述:

package android.hardware.vibrator@1.3;import @1.0::EffectStrength;import @1.0::Status;import @1.2::IVibrator;interface IVibrator extends @1.2::IVibrator{supportsExternalControl()generates(bool supports);setExternalControl(bool enabled)generates(Status status);perform_1_3(Effect effect,EffectStrength strength)generates(Status status,uint32_tlengthMs);};

frameworks/base/services/core/java/com/android/server/VibratorService.java本身是一个 Binder 服务端向 App 提供服务,同时也是一个HwBinder客户端通过 JNI 访问到 HAL 服务端。

publicclassVibratorServiceextendsIVibratorService.StubimplementsInputManager.InputDeviceListener{// ......staticnativebooleanvibratorExists();staticnativevoidvibratorInit();staticnativevoidvibratorOn(longmilliseconds);staticnativevoidvibratorOff();staticnativebooleanvibratorSupportsAmplitudeControl();staticnativevoidvibratorSetAmplitude(intamplitude);staticnativelongvibratorPerformEffect(longeffect,longstrength);staticnativebooleanvibratorSupportsExternalControl();staticnativevoidvibratorSetExternalControl(booleanenabled);// ......}

VibratorService 中有多个 native 方法,这些方法用于远程调用 Hal 层。

对应的 JNI 函数实现在frameworks/base/services/core/jni/com_android_server_VibratorService.cpp

#defineLOG_TAG"VibratorService"#include<android/hardware/vibrator/1.0/IVibrator.h>#include<android/hardware/vibrator/1.0/types.h>#include<android/hardware/vibrator/1.0/IVibrator.h>#include<android/hardware/vibrator/1.1/types.h>#include<android/hardware/vibrator/1.2/IVibrator.h>#include<android/hardware/vibrator/1.2/types.h>#include<android/hardware/vibrator/1.3/IVibrator.h>#include"jni.h"#include<nativehelper/JNIHelp.h>#include"android_runtime/AndroidRuntime.h"#include<utils/misc.h>#include<utils/Log.h>#include<hardware/vibrator.h>#include<inttypes.h>#include<stdio.h>using android::hardware::Return;using android::hardware::vibrator::V1_0::EffectStrength;using android::hardware::vibrator::V1_0::Status;using android::hardware::vibrator::V1_1::Effect_1_1;namespace V1_0=android::hardware::vibrator::V1_0;namespace V1_1=android::hardware::vibrator::V1_1;namespace V1_2=android::hardware::vibrator::V1_2;namespace V1_3=android::hardware::vibrator::V1_3;namespace android{staticconstexprintNUM_TRIES=2;// Creates a Return<R> with STATUS::EX_NULL_POINTER.template<class R>inlineReturn<R>NullptrStatus(){using::android::hardware::Status;returnReturn<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};}// Helper used to transparently deal with the vibrator HAL becoming unavailable.template<class R,class I,class...Args0,class...Args1>Return<R>halCall(Return<R>(I::*fn)(Args0...),Args1&&...args1){// Assume that if getService returns a nullptr, HAL is not available on the// device.staticsp<I>sHal=I::getService();staticbool sAvailable=sHal!=nullptr;if(!sAvailable){returnNullptrStatus<R>();}// Return<R> doesn't have a default constructor, so make a Return<R> with// STATUS::EX_NONE.using::android::hardware::Status;Return<R>ret{Status::fromExceptionCode(Status::EX_NONE)};// Note that ret is guaranteed to be changed after this loop.for(inti=0;i<NUM_TRIES;++i){ret=(sHal==nullptr)?NullptrStatus<R>():(*sHal.*fn)(std::forward<Args1>(args1)...);if(ret.isOk()){break;}ALOGE("Failed to issue command to vibrator HAL. Retrying.");// Restoring connection to the HAL.sHal=I::tryGetService();}returnret;}template<class R>boolisValidEffect(jlong effect){if(effect<0){returnfalse;}R val=static_cast<R>(effect);autoiter=hardware::hidl_enum_range<R>();returnval>=*iter.begin()&&val<=*std::prev(iter.end());}staticvoidvibratorInit(JNIEnv/* env */,jobject/* clazz */){halCall(&V1_0::IVibrator::ping).isOk();}staticjbooleanvibratorExists(JNIEnv*/* env */,jobject/* clazz */){returnhalCall(&V1_0::IVibrator::ping).isOk()?JNI_TRUE:JNI_FALSE;}staticvoidvibratorOn(JNIEnv*/* env */,jobject/* clazz */,jlong timeout_ms){Status retStatus=halCall(&V1_0::IVibrator::on,timeout_ms).withDefault(Status::UNKNOWN_ERROR);if(retStatus!=Status::OK){ALOGE("vibratorOn command failed (%"PRIu32").",static_cast<uint32_t>(retStatus));}}staticvoidvibratorOff(JNIEnv*/* env */,jobject/* clazz */){Status retStatus=halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);if(retStatus!=Status::OK){ALOGE("vibratorOff command failed (%"PRIu32").",static_cast<uint32_t>(retStatus));}}staticjlongvibratorSupportsAmplitudeControl(JNIEnv*,jobject){returnhalCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);}staticvoidvibratorSetAmplitude(JNIEnv*,jobject,jint amplitude){Status status=halCall(&V1_0::IVibrator::setAmplitude,static_cast<uint32_t>(amplitude)).withDefault(Status::UNKNOWN_ERROR);if(status!=Status::OK){ALOGE("Failed to set vibrator amplitude (%"PRIu32").",static_cast<uint32_t>(status));}}staticjbooleanvibratorSupportsExternalControl(JNIEnv*,jobject){returnhalCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);}staticvoidvibratorSetExternalControl(JNIEnv*,jobject,jboolean enabled){Status status=halCall(&V1_3::IVibrator::setExternalControl,static_cast<uint32_t>(enabled)).withDefault(Status::UNKNOWN_ERROR);if(status!=Status::OK){ALOGE("Failed to set vibrator external control (%"PRIu32").",static_cast<uint32_t>(status));}}staticjlongvibratorPerformEffect(JNIEnv*,jobject,jlong effect,jint strength){Status status;uint32_tlengthMs;autocallback=[&status,&lengthMs](Status retStatus,uint32_tretLengthMs){status=retStatus;lengthMs=retLengthMs;};EffectStrengtheffectStrength(static_cast<EffectStrength>(strength));Return<void>ret;if(isValidEffect<V1_0::Effect>(effect)){ret=halCall(&V1_0::IVibrator::perform,static_cast<V1_0::Effect>(effect),effectStrength,callback);}elseif(isValidEffect<Effect_1_1>(effect)){ret=halCall(&V1_1::IVibrator::perform_1_1,static_cast<Effect_1_1>(effect),effectStrength,callback);}elseif(isValidEffect<V1_2::Effect>(effect)){ret=halCall(&V1_2::IVibrator::perform_1_2,static_cast<V1_2::Effect>(effect),effectStrength,callback);}elseif(isValidEffect<V1_3::Effect>(effect)){ret=halCall(&V1_3::IVibrator::perform_1_3,static_cast<V1_3::Effect>(effect),effectStrength,callback);}else{ALOGW("Unable to perform haptic effect, invalid effect ID (%"PRId32")",static_cast<int32_t>(effect));return-1;}if(!ret.isOk()){ALOGW("Failed to perform effect (%"PRId32")",static_cast<int32_t>(effect));return-1;}if(status==Status::OK){returnlengthMs;}elseif(status!=Status::UNSUPPORTED_OPERATION){// Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor// doesn't have a pre-defined waveform to perform for it, so we should just give the// opportunity to fall back to the framework waveforms.ALOGE("Failed to perform haptic effect: effect=%"PRId64", strength=%"PRId32", error=%"PRIu32").",static_cast<int64_t>(effect),static_cast<int32_t>(strength),static_cast<uint32_t>(status));}return-1;}staticconstJNINativeMethod method_table[]={{"vibratorExists","()Z",(void*)vibratorExists},{"vibratorInit","()V",(void*)vibratorInit},{"vibratorOn","(J)V",(void*)vibratorOn},{"vibratorOff","()V",(void*)vibratorOff},{"vibratorSupportsAmplitudeControl","()Z",(void*)vibratorSupportsAmplitudeControl},{"vibratorSetAmplitude","(I)V",(void*)vibratorSetAmplitude},{"vibratorPerformEffect","(JJ)J",(void*)vibratorPerformEffect},{"vibratorSupportsExternalControl","()Z",(void*)vibratorSupportsExternalControl},{"vibratorSetExternalControl","(Z)V",(void*)vibratorSetExternalControl},};intregister_android_server_VibratorService(JNIEnv*env){returnjniRegisterNativeMethods(env,"com/android/server/VibratorService",method_table,NELEM(method_table));}};

所有的函数都通过halcall来实现,halcall中会去从 HwServiceManager 中去获取Vibrator Hal的代理对象,然后通过这个代理对象发起远程调用,从而调用到 HAL 层。

最后我们再来看 HAL 端的 VINTF 配置文件/Project/android-10.0.0_r41/device/google/coral/vibrator/android.hardware.vibrator@1.3-service.coral.xml

<manifest version="1.0"type="device"><hal format="hidl"><name>android.hardware.vibrator</name><transport>hwbinder</transport><version>1.3</version><interface><name>IVibrator</name><instance>default</instance></interface></hal></manifest>

注意这里 transport 指定了 hal 的类型为 hwbinder,也就是我们说的Binderized hal


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1119801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可信:“AI+Data”时代企业落地的生死线与破局之道

数据可信&#xff1a;“AIData”时代企业落地的生死线与破局之道在 AI 技术迅猛发展但企业智能化转型落地效果欠佳的背景下&#xff0c;Yolanda 科技见闻与矩阵起源联合直播聚焦 “数据可信” 主题&#xff0c;多位专家指出当前企业 AI 落地核心瓶颈已转向数据与知识的质量与供…

别再装一堆客户端了!

Mac用户的文件传输"终极方案"探索&#xff1a;这款工具深度测评与效率工作流搭建在苹果电脑系统生态中&#xff0c;如何选择一款功能全面、使用高效且界面简洁的文件传输管理软件&#xff0c;一直是许多开发人员、设计人员和技术运维工作者关注的课题。今天&#xff…

【异常】Spring Ai Alibaba 流式输出卡住无响应的问题

Spring Ai Alibaba 流式输出卡住无响应的问题关键点RestClientCustomizerWebClientCustomizer 重点 流式输出使用这个// 定义全局WebClientBeanpublic WebClientCustomizer webClientCustomizer() {ConnectionProvider providerWeb ConnectionProvider.builder("webClien…

商联达云成本优化实战:精细化资源调度与管理,助力企业降本增效

在数字化转型浪潮席卷全球的今天&#xff0c;企业纷纷拥抱云计算以提升业务敏捷性与创新能力。然而&#xff0c;随着云服务的大规模应用&#xff0c;一个不容忽视的挑战浮出水面——“云成本失控”。这一现象已成为制约企业数字化进程的关键瓶颈&#xff0c;迫使企业重新审视其…

【后端开发面试高频场景题设计题】深度解析| 面试全覆盖

文章目录目录一、 压轴高频场景题深度解析1.1 分布式缓存与数据库的数据一致性保障方案问题描述分析思路参考答案面试考察点面试追问1.2 数据库读写分离方案与实践问题描述分析思路参考答案1.2.1 读写分离核心架构对比1.2.2 主从同步方式对比1.2.3 主从同步延迟的解决方案面试考…

JavaEE——多线程(5)

Java线程池详解Java 线程池是管理线程生命周期、控制并发度的核心组件&#xff0c;基于 “池化思想” 减少线程创建 / 销毁的开销&#xff0c;优化系统资源利用率&#xff0c;同时提供任务队列、拒绝策略等机制&#xff0c;确保并发编程的稳定性和可维护性。1.为什么需要线程池…

数据损坏类型及相关恢复方法

&#xff08;一&#xff09;文件的删除及恢复文件删除的本质是操作系统在文件目录项首位写入删除标记&#xff08;如FAT32的"0xE5"&#xff0c;NTFS的$MFT条目置空&#xff09;&#xff0c;同时在文件分配表&#xff08;FAT&#xff09;或主文件表&#xff08;MFT&am…

从175亿参数到Transformer革命:一文搞懂大语言模型的底层逻辑

一、打破认知:LLM不是魔法,是数学 当你打开ChatGPT,看着它流畅地回答问题、撰写文案、甚至编写代码时,你是否会产生一种错觉——这是某种"智能生命"? 让我先给你泼一盆冷水:大语言模型(LLM)的本质,不过是一个专门处理文本的深度神经网络。它既不是科幻电影里的人工智…

Zookeeper在大数据领域的元数据管理实践

Zookeeper在大数据领域的元数据管理实践 关键词&#xff1a;Zookeeper、大数据、元数据管理、分布式系统、实践应用 摘要&#xff1a;本文主要探讨了Zookeeper在大数据领域元数据管理方面的实践。首先介绍了相关背景知识&#xff0c;包括目的、预期读者、文档结构和术语表。接着…

企业使用智能体能省多少钱?一套可直接套用的真实ROI计算模型

在2026年企业全面进入精细化经营的背景下&#xff0c;任何技术投入都绕不开一个核心问题&#xff1a;ROI是否能在部署前算清&#xff1f;过程中能否验证&#xff1f;结果是否可复用&#xff1f;结论先行&#xff1a;企业智能体不是概念性投入&#xff0c;而是目前少数可以在上线…

高并发接口调用的线程模型与处理机制

高并发接口调用的线程模型与处理机制 一、并发调用的基本概念 当多个用户同时请求同一接口时&#xff0c;系统如何处理这些并发请求&#xff0c;核心取决于线程分配机制和资源调度策略。二、Web服务器的请求处理模型 2.1 请求线程分配机制 所有Web应用&#xff08;如Spring Boo…

基于点云和建模命令反推CADQuery代码的批量推理系统

基于点云和建模命令反推CADQuery代码的批量推理系统 1. 项目概述与设计思路 1.1 项目背景 在CAD/CAM领域,从点云数据重建CAD模型是一个具有挑战性的任务。传统方法需要复杂的几何算法和人工干预,而现代大语言模型(LLM)在理解几何关系和生成代码方面展现出强大能力。本项…

走出“实验室”走向“天空” 杭州如何托举低空经济加速起飞?

具身智能加速起跑、低空经济蓬勃发展、人工智能深入公共治理与民生服务……在新一轮科技与产业变革中&#xff0c;杭州正以制度创新、场景开放和生态协同为抓手&#xff0c;加快打通科技成果从实验室走向市场的“最后一公里”&#xff0c;全力建设具有全国影响力的人工智能创新…

0095__WiX Toolset

https://blog.csdn.net/gitblog_00552/article/details/155294915

有监督学习神经网络改造为无监督学习的PyTorch可微分优化实现

有监督学习神经网络改造为无监督学习的PyTorch可微分优化实现 1. 引言:问题背景与需求分析 1.1 原始问题描述 我们面临一个关键任务:将一个原本使用有监督学习的神经网络改造为无监督学习架构。原始模型中,标签数据是通过一个MATLAB实现的交错网格差分法函数计算得到的。…

Spring Boot测试类的使用参考

Spring Boot测试类的使用参考 1. 集成测试概述 集成测试是在完整的Spring应用上下文中测试应用组件之间的交互。与单元测试不同&#xff0c;集成测试会启动Spring容器并加载所有配置的Bean。 2. 依赖配置 2.1 Maven依赖 <!-- Spring Boot测试核心依赖 --> <dependency…

0101__WiX Toolset 安装包制作入门教程(目录篇)

https://cloud.tencent.com.cn/developer/article/2349829

高通开源驱动ath12k已正式支持QCC2072

最新消息&#xff0c;高通于25年12月底更新开源驱动ath12k&#xff0c;已正式支持QCC2072 Wi-Fi7 芯片。 驱动对应链接&#xff1a; https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware/-/tree/main 补丁说明链接&#xff1a; https://lore.kernel.org/ath12k/ O…

宇信科技以金融科技前沿探索 获评《财经》新媒体2025“新奖”——“未来场景定义者”

在“十四五”与“十五五”交汇的历史节点&#xff0c;中国经济正以韧性、创新与结构性跃升为鲜明底色&#xff0c;描绘出一幅深刻转型的画卷。其中&#xff0c;以“人工智能”行动为牵引的新科技与实体经济深度融合&#xff0c;成为驱动高质量发展的核心引擎。近日&#xff0c;…

1024编程——让我们的孩子对话未来

编程到底学什么&#xff1f; 其实&#xff0c;编程思维是“理解问题——找出路径”的高效思维过程&#xff0c;它由分解、模式识别、抽象、算法四个步骤组成。编程能够培养孩子的自律性&#xff0c;需要制定规则并培养孩子形成遵守规则的意识。每一门编程语言都有自己的规则&am…