Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
摘要:本节主要来讲解Android10.0 Native层HIDL服务的获取原理
阅读本文大约需要花费23分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
欢迎关注我的公众号!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
- Android系统架构
- Android是怎么启动的
- Android 10.0系统启动之init进程
- Android10.0系统启动之Zygote进程
- Android 10.0 系统启动之SystemServer进程
- Android 10.0 系统服务之ActivityMnagerService
- Android10.0系统启动之Launcher(桌面)启动流程
- Android10.0应用进程创建过程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现
《Binder通信原理》:
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入门篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++实例分析
- Android10.0 Binder通信原理(五)-Binder驱动分析
- Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework层分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
- Android10.0 Binder通信原理(十一)-Binder总结
《HwBinder通信原理》
- HwBinder入门篇-Android10.0 HwBinder通信原理(一)
- HIDL详解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
- Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》
- 编译系统入门篇-Android10.0编译系统(一)
- 编译环境初始化-Android10.0编译系统(二)
- make编译过程-Android10.0编译系统(三)
- Image打包流程-Android10.0编译系统(四)
- Kati详解-Android10.0编译系统(五)
上一节,我们学习了Native层 HIDL服务的注册原理,这一节我们来看看Native层HIDL服务的获取流程。
5.IDemo的服务获取
IDemo的HIDL服务获取流程如下图所示:
5.1调用栈如下
5.2 main
[\vendor\ingres\hal_demo\cpp\hal_demo_test.cpp]
int main() {//1.获取IDemo这个HIDL服务的代理对象android::sp<IDemo> service = IDemo::getService();if(service == nullptr) {printf("Failed to get service\n");return -1;}//2.调用服务的HIDL接口 getHelloString()service->getHelloString("IngresGe", [&](hidl_string result) {printf("%s\n", result.c_str());});return 0;
}
主要分两步:
1.获取IDemo这个HIDL服务的代理对象
2.调用服务的HIDL接口 getHelloString()
5.3 getService()
[/out/soong/.intermediates/vendor/ingres/interfaces/demo/1.0/vendor.ingres.demo@1.0_genc++/gen/vendor/ingres/demo/1.0/DemoAll.cpp]
::android::sp<IDemo> IDemo::getService(const std::string &serviceName, const bool getStub) {return ::android::hardware::details::getServiceInternal<BpHwDemo>(serviceName, true, getStub);
}
getService的调用栈如下:
根据上面的调用栈,最终进入getRawServiceInternal()
[/system/libhidl/transport/ServiceManagement.cpp]
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,const std::string& instance,bool retry, bool getStub) {using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;using ::android::hidl::manager::V1_0::IServiceManager;sp<Waiter> waiter;sp<IServiceManager1_1> sm;Transport transport = Transport::EMPTY;if (kIsRecovery) {transport = Transport::PASSTHROUGH;} else {//拿到HwServiceManager的对象,参考[5.4]sm = defaultServiceManager1_1();if (sm == nullptr) {ALOGE("getService: defaultServiceManager() is null");return nullptr;}//获取IDemo服务的transport,确认是直通式PASSTHROUGH,还是绑定式:HWBINDER//transport可以在/vendor/etc/vintf/manifest.xml中查看<transport>hwbinder</transport>Return<Transport> transportRet = sm->getTransport(descriptor, instance);if (!transportRet.isOk()) {ALOGE("getService: defaultServiceManager()->getTransport returns %s",transportRet.description().c_str());return nullptr;}transport = transportRet;}const bool vintfHwbinder = (transport == Transport::HWBINDER); //绑定式服务const bool vintfPassthru = (transport == Transport::PASSTHROUGH); //直通式服务...for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {if (waiter == nullptr && tries > 0) {waiter = new Waiter(descriptor, instance, sm);}if (waiter != nullptr) {waiter->reset(); // don't reorder this -- see comments on reset()}//如果是绑定式的服务,调用 BpHwServiceManager::get()Return<sp<IBase>> ret = sm->get(descriptor, instance);if (!ret.isOk()) {ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",ret.description().c_str(), descriptor.c_str(), instance.c_str());break;}sp<IBase> base = ret;if (base != nullptr) {Return<bool> canCastRet =details::canCastInterface(base.get(), descriptor.c_str(), true /* emitError */);if (canCastRet.isOk() && canCastRet) {if (waiter != nullptr) {waiter->done();}return base; // still needs to be wrapped by Bp class.}if (!handleCastError(canCastRet, descriptor, instance)) break;}// In case of legacy or we were not asked to retry, don't.if (vintfLegacy || !retry) break;if (waiter != nullptr) {ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());waiter->wait(true /* timeout */);}}if (waiter != nullptr) {waiter->done();}if (getStub || vintfPassthru || vintfLegacy) {//如果是直通式的hidl服务,获取直通式的HwServiceManager对象来获取服务const sp<IServiceManager> pm = getPassthroughServiceManager();if (pm != nullptr) {sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);if (!getStub || trebleTestingOverride) {base = wrapPassthrough(base);}return base;}}return nullptr;
}
getRawServiceInternal()步骤如下:
1.获取HwServiceManager的代理对象
2.获取IDemo 这个hidl服务的transport,来确认是绑定式服务,还是直通式服务
3.根据transport类型,调用不同的接口来获取服务对象 (我们设计的IDemo是绑定式hidl服务)
5.4 defaultServiceManager1_1
[/system/libhidl/transport/ServiceManagement.cpp]
sp<IServiceManager1_1> defaultServiceManager1_1() {return defaultServiceManager1_2();
}[/system/libhidl/transport/ServiceManagement.cpp]
defaultServiceManager1_2()是用来拿到HwServiceManager的代理对象--BpHwServiceManager
sp<IServiceManager1_2> defaultServiceManager1_2() {using android::hidl::manager::V1_2::BnHwServiceManager;using android::hidl::manager::V1_2::BpHwServiceManager;static std::mutex gDefaultServiceManagerLock;static sp<IServiceManager1_2> gDefaultServiceManager;{std::lock_guard<std::mutex> _l(gDefaultServiceManagerLock);if (gDefaultServiceManager != nullptr) {return gDefaultServiceManager;}//1.检查hwbinder的节点是否存在,如果不存在说明不支持hwbinderif (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {// HwBinder not available on this device or not accessible to// this process.return nullptr;}//2.等待属性"hwservicemanager.ready" 变为true,表明hwservicemanager已经启动好waitForHwServiceManager();while (gDefaultServiceManager == nullptr) {//3.拿到HwServiceManager的代理对象gDefaultServiceManager =fromBinder<IServiceManager1_2, BpHwServiceManager, BnHwServiceManager>(ProcessState::self()->getContextObject(nullptr));if (gDefaultServiceManager == nullptr) {LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";sleep(1);}}}return gDefaultServiceManager;
}
5.4.1 BpHwBinder::transact()
[/system/libhwbinder/BpHwBinder.cpp]
status_t BpHwBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback /*callback*/)
{// Once a binder has died, it will never come back to life.if (mAlive) {//拿到IPCThreadState的对象,调用transact()执行status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);if (status == DEAD_OBJECT) mAlive = 0;return status;}return DEAD_OBJECT;
}
BpBinder::transact()就是调用IPCThreadState::self()->transact() 进行处理
根据如下调用栈所示,BpHwBinder::transact()最终会转到BnHwServiceManager::_hidl_get(),实现流程和注册服务类似,相关源码分析参考上一节《Native层HIDL服务的注册原理》的[4.7.1] - [4.8]
5.5 BnHwServiceManager::_hidl_get()
[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/android.hidl.manager@1.2_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::status_t BnHwServiceManager::_hidl_get(::android::hidl::base::V1_0::BnHwBase* _hidl_this,const ::android::hardware::Parcel &_hidl_data,::android::hardware::Parcel *_hidl_reply,TransactCallback _hidl_cb) {...::android::status_t _hidl_err = ::android::OK;if (!_hidl_data.enforceInterface(BnHwServiceManager::Pure::descriptor)) {_hidl_err = ::android::BAD_TYPE;return _hidl_err;}const ::android::hardware::hidl_string* fqName;const ::android::hardware::hidl_string* name;size_t _hidl_fqName_parent;//1.获取hidl服务的fqName_hidl_err = _hidl_data.readBuffer(sizeof(*fqName), &_hidl_fqName_parent, reinterpret_cast<const void **>(&fqName));if (_hidl_err != ::android::OK) { return _hidl_err; }_hidl_err = ::android::hardware::readEmbeddedFromParcel(const_cast<::android::hardware::hidl_string &>(*fqName),_hidl_data,_hidl_fqName_parent,0 /* parentOffset */);if (_hidl_err != ::android::OK) { return _hidl_err; }size_t _hidl_name_parent;//2.获取hidl服务的name_hidl_err = _hidl_data.readBuffer(sizeof(*name), &_hidl_name_parent, reinterpret_cast<const void **>(&name));if (_hidl_err != ::android::OK) { return _hidl_err; }_hidl_err = ::android::hardware::readEmbeddedFromParcel(const_cast<::android::hardware::hidl_string &>(*name),_hidl_data,_hidl_name_parent,0 /* parentOffset */);if (_hidl_err != ::android::OK) { return _hidl_err; }atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::get::server");...//3.根据hidl服务的fqName和name,从HwServiceManager的hidl service的map中拿到服务对象::android::sp<::android::hidl::base::V1_0::IBase> _hidl_out_service = static_cast<IServiceManager*>(_hidl_this->getImpl().get())->get(*fqName, *name);//4.把reply信息写入Parcel::android::hardware::writeToParcel(::android::hardware::Status::ok(), _hidl_reply);if (_hidl_out_service == nullptr) {_hidl_err = _hidl_reply->writeStrongBinder(nullptr);} else {//5.把获取的hidl服务转成IBinder对象::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::getOrCreateCachedBinder(_hidl_out_service.get());if (_hidl_binder.get() != nullptr) {//6.把转换后的IBinder对象,写入reply的Parcel数据中_hidl_err = _hidl_reply->writeStrongBinder(_hidl_binder);} else {_hidl_err = ::android::UNKNOWN_ERROR;}}/* _hidl_err ignored! */atrace_end(ATRACE_TAG_HAL);..//7.通过回调,把reply的Parcel数据给发给client_hidl_cb(*_hidl_reply);return _hidl_err;
}
_hidl_get流程如下:
1.获取hidl服务的fqName
2.获取hidl服务的name
3.根据hidl服务的fqName和name,从HwServiceManager的hidl service的map中拿到服务对象
4.把reply信息写入Parcel
5.把获取的hidl服务转成IBinder对象
6.把转换后的IBinder对象,写入reply的Parcel数据中
7.通过回调,把reply的Parcel数据给发给client
5.5.1 ServiceManager::get()
[/system/hwservicemanager/ServiceManager.cpp]
Return<sp<IBase>> ServiceManager::get(const hidl_string& hidlFqName,const hidl_string& hidlName) {const std::string fqName = hidlFqName;const std::string name = hidlName;if (!mAcl.canGet(fqName, getBinderCallingContext())) {return nullptr;}//1.根据fqName和name找到对应的hidlServiceHidlService* hidlService = lookup(fqName, name);if (hidlService == nullptr) {tryStartService(fqName, name);return nullptr;}//2.根据hidlService 拿到IBase的对象sp<IBase> service = hidlService->getService();if (service == nullptr) {tryStartService(fqName, name);return nullptr;}hidlService->guaranteeClient();hardware::addPostCommandTask([hidlService] {hidlService->handleClientCallbacks(false /* isCalledOnInterval */);});return service;
}
5.7.3 ServiceManager::lookup()
主要是根据fqName和name从 HwServiceManager的服务map:mServiceMap 中找到对应的hidlservice。
[/system/hwservicemanager/ServiceManager.cpp]
HidlService* ServiceManager::lookup(const std::string& fqName, const std::string& name) {//1.根据fqName从 mServiceMap 中 找到一个节点auto ifaceIt = mServiceMap.find(fqName);if (ifaceIt == mServiceMap.end()) {return nullptr;}//2.从找到的map节点中,拿到PackageInterfaceMap的内容PackageInterfaceMap &ifaceMap = ifaceIt->second;//3.从PackageInterfaceMap中根据name找到hidlServiceHidlService *hidlService = ifaceMap.lookup(name);return hidlService;
}
5.5.2 HidlService::getService()
获取HidlService对象的mService
[/system/hwservicemanager/HidlService.cpp]
sp<IBase> HidlService::getService() const {return mService;
}
6. 协议码的转换流程
Binder通信协议是基于Command-Reply的方式的。
7.IDemo Client\Server交互流程
在IDemo的服务注册和获取的过程中,IDemo的服务和Client都是作为Client端,HwServiceManager作为Server端。
在IDemo的服务和client调用过程中,IDemo的服务为Server端,Client为客户端。
8.代码路径
/system/libhwbinder/BpHwBinder.cpp
/system/libhwbinder/IPCThreadState.cpp
/system/libhidl/transport/ServiceManagement.cpp
/system/libhidl/transport/include/hidl/HidlTransportSupport.h
/vendor/ingres/hal_demo/cpp/hal_demo_test.cpp
/out/soong/.intermediates/vendor/ingres/interfaces/demo/1.0/vendor.ingres.demo@1.0_genc++/gen/vendor/ingres/demo/1.0/DemoAll.cpp
/out/soong/.intermediates/system/libhidl/transport/manager/1.2/android.hidl.manager@1.2_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp
9. 总结
至此,Native层的HIDL服务注册和获取就梳理完了,主要就是进程和HwBinder驱动、HwServiceManager的交互流程,下一节我们再一起看看JAVA层的hidl服务注册和获取流程。
我的微信公众号:IngresGe
Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)相关推荐
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的获取原理 阅读本文大约需要花费19分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
摘要:本节主要来讲解Android10.0 Native层HIDL服务的注册原理 阅读本文大约需要花费23分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Androi ...
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的注册原理 阅读本文大约需要花费22分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
摘要:本节主要来讲解Android10.0 JAVA层的HIDL服务创建和JAVA层的Client验证 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级 ...
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
摘要:本节主要来讲解Android10.0 Native层的HIDL服务创建和Native层的Client验证 阅读本文大约需要花费18分钟. 文章首发微信公众号:IngresGe 专注于Androi ...
- nacis服务注册原理_HwServiceManager篇Android10.0 HwBinder通信原理(五)
阅读本文大约需要花费34分钟. 原创不易,如果您觉得有点用,希望可以随手转发或者点击右下角的 "在看".""分享"",拜谢! <And ...
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
摘要:本节主要来进行Android10.0 HwBinder的原理总结 阅读本文大约需要花费14分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
摘要:本节主要来讲解Android10.0 HwBinder驱动的流程 阅读本文大约需要花费24分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
摘要:本节主要来讲解Android10.0 HwServiceManager的通信原理 阅读本文大约需要花费34分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,And ...
最新文章
- 表格布局实践中经验的一些总结
- java 子类重写父类的方法应注意的问题
- 重拾算法(3)——用458329个测试用例全面测试二叉树和线索二叉树的遍历算法
- 有关Location对象,及URL的解析
- go语言中变量的定义和使用
- 一站式金融云托管服务 都匀融通村镇银行系统成功上线运行
- P1541-乌龟棋【多维dp】
- cat命令详解_好程序员Python培训之详解eval好与坏
- 为什么开发移动端web不使用jQuery
- Java8 实战系列-05-lambda 类型推断
- excel熵值法计算权重_小技巧1:Excel进行熵值法计算权重,查收一下!
- java取拼音首字母_java取出汉字字符串的拼音首字母
- Sketch使用教程(四)
- [小技巧1]Word或WPS文献引用、交叉引用方括号编号
- 高防服务器的机房硬件防火墙类型和主要功能
- telnet登录交换机
- 中考体育项目满分标准(深圳、安徽、湖北)
- 已有一个排好序的数组,今输入一个数,要求按原来排序的规律将它插入数组中
- Android手写签名
- 表情识别(七)--面部表情识别阶段综述(2018.4)
热门文章
- E0144“const char *“ 类型的值不能用于初始化 “char *“ 类型的实体
- 「BATJ面试系列」并发编程
- Spring Boot 2.x整合Websocket(基于Spring Boot 2.x 前后端分离 iview admin vue 集成activiti工作流...
- nginx反向代理、负载均衡、动态请求
- 【源资讯 第37期】一个时代的终结 —— 再见, Flash !
- vmware克隆server2008R2造成SID冲突
- 硬链接和软链接使用,以及区别
- SAP 应用服务负载均衡的实现
- 类的内置方法__attr__介绍
- (转)linux基本变量学习:位置变量$0 、$1 shift轮替、本地变量、环境变量、特殊变量...