了解更多开源请访问:开源基础软件社区https://ost.51cto.com1.后台介绍3.1版本标准系统增加调用相关联系方式应用、来电应用等,系统服务层面的电话相关功能也比较完善。相关modem模块目前可以从美格智能slm790和紫光展锐模块的代码中看到,前面介绍过鸿蒙电话服务子系统功能划分的介绍只是官方文档的介绍。您可以通过本文档先了解各个功能模块。今天我们就从上到下分析代码调用流程,并以拨打电话为例,介绍一下鸿蒙电话子系统的各个部分。在电话服务子系统的/base/telephony目录下,大约有700个文件,11万多行代码。2、应用层js代码介绍应用层调用的应用是联系人,联系人应用的通话记录、联系人视图、拨号盘、收藏夹都有调用的调用。最后调用的是app.js中的call函数,调用@ohos.telephony.call中的dial方法。应用层只是调用telephonyframework层的api,由@ohos.telephony.call提供。3、调用NAPI实现介绍。应用层调用js函数,电话服务层用c语言实现。两者之间的桥梁是通过NAPI实现的。NAPI的介绍可以参考这些文章。源代码分析JavaScriptAPI框架(NAPI)。简单来说,js函数在c层都有相应的实现,它们之间是一一对应的。比如js的拨号对应c++的DialCall。相关代码如下,这部分代码在通话管理模块中。NapiCallManager::DialCall函数中调用的函数是。HandleAsyncWork(env,asyncContext,“DialCall”,NativeDialCall,NativeDialCallBack)。之后在CallManagerClient中跳转到DialCall,然后是CallManagerProxy::DialCall,如下:4.如何从CallManagerServiceProxy到CallManagerServiceStub再到CallManagerProxy::DialCall,代码一下子就不清楚了。callManagerServicePtr_是什么,它的DialCall在哪里?,它的位置如下:SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager()和managerPtr->GetSystemAbility(systemAbilityId_)是理解下一次调用位置的关键。这里涉及到另外一个知识点,就是进程通信。这里使用了ipc机制。可以查看官方文档的介绍。foundation/comminucotion目录下ipc下有readme文档,贴一张原图:大致意思是代理使用samgr,也就是SystemAbilityManager,调用跨进程Stub中的函数,代码层面可以通过systemAbilityId_和接口类定位函数调用的对应关系,其中abilityid为TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID,接口类为ICallManagerService,通过搜索定位CallManagerServiceProxy和CallManagerServiceStub。函数调用是从CallManagerServiceProxy::DialCall到CallManagerServiceStub::OnDialCall的转换。5、从CallControlManager::DialCall到蜂窝呼叫(cellular_call)模块CallManagerServiceStub::OnDialCall,调用CallControlManager::DialCall,然后走。CallRequestHandlerService::DialCall(),这里调用了一个发送事件函数,是一种线程异步处理机智可以看这篇文章,只要有发送就会接收,我们找到接收事件的地方。对应关系在如下位置,从而找到函数CallRequestHandler::DialCallEvent。CallRequestHandler::DialCallEvent中有一个特定类型的判断:我们进入CallRequestProcess::DialRequest分支,然后进入CellularCallIpcInterfaceProxy::Dial。这里又遇到了ipc,同样的方法此时id为TELEPHONY_CELLULAR_CALL_SYS_ABILITY_ID。发现stub函数的位置是CellularCallStub::Dial,此时已经到了cellularcall模块的目录。6.CSControl::Dial从蜂窝电话(cellular_call)直接调用到核心服务(core_service)CellularCallStub::Dial。这里还有一类判断,判断手机网络制式是gsm还是cdma。了解通信行业的人都知道,gsm和cdma是2G时代的两个制式标准。一个是欧洲主导,一个是高通主导。有点扯远了,继续看代码。两者最后调用CSControl::EncapsulateDialCommon,然后是CellularCallConnectionCS::DialRequest。然后进入核心服务模块。然后是TelRilManager::Dial和TelRilCall::Dial。7、从核心服务(core_service)调用TelRilBase基类的SendBufferEvent(HREQ_CALL_DIAL,wData)函数代码到RIL适配器(RILAdapter)TelRilCall::Dial如下:成员cellularRadio_的初始化实际上是在TelRilManager中。这就涉及到另外一个知识点驱动。看这篇OpenHarmonyHDFHDI基本能力分析和使用。调制解调器的操作用作RIL适配层中的驱动程序服务。SendRequest是对驱动程序的异步调用。RilAdapterDispatch中的函数负责接收和处理SendRequest。而这个处理函数是在加载驱动的时候运行的。RilAdapterDispatch中的函数DispatchRequest位于HRilManager中,然后调用DispatchModule。继续调用HRilManager::Dispatch,在HRilCall中进入ProcessCallRequest,然后根据HREQ_CALL_DIAL在函数指针数组reqMemberFuncMap_中找到处理函数HRilCall::Dial,然后处理逻辑变为callFuncs_->Dial。8、RILAdapter中的处理流程需要知道callFuncs_->Dial的最终位置,需要找到callFuncs_的赋值过程,HRilCall::RegisterCallFuncs的上层调用是HRilManager::RegisterCallFuncs和上层是HRilRegOps。在LoadVendor中调用了HRilRegOps,涉及到modem的加载机制。具体厂商的调制解调器处理的部分通过so加载介绍。通过打开so文件,建立函数的对应关系,最终调用at命令的具体实现部分。so的代码目录在vendor目录下,通过成员为函数指针的结构体建立关联。即callFuncs_->Dialinso的处理函数是ReqDial,这里组装了一个具体的at命令,调用的命令是ATD,GenerateCommand(cmd,MAX_CMD_LENGTH,“ATD%s%s;”,pDial->地址,clir)。最后通过WriteATCommand函数写入到at命令的通道中,通道就是具体的modem模块与主处理器硬件的连接。即当前代码中的usb通道。了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。
