OpenHarmony电话子系统源码流程解析
电话子系统各子模块业务比较繁杂,本文解析梳理的侧重点不是理清电话子系统详细业务流程,重点是明晰ui层(js或ets)到modem层各类节点的框架交互衔接。具体以拨号为引子梳理代码是如何从js层到达厂商
前言
电话子系统各子模块业务比较繁杂,本文解析梳理的侧重点不是理清电话子系统详细业务流程,重点是明晰ui层(js或ets)到modem层各类节点的框架交互衔接。具体以拨号为引子梳理代码是如何从js层到达厂商库的。源码追踪中使用的是OpenHarmony 3.1Beta版本。
-
js接口层如何与js UI界面对接
-
js接口层对上提供的服务从哪里来
-
Napi接口提供了哪些服务输出
-
Napi接口的服务从哪里来
-
以callmanager为例,介绍client通过何种形式与service通讯
-
SA服务配置文件在哪,有哪些配置项,怎么对外提供服务的
-
介绍一下提供服务时的IPC序列化和反序列化怎么使用
-
以modem HDF驱动介绍一下UHDF驱动的配置以及怎么对外提供服务
-
coreservice层怎么使用的HDF
-
HDF服务怎么与厂商库业务代码打通
概述
电话子系统为OpenHarmony系统提供基础的通信功能,包括CS域的语音短信业务,PS域的多媒体消息、数据业务,SIM管理,network驻网管理和RIL的业务等。
下面将以打电话的拨号(Dial指令)指令为引子,通过代码追踪向大家介绍JS UI层指令是如何一层一层到达modem的。
电话子系统在OpenHarmony框架中的位置图
源码位于源码根目录下的base/telephony/:
电话子系统通话管理主流程图以及分层说明
通话模块->蜂窝模块->coreservice模块->riladapter以及厂商库模块
通话模块:
蜂窝模块:
CoreService模块:
riladapter以及厂商库模块:
分层说明:APP(js应用)->callservice层(上层业务层:权限判断,铃音,蓝牙,视频,cs域、ps域、OTT语音电话分类分发等)->CellularCall(蜂窝业务层:针对蜂窝业务相关:GSM,CDMA,IMS等)->coreService(电话设备管理:电话卡,驻网,短彩信,RIL层等等)->hril层(HDF驱动交互,电话子系统对厂商库接口的统一抽象层)->vendorlib层(厂商库层,针对不同modem可替换)->modem芯片层(手机modem硬件,里面有各厂商固化的协议、以及功能固件)
代码仓库模块分类简介:
call_manager:管理各种类型的通话连接
status registry:实现APP对telephony相关状态信息的管理
sms_mms:负责短彩信相关功能
core_service:电话基础服务模块主要功能实现实现各模块与RIL Adapter进行交互对接
ril_adapter:无线接入适配层,抽象统一底层厂商库对上提供的接口,并负责与modem通信
data_storage:负责telephony持久化数据存储,提供DataAbility访问接口
cellular_data:负责建立蜂窝数据连接
CellularCall:负责运营商网络的基础通话实现
Dial文件关联以及流程解析
1.js接口层
1.1 js接口层的库文件在哪里,怎么编译安装到系统的
./system/lib/module/telephony/libcall.z.so
//这里有一点说明就是追踪OpenHarmony代码时,build.gn中的ohos_shared_library("call") 对应的so名称要添加上lib和.z.so,直接搜索call.so是搜索不到的
编译以及安装位置:call_manager\frameworks\js\BUILD.gn
1.2 js模块怎么被加载,加载时怎么注册接口以及init,init做了什么
js层:import call from '@ohos.telephony.call';
js接口层:
call_manager\frameworks\js\napi\src\napi_call_manager.cpp extern "C" __attribute__((constructor)) void RegisterModule(void) {//__attribute__((constructor))在main函数之前运行的,因为这个js UI所在的进程调用了这个js接口库,这个函数在js UI所在的进程的main函数启动之前运行 napi_module_register(&g_nativeCallManagerModule); } static napi_module g_nativeCallManagerModule = { .nm_version = NATIVE_VERSION, .nm_flags = NATIVE_FLAGS, .nm_filename = nullptr, .nm_register_func = NapiCallManager::RegisterCallManagerFunc,//import call from '@ohos.telephony.call'执行导入时先执行这个函数 .nm_modname = "telephony.call", .nm_priv = ((void *)0), .reserved = {0}, }; napi_value NapiCallManager::RegisterCallManagerFunc(napi_env env, napi_value exports) { // Interface initialization DeclareCallBasisInterface(env, exports);//在这个函数里将napi的Dial函数封装成js层能调用的函数接口 DeclareCallConferenceInterface(env, exports); DeclareCallSupplementInterface(env, exports); DeclareCallExtendInterface(env, exports); DeclareCallMultimediaInterface(env, exports); // Enumeration class initialization DeclareCallMediaEnum(env, exports); DeclareCallDialEnum(env, exports);//在这里封装napi的Dial函数参数以及枚举类型为js层形式的属性 DeclareCallStateEnum(env, exports); DeclareCallEventEnum(env, exports); DeclareCallRestrictionEnum(env, exports); DeclareCallWaitingEnum(env, exports); DeclareCallTransferEnum(env, exports); DeclareCallImsInterface(env, exports); // Enumeration class extension initialization DeclareAudioDeviceEnum(env, exports); DeclareVideoStateTypeEnum(env, exports); DeclareImsCallModeEnum(env, exports); DeclareDialSceneEnum(env, exports); DeclareCallTypeEnum(env, exports); DeclareDialTypeEnum(env, exports); DeclareTelCallStateEnum(env, exports); DeclareConferenceStateEnum(env, exports); DeclareCallStateToAppEnum(env, exports); DeclareCallEventEnumEx(env, exports); DeclareRestrictionTypeEnum(env, exports); DeclareRestrictionModeEnum(env, exports); DeclareRestrictionStatusEnum(env, exports); DeclareCallWaitingEnumEx(env, exports); DeclareTransferStatusEnum(env, exports); DeclareTransferTypeEnum(env, exports); DeclareTransferSettingTypeEnum(env, exports); Init();//创建客户端去连接CallManagerSA服务 return exports; } void Init() { // Establish a connection with call_manager DelayedSingleton<CallManagerClient>::GetInstance()->Init(TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID); }
用到了CallManagerClient去获取callmanagerSA服务
1.3 CallManagerClient从哪里引入
call_manager\frameworks\js\BUILD.gn
ohos_shared_library("call") { sources = [ "napi/src/napi_call_ability_callback.cpp", "napi/src/napi_call_manager.cpp", "napi/src/napi_call_manager_callback.cpp", "napi/src/napi_call_manager_utils.cpp", ] configs = [ "//base/telephony/core_service/utils:telephony_log_config" ] public_configs = [ ":call_manager_js_config" ] deps = [ "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", "//foundation/ace/napi:ace_napi", "//third_party/libuv:uv_static", "//utils/native/base:utils", ] external_deps = [ "ability_base:want", "ability_runtime:ability_manager", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "call_manager:tel_call_manager_api",//这里引入CallManagerClient,tel_call_manager_api就是NAPI 接口层库,js接口层库是针对js特性,对NAPI 接口层的再封装。 "core_service:tel_core_service_api", "eventhandler:libeventhandler", "ipc:ipc_core", "safwk:system_ability_fwk", "samgr_standard:samgr_proxy", ]
2.NAPI 接口层
NAPI 接口层的库文件在哪里,怎么编译安装到系统的,怎么使用NAPI开发
./system/lib/module/libtel_call_manager_api.z.so call_manager\frameworks\native\BUILD.gn 通过call_manager\interfaces\innerkits\call_manager_client.h头文件导入接口函数,来做NAPI开发 DelayedSingleton<CallManagerClient>::GetInstance()- >Init(TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID); 用到了CallManagerClient去获取callmanagerSA服务
3.接口归一,CallManager客户端以及代理层
3.1 JS层接口是对NAPI层接口的再封装,最终都通过CallManagerClient::Init(int32_t systemAbilityId)创建代理
call_manager\frameworks\native\src\call_manager_client.cpp void CallManagerClient::Init(int32_t systemAbilityId) { if (g_callManagerProxy == nullptr) { g_callManagerProxy = DelayedSingleton<CallManagerProxy>::GetInstance(); if (g_callManagerProxy == nullptr) { TELEPHONY_LOGE("g_callManagerProxy is nullptr"); return; } g_callManagerProxy->Init(systemAbilityId); } TELEPHONY_LOGI("CallManagerClient init success!"); }
这里调用到了CallManagerProxy: g_callManagerProxy->Init(systemAbilityId);
3.2、通过代理去连接CallManagerSA服务
call_manager\frameworks\native\src\call_manager_proxy.cpp void CallManagerProxy::Init(int32_t systemAbilityId)//该函数调用ConnectService()去连接一个CallManagerSA服务 int32_t CallManagerProxy::ConnectService() { Utils::UniqueWriteGuard<Utils::RWLock> guard(rwClientLock_); if (callManagerServicePtr_ != nullptr) { return TELEPHONY_SUCCESS; } sptr<ISystemAbilityManager> managerPtr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); //获取SA服务管理器对象 if (managerPtr == nullptr) { TELEPHONY_LOGE("GetSystemAbilityManager failed!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } sptr<ICallManagerService> callManagerServicePtr = nullptr; sptr<IRemoteObject> iRemoteObjectPtr = managerPtr->GetSystemAbility(systemAbilityId_); //SA服务管理器对象通过SA服务id,拿到一个能与该SA服务交互的RemoteObject。 if (iRemoteObjectPtr == nullptr) { TELEPHONY_LOGE("GetSystemAbility failed!"); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } callManagerServicePtr = iface_cast<ICallManagerService>(iRemoteObjectPtr); if (!callManagerServicePtr) { TELEPHONY_LOGE("iface_cast<ICallManagerService> failed!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } callManagerServicePtr_ = callManagerServicePtr; return TELEPHONY_SUCCESS; }
4.CallManagerSA服务的配置、建立与使用
4.1 SA服务ID定义
foundation\distributedschedule\samgr\interfaces\innerkits\samgr_proxy\include\system_ability_definition.h TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID:4005 system_ability_definition.h头文件中定义有各种SA服务的ID枚举值。 服务对应的配置文件名:SA id值结合.xml扩展名;例如:4005.xml。
4.2 sa_profile编译构建与配置文件
call_manager\sa_profile\BUILD.gn call_manager\sa_profile\4005.xml <info> <process>foundation</process> <systemability> <!-- Declare a system ability and its profile --> <name>4005</name> <!-- Declare the id of system ability. Must be same with system_ability_definition.h --> <libpath>libtel_call_manager.z.so</libpath> <run-on-create>true</run-on-create> <!-- "true" means the system ability would start immediately, "false" means the system ability would start on demand. --> <distributed>false</distributed> <!-- "true" means the system ability supports distributed scheduling while "false" is not. --> <dump-level>1</dump-level> <!-- Declare the dump level. 1-high; 2-media; 3-low --> </systemability> </info>
4.3 SA服务注册创建
call_manager\services\call_manager_service\src\call_manager_service.cpp const bool g_registerResult = SystemAbility::MakeAndRegisterAbility(DelayedSingleton<CallManagerService>::GetInstance().get()); CallManagerService::CallManagerService() : SystemAbility(TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID, true), callControlManagerPtr_(nullptr) {}
上面创建callmanagerSA服务
4.4 通过CallManagerProxy调用服务接口
举例:下面使用callmanagerSA服务的DialCall接口: call_manager\frameworks\native\src\call_manager_proxy.cpp int32_t CallManagerProxy::DialCall(std::u16string number, AppExecFwk::PacMap &extras) { if (ReConnectService() != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("ipc reconnect failed!"); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } std::lock_guard<std::mutex> lock(mutex_); int32_t errCode = callManagerServicePtr_->DialCall(number, extras);//跳转到callManagerServiceProxy类里的DialCall函数 if (errCode != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("DialCall failed, errcode:%{public}d", errCode); return errCode; } return TELEPHONY_SUCCESS; } 送到callManagerServiceProxy:
5. SA服务过程中的IPC数据序列化与反序列
5.1 序列化数据通过远端对象发送信息到SA服务端
callManagerServicePtr_->DialCall(number, extras); call_manager\frameworks\native\src\call_manager_service_proxy.cpp int32_t CallManagerServiceProxy::DialCall(std::u16string number, AppExecFwk::PacMap &extras) { MessageOption option; MessageParcel dataParcel; MessageParcel replyParcel; //对下发的参数数据进行IPC序列化 if (!dataParcel.WriteInterfaceToken(CallManagerServiceProxy::GetDescriptor())) { TELEPHONY_LOGE("write descriptor fail"); return TELEPHONY_ERR_WRITE_DESCRIPTOR_TOKEN_FAIL; } if (number.empty()) { TELEPHONY_LOGE("number is empty"); return TELEPHONY_ERR_ARGUMENT_INVALID; } dataParcel.WriteString16(number); dataParcel.WriteInt32(extras.GetIntValue("accountId")); dataParcel.WriteInt32(extras.GetIntValue("videoState")); dataParcel.WriteInt32(extras.GetIntValue("dialScene")); dataParcel.WriteInt32(extras.GetIntValue("dialType")); dataParcel.WriteInt32(extras.GetIntValue("callType")); if (Remote() == nullptr) { TELEPHONY_LOGE("function Remote() return nullptr!"); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } //调用远端对象的SendRequest函数将请求以及相应的参数通过IPC发送出去 int32_t error = Remote()->SendRequest(INTERFACE_DIAL_CALL, dataParcel, replyParcel, option); if (error != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("function DialCall call failed! errCode:%{public}d", error); return error; } return replyParcel.ReadInt32();//返回IPC对端反馈的返回码 }
5.2 数据到达callManagerServiceSA服务层STUB,反序列化并拆解成对应到具体函数处理通道
call_manager\services\call_manager_service\src\call_manager_service_stub.cpp //当有数据从IPC发送过来以后,IPC会调用CallManagerServiceStub端的OnRemoteRequest函数; int32_t CallManagerServiceStub::OnRemoteRequest( uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { std::u16string myDescriptor = CallManagerServiceStub::GetDescriptor(); std::u16string remoteDescriptor = data.ReadInterfaceToken(); if (myDescriptor != remoteDescriptor) { TELEPHONY_LOGE("descriptor checked fail !"); return TELEPHONY_ERR_DESCRIPTOR_MISMATCH; } TELEPHONY_LOGI("OnReceived, cmd = %{public}u", code); auto itFunc = memberFuncMap_.find(code);//通过请求类型枚举值关键字在memberFuncMap_找请求类型对应的处理函数: if (itFunc != memberFuncMap_.end()) { auto memberFunc = itFunc->second; if (memberFunc != nullptr) { return (this->*memberFunc)(data, reply);//找请求类型对应的处理函数后调用该函数 } } return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } void CallManagerServiceStub::InitCallBasicRequest() { //初始化请求类型枚举值与请求类型处理函数一一对应的memberFuncMap_ memberFuncMap_[INTERFACE_REGISTER_CALLBACK] = &CallManagerServiceStub::OnRegisterCallBack; memberFuncMap_[INTERFACE_UNREGISTER_CALLBACK] = &CallManagerServiceStub::OnUnRegisterCallBack; memberFuncMap_[INTERFACE_DIAL_CALL] = &CallManagerServiceStub::OnDialCall;//DIAL_CALL对应于OnDialCall memberFuncMap_[INTERFACE_ANSWER_CALL] = &CallManagerServiceStub::OnAcceptCall; memberFuncMap_[INTERFACE_REJECT_CALL] = &CallManagerServiceStub::OnRejectCall; memberFuncMap_[INTERFACE_HOLD_CALL] = &CallManagerServiceStub::OnHoldCall; memberFuncMap_[INTERFACE_UNHOLD_CALL] = &CallManagerServiceStub::OnUnHoldCall; memberFuncMap_[INTERFACE_DISCONNECT_CALL] = &CallManagerServiceStub::OnHangUpCall; memberFuncMap_[INTERFACE_GET_CALL_STATE] = &CallManagerServiceStub::OnGetCallState; memberFuncMap_[INTERFACE_SWAP_CALL] = &CallManagerServiceStub::OnSwitchCall; } int32_t CallManagerServiceStub::OnDialCall(MessageParcel &data, MessageParcel &reply) { int32_t result = TELEPHONY_ERR_FAIL; AppExecFwk::PacMap dialInfo; //IPC反序列化数据,并将OnDialCall中的数据组织到dialInfo中 std::u16string callNumber = data.ReadString16(); dialInfo.PutIntValue("accountId", data.ReadInt32()); dialInfo.PutIntValue("videoState", data.ReadInt32()); dialInfo.PutIntValue("dialScene", data.ReadInt32()); dialInfo.PutIntValue("dialType", data.ReadInt32());//这里带有拨号类型,用于后面的拨号策略判定 dialInfo.PutIntValue("callType", data.ReadInt32()); dialInfo.PutStringValue("bundleName", data.ReadString()); if (callNumber.length() > ACCOUNT_NUMBER_MAX_LENGTH) { TELEPHONY_LOGE("the account number length exceeds the limit"); return CALL_ERR_NUMBER_OUT_OF_RANGE; } result = DialCall(callNumber, dialInfo);//调用CallManagerService里的DialCall函数,CallManagerService是CallManagerServiceStub的子类 TELEPHONY_LOGI("result:%{public}d", result); if (!reply.WriteInt32(result)) { TELEPHONY_LOGE("fail to write parcel"); return TELEPHONY_ERR_WRITE_REPLY_FAIL; } return result; }
6. 被反序列化的数据到达SA服务中进行权限判断,根据业务进行处理通道的具体分配
6.1 到达callManagerServiceSA服务层,进行权限判断检查
call_manager\services\call_manager_service\src\call_manager_service.cpp int32_t CallManagerService::DialCall(std::u16string number, AppExecFwk::PacMap &extras) { int32_t uid = IPCSkeleton::GetCallingUid(); std::string bundleName = ""; TelephonyPermission::GetBundleNameByUid(uid, bundleName); extras.PutStringValue("bundleName", bundleName); if (!TelephonyPermission::CheckPermission(OHOS_PERMISSION_PLACE_CALL)) {//权限判断 TELEPHONY_LOGE("Permission denied!"); return TELEPHONY_ERR_PERMISSION_ERR; } if (callControlManagerPtr_ != nullptr) { return callControlManagerPtr_->DialCall(number, extras);//调用CallControlManager::DialCall } else { TELEPHONY_LOGE("callControlManagerPtr_ is nullptr!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } }
6.2 整理传入的DialCall参数:包括号码是否是紧急号码,处理拨号策略
call_manager\services\call\src\call_control_manager.cpp int32_t CallControlManager::DialCall(std::u16string &number, AppExecFwk::PacMap &extras) { int32_t errorCode = TELEPHONY_ERR_FAIL; sptr<CallBase> callObjectPtr = nullptr; std::string accountNumber(Str16ToStr8(number)); int32_t ret = NumberLegalityCheck(accountNumber); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("Invalid number!"); return ret; } bool isEcc = DelayedSingleton<CallNumberUtils>::GetInstance()->CheckNumberIsEmergency( accountNumber, extras.GetIntValue("accountId"), errorCode); ret = DialPolicy(number, extras, isEcc);//处理拨号策略 if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("dial policy result:%{public}d", ret); return ret; } // temporarily save dial information { std::lock_guard<std::mutex> lock(mutex_);//这里加互斥锁写入保护,而DialCall事件被发送到EventRunner线程,被这个线程处理时取数据调用GetDialParaInfo时再加互斥锁进行读取保护,两个线程共用这段数据,所以要加互斥锁 dialSrcInfo_.callId = ERR_ID; dialSrcInfo_.number = accountNumber; dialSrcInfo_.isDialing = true; dialSrcInfo_.isEcc = isEcc; dialSrcInfo_.callType = (CallType)extras.GetIntValue("callType"); dialSrcInfo_.accountId = extras.GetIntValue("accountId"); dialSrcInfo_.dialType = (DialType)extras.GetIntValue("dialType"); dialSrcInfo_.videoState = (VideoStateType)extras.GetIntValue("videoState"); dialSrcInfo_.bundleName = extras.GetStringValue("bundleName"); extras_.Clear(); extras_ = extras; } if (callRequestHandlerServicePtr_ == nullptr) { TELEPHONY_LOGE("callRequestHandlerServicePtr_ is nullptr!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } ret = callRequestHandlerServicePtr_->DialCall();//调用CallRequestHandlerService::DialCall if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("DialCall failed!"); return ret; } return TELEPHONY_SUCCESS; }
6.3 创建一个新的线程CallRequestHandler来处理call相关业务,可以支持事情排队优先级
base\telephony\call_manager\services\call\src\call_request_handler.cpp void CallRequestHandlerService::Start() { eventLoop_ = AppExecFwk::EventRunner::Create("CallRequestHandler");//<AppExecFwk::EventRunner>指针 if (eventLoop_.get() == nullptr) { TELEPHONY_LOGE("failed to create EventRunner"); return; } handler_ = std::make_shared<CallRequestHandler>(eventLoop_);//创建事件线程eventLoop_的EventHandler事件处理器 if (handler_.get() == nullptr) { TELEPHONY_LOGE("failed to create CallRequestHandler"); return; } handler_->Init();//对事件处理器进行初始化 eventLoop_->Run();//执行run循环接收发送过来的事件并分发到对应的事件处理器CallRequestHandler去处理 return; }
6.4 采用SendEvent方式将指令发送到call相关事件处理线程
int32_t CallRequestHandlerService::DialCall() { if (handler_.get() == nullptr) { TELEPHONY_LOGE("handler_ is nullptr"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (!handler_->SendEvent(HANDLER_DIAL_CALL_REQUEST)) {//发送给EventRunner线程eventLoop_来处理 TELEPHONY_LOGE("send dial event failed!"); return CALL_ERR_SYSTEM_EVENT_HANDLE_FAILURE; } return TELEPHONY_SUCCESS; }
6.5 call相关事件处理线程对DialCallEvent的处理
上面发出的event会被同一个文件中的CallRequestHandler类捕获,触发ProcessEvent处理(转换了线程,可以对到这里的call事件进行优先级排队)。 memberFuncMap会根据event的id从memberFuncMap_拿到对应的memberFunc,然后进入对应的处理函数DialCallEvent: void CallRequestHandler::DialCallEvent(const AppExecFwk::InnerEvent::Pointer &event) { if (event == nullptr) { TELEPHONY_LOGE("CallRequestHandler::ProcessEvent parameter error"); return; } if (callRequestProcessPtr_ == nullptr) { TELEPHONY_LOGE("callRequestProcessPtr_ is nullptr"); return; } callRequestProcessPtr_->DialRequest();//调用CallRequestProcess::DialRequest函数 }
6.6 根据拨号类型转换为2G cs域Dial,判断是4G运营商ip域多媒体Dial,还是OTT(over the top等应用通话)等Dial业务
如果是用到运营商蜂窝基站来打电话,还要蜂窝通话的核心服务CoreServiceConnection会被拉起来 call_manager\services\call\src\call_request_process.cpp void CallRequestProcess::DialRequest() { DialParaInfo info; DelayedSingleton<CallControlManager>::GetInstance()->GetDialParaInfo(info);//这里面会加互斥锁然后获取另一个线程写入的参数信息 if (!info.isDialing) { TELEPHONY_LOGE("the device is not dialing!"); return; } if (info.dialType == DialType::DIAL_CARRIER_TYPE) { std::vector<std::u16string> fdnNumberList = DelayedSingleton<CoreServiceConnection>::GetInstance()->GetFdnNumberList(info.accountId); if (!fdnNumberList.empty() && !IsFdnNumber(fdnNumberList, info.number)) { CallEventInfo eventInfo; (void)memset_s(eventInfo.phoneNum, kMaxNumberLen, 0, kMaxNumberLen); eventInfo.eventId = CallAbilityEventId::EVENT_INVALID_FDN_NUMBER; (void)memcpy_s(eventInfo.phoneNum, kMaxNumberLen, info.number.c_str(), info.number.length()); DelayedSingleton<CallControlManager>::GetInstance()->NotifyCallEventUpdated(eventInfo); TELEPHONY_LOGW("invalid fdn number!"); return; } } TELEPHONY_LOGI("dialType:%{public}d", info.dialType); switch (info.dialType) {//根据拨号类型分发到不同的分支进行处理,这里以2G CS域电话拨号为例进行分析 case DialType::DIAL_CARRIER_TYPE: CarrierDialProcess(info);//2G CS域电话拨号 break; case DialType::DIAL_VOICE_MAIL_TYPE: VoiceMailDialProcess(info); break; case DialType::DIAL_OTT_TYPE: OttDialProcess(info); break; default: TELEPHONY_LOGE("invalid dialType:%{public}d", info.dialType); break; } }
6.7 2G cs域Dial是怎么转到运营商CellularCall业务(蜂窝通话里还要处理gsm,CDMA等这些信息)处理的
2G cs域Dial,还是4G运营商ip域多媒体Dial最后都会转到手机蜂窝基站连接处理相关部分区 void CallRequestProcess::CarrierDialProcess(DialParaInfo &info) { CellularCallInfo callInfo; int32_t ret = PackCellularCallInfo(info, callInfo); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGW("PackCellularCallInfo failed!"); } // Obtain gateway information ret = DelayedSingleton<CellularCallConnection>::GetInstance()->Dial(callInfo);//转到CellularCallConnection if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("Dial failed!"); return; } } base\telephony\call_manager\services\telephony_interaction\src\cellular_call_connection.cpp int CellularCallConnection::Dial(const CellularCallInfo &callInfo) { if (ReConnectService() != TELEPHONY_SUCCESS) {//判断CellularCallConnection这边是否有连接到CellularCall SA服务端,没有则会去连接 TELEPHONY_LOGE("ipc reconnect failed!"); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } std::lock_guard<std::mutex> lock(mutex_); TELEPHONY_LOGI("callType:%{public}d", callInfo.callType); int errCode = cellularCallInterfacePtr_->Dial(callInfo);//通过远端对象调用Dial if (errCode != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("dial failed, errcode:%{public}d", errCode); return errCode; } return TELEPHONY_SUCCESS; } int32_t CellularCallConnection::ReConnectService() { #ifdef CELLULAR_SUPPORT if (cellularCallInterfacePtr_ == nullptr) { TELEPHONY_LOGI("try to reconnect cellular call service now..."); int32_t result = ConnectService(); if (result != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("Connect service: %{public}d", result); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } } #endif return TELEPHONY_SUCCESS; }
6.8 CellularCallConnection::ReConnectService()创建了连接cellular_callSA服务的远端对象(CellularCallProxy代理)
int32_t CellularCallConnection::ConnectService() {//与cellular_callSA服务通讯前先连接它,获取能与它通讯的远端对象 Utils::UniqueWriteGuard<Utils::RWLock> guard(rwClientLock_); if (cellularCallInterfacePtr_ != nullptr) { return TELEPHONY_SUCCESS; } //获取系统的SA服务管理器 sptr<ISystemAbilityManager> managerPtr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (managerPtr == nullptr) { return TELEPHONY_ERR_LOCAL_PTR_NULL; } sptr<CellularCallInterface> cellularCallInterfacePtr = nullptr; //使用系统的SA服务管理器通过SA ID获取能与这个SA服务端通讯的远端对象 sptr<IRemoteObject> iRemoteObjectPtr = managerPtr->GetSystemAbility(systemAbilityId_); if (iRemoteObjectPtr == nullptr) { return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } cellularCallInterfacePtr = iface_cast<CellularCallInterface>(iRemoteObjectPtr); if (!cellularCallInterfacePtr) { return TELEPHONY_ERR_LOCAL_PTR_NULL; } std::weak_ptr<CellularCallConnection> weakPtr = shared_from_this(); auto deathCallback = [weakPtr](const wptr<IRemoteObject> &object) { auto sharedPtr = weakPtr.lock(); if (sharedPtr) { sharedPtr->OnDeath(); } }; cellularCallRecipient_ = (std::make_unique<CellularCallDeathRecipient>(deathCallback)).release(); if (cellularCallRecipient_ == nullptr) { return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (!iRemoteObjectPtr->AddDeathRecipient(cellularCallRecipient_)) { return TELEPHONY_ERR_ADD_DEATH_RECIPIENT_FAIL; } cellularCallInterfacePtr_ = cellularCallInterfacePtr; int32_t ret = RegisterCallBackFun(); if (ret != TELEPHONY_SUCCESS) { return ret; } connectState_ = true; return TELEPHONY_SUCCESS; }
6.9 通过cellular_call SA服务的远端对象发出了Dial信息
int CellularCallConnection::Dial(const CellularCallInfo &callInfo) { if (ReConnectService() != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("ipc reconnect failed!"); return TELEPHONY_ERR_IPC_CONNECT_STUB_FAIL; } std::lock_guard<std::mutex> lock(mutex_); TELEPHONY_LOGI("callType:%{public}d", callInfo.callType); int errCode = cellularCallInterfacePtr_->Dial(callInfo);//调用CellularCallProxy::Dial if (errCode != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("dial failed, errcode:%{public}d", errCode); return errCode; } return TELEPHONY_SUCCESS; }
6.10 通过CellularCallProxy的序列化后发送出Dial信息
如何跳转到cellular_callSA服务,通过class CellularCallProxy : public IRemoteProxy<CellularCallInterface> call_manager\services\telephony_interaction\include\cellular_call_interface.h call_manager\services\telephony_interaction\include\cellular_call_proxy.h 通过CellularCallConnection::ConnectService()获取到SA服务的远端对象(proxy)。 通过远端对象的IPC通讯与CellularCallservice打通联系: int32_t CellularCallProxy::Dial(const CellularCallInfo &callInfo) { MessageOption option; MessageParcel in; MessageParcel out; //IPC序列化数据 if (!in.WriteInterfaceToken(CellularCallProxy::GetDescriptor())) { return TELEPHONY_ERR_WRITE_DESCRIPTOR_TOKEN_FAIL; } if (!in.WriteInt32(MAX_SIZE)) { return TELEPHONY_ERR_WRITE_DATA_FAIL; } if (!in.WriteRawData((const void *)&callInfo, sizeof(CellularCallInfo))) { return TELEPHONY_ERR_WRITE_DATA_FAIL; } //通过IPC发送数据 int32_t error = Remote()->SendRequest(static_cast<uint32_t>(OperationType::DIAL), in, out, option); if (error == ERR_NONE) { return out.ReadInt32(); } return error; }
6.11 通过cellular_call_stub的反序列拆解分发Dial信息
base\telephony\cellular_call\services\manager\src\cellular_call_stub.cpp //在IPC收到给cellular_call这个SA的数据以后调用CellularCallStub::OnRemoteRequest int32_t CellularCallStub::OnRemoteRequest( uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { std::u16string myDescriptor = CellularCallStub::GetDescriptor(); std::u16string remoteDescriptor = data.ReadInterfaceToken(); if (myDescriptor != remoteDescriptor) { TELEPHONY_LOGE("descriptor checked fail"); return TELEPHONY_ERR_DESCRIPTOR_MISMATCH; } auto itFunc = requestFuncMap_.find(static_cast<OperationType>(code));//根据请求code来查找处理函数,并调用这个处理函数 if (itFunc != requestFuncMap_.end()) { auto requestFunc = itFunc->second; if (requestFunc != nullptr) { return (this->*requestFunc)(data, reply); } } TELEPHONY_LOGI("CellularCallStub::OnRemoteRequest, default case, need check."); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } CellularCallStub::CellularCallStub() { //构造函数中会进行请求枚举关键值与对应的处理函数的一一映射,并存储到requestFuncMap_中 TELEPHONY_LOGI("CellularCallStub::CellularCallStub"); requestFuncMap_[OperationType::DIAL] = &CellularCallStub::OnDialInner;//拨号请求映射到了CellularCallStub::OnDialInner requestFuncMap_[OperationType::HANG_UP] = &CellularCallStub::OnHangUpInner; requestFuncMap_[OperationType::REJECT] = &CellularCallStub::OnRejectInner; requestFuncMap_[OperationType::ANSWER] = &CellularCallStub::OnAnswerInner; requestFuncMap_[OperationType::EMERGENCY_CALL] = &CellularCallStub::OnIsEmergencyPhoneNumberInner; requestFuncMap_[OperationType::HOLD_CALL] = &CellularCallStub::OnHoldCallInner; requestFuncMap_[OperationType::UN_HOLD_CALL] = &CellularCallStub::OnUnHoldCallInner; requestFuncMap_[OperationType::SWITCH_CALL] = &CellularCallStub::OnSwitchCallInner; requestFuncMap_[OperationType::COMBINE_CONFERENCE] = &CellularCallStub::OnCombineConferenceInner; requestFuncMap_[OperationType::SEPARATE_CONFERENCE] = &CellularCallStub::OnSeparateConferenceInner; requestFuncMap_[OperationType::INVITE_TO_CONFERENCE] = &CellularCallStub::OnInviteToConferenceInner; requestFuncMap_[OperationType::KICK_OUT_CONFERENCE] = &CellularCallStub::OnKickOutFromConferenceInner; requestFuncMap_[OperationType::HANG_UP_ALL_CONNECTION] = &CellularCallStub::OnHangUpAllConnectionInner; requestFuncMap_[OperationType::UPDATE_CALL_MEDIA_MODE] = &CellularCallStub::OnUpdateCallMediaModeInner; requestFuncMap_[OperationType::REGISTER_CALLBACK] = &CellularCallStub::OnRegisterCallBackInner; requestFuncMap_[OperationType::UNREGISTER_CALLBACK] = &CellularCallStub::OnUnRegisterCallBackInner; requestFuncMap_[OperationType::START_DTMF] = &CellularCallStub::OnStartDtmfInner; requestFuncMap_[OperationType::STOP_DTMF] = &CellularCallStub::OnStopDtmfInner; requestFuncMap_[OperationType::SEND_DTMF] = &CellularCallStub::OnSendDtmfInner; requestFuncMap_[OperationType::START_RTT] = &CellularCallStub::OnStartRttInner; requestFuncMap_[OperationType::STOP_RTT] = &CellularCallStub::OnStopRttInner; requestFuncMap_[OperationType::SET_CALL_TRANSFER] = &CellularCallStub::OnSetCallTransferInner; requestFuncMap_[OperationType::GET_CALL_TRANSFER] = &CellularCallStub::OnGetCallTransferInner; requestFuncMap_[OperationType::SET_CALL_WAITING] = &CellularCallStub::OnSetCallWaitingInner; requestFuncMap_[OperationType::GET_CALL_WAITING] = &CellularCallStub::OnGetCallWaitingInner; requestFuncMap_[OperationType::SET_CALL_RESTRICTION] = &CellularCallStub::OnSetCallRestrictionInner; requestFuncMap_[OperationType::GET_CALL_RESTRICTION] = &CellularCallStub::OnGetCallRestrictionInner; requestFuncMap_[OperationType::SET_DOMAIN_PREFERENCE_MODE] = &CellularCallStub::OnSetDomainPreferenceModeInner; requestFuncMap_[OperationType::GET_DOMAIN_PREFERENCE_MODE] = &CellularCallStub::OnGetDomainPreferenceModeInner; requestFuncMap_[OperationType::SET_LTE_IMS_SWITCH_STATUS] = &CellularCallStub::OnSetLteImsSwitchStatusInner; requestFuncMap_[OperationType::GET_LTE_IMS_SWITCH_STATUS] = &CellularCallStub::OnGetLteImsSwitchStatusInner; requestFuncMap_[OperationType::SET_IMS_CONFIG_STRING] = &CellularCallStub::OnSetImsConfigStringInner; requestFuncMap_[OperationType::SET_IMS_CONFIG_INT] = &CellularCallStub::OnSetImsConfigIntInner; requestFuncMap_[OperationType::GET_IMS_CONFIG] = &CellularCallStub::OnGetImsConfigInner; requestFuncMap_[OperationType::SET_IMS_FEATURE] = &CellularCallStub::OnSetImsFeatureValueInner; requestFuncMap_[OperationType::GET_IMS_FEATURE] = &CellularCallStub::OnGetImsFeatureValueInner; requestFuncMap_[OperationType::SET_IMS_SWITCH_ENHANCE_MODE] = &CellularCallStub::OnSetImsSwitchEnhanceModeInner; requestFuncMap_[OperationType::GET_IMS_SWITCH_ENHANCE_MODE] = &CellularCallStub::OnGetImsSwitchEnhanceModeInner; requestFuncMap_[OperationType::CTRL_CAMERA] = &CellularCallStub::OnCtrlCameraInner; requestFuncMap_[OperationType::SET_PREVIEW_WINDOW] = &CellularCallStub::OnSetPreviewWindowInner; requestFuncMap_[OperationType::SET_DISPLAY_WINDOW] = &CellularCallStub::OnSetDisplayWindowInner; requestFuncMap_[OperationType::SET_CAMERA_ZOOM] = &CellularCallStub::OnSetCameraZoomInner; requestFuncMap_[OperationType::SET_PAUSE_IMAGE] = &CellularCallStub::OnSetPauseImageInner; requestFuncMap_[OperationType::SET_DEVICE_DIRECTION] = &CellularCallStub::OnSetDeviceDirectionInner; requestFuncMap_[OperationType::SET_MUTE] = &CellularCallStub::OnSetMuteInner; requestFuncMap_[OperationType::GET_MUTE] = &CellularCallStub::OnGetMuteInner; } int32_t CellularCallStub::OnDialInner(MessageParcel &data, MessageParcel &reply) { TELEPHONY_LOGI("CellularCallStub::OnDialInner entry"); int32_t size = data.ReadInt32();//IPC数据反序列化 size = ((size > MAX_SIZE) ? 0 : size); if (size <= 0) { TELEPHONY_LOGE("CellularCallStub::OnRemoteRequest data size error"); return TELEPHONY_ERR_FAIL; } auto pCallInfo = (CellularCallInfo *)data.ReadRawData(sizeof(CellularCallInfo));//IPC数据反序列化 if (pCallInfo == nullptr) { TELEPHONY_LOGE("OnDialInner return, pCallInfo is nullptr."); return TELEPHONY_ERR_ARGUMENT_INVALID; } reply.WriteInt32(Dial(*pCallInfo));//调用CellularCallService的Dial函数并返回反馈码 return TELEPHONY_SUCCESS; }
6.12 通过cellular_call_stub的分发Dial信息到CellularCallService,再分发到cs域dial
class CellularCallService : public SystemAbility, public CellularCallStub,//继承了CellularCallStub public std::enable_shared_from_this<CellularCallService> cellular_call\services\manager\src\cellular_call_service.cpp int32_t CellularCallService::Dial(const CellularCallInfo &callInfo) { return csControl->Dial(callInfo);//调用了csControl->Dial }
6.13 cs域dial再根据拨号类型分发到gsm或者CDMA
cellular_call\services\control\src\cs_control.cpp int32_t CSControl::Dial(const CellularCallInfo &callInfo) { TELEPHONY_LOGI("Dial start"); int32_t ret = DialPreJudgment(callInfo); if (ret != TELEPHONY_SUCCESS) { return ret; } ModuleServiceUtils moduleServiceUtils; PhoneType netType = moduleServiceUtils.GetNetworkStatus(callInfo.slotId); if (netType == PhoneType::PHONE_TYPE_IS_GSM) { return DialGsm(callInfo);//根据netType来决定调用GSM拨号,还是其它。我们以DialGsm来拉通流程 } if (netType == PhoneType::PHONE_TYPE_IS_CDMA) { return DialCdma(callInfo);//调用Cdma拨号 } TELEPHONY_LOGE("Dial return, net type error."); return CALL_ERR_UNSUPPORTED_NETWORK_TYPE; } int32_t CSControl::DialGsm(const CellularCallInfo &callInfo) {// TELEPHONY_LOGI("DialGsm entry."); StandardizeUtils standardizeUtils; // Remove the phone number separator std::string newPhoneNum = standardizeUtils.RemoveSeparatorsPhoneNumber(callInfo.phoneNum); CLIRMode clirMode = CLIRMode::DEFAULT; if (IsNeedExecuteMMI(callInfo.slotId, newPhoneNum, clirMode)) { TELEPHONY_LOGI("DialGsm return, mmi code type."); return RETURN_TYPE_MMI; } if (!CanCall(connectionMap_)) { TELEPHONY_LOGE("DialGsm return, error type: call state error."); return CALL_ERR_CALL_COUNTS_EXCEED_LIMIT; } // Calls can be put on hold, recovered, released, added to conversation, // and transferred similarly as defined in 3GPP TS 22.030 [19]. if (IsInState(connectionMap_, TelCallState::CALL_STATUS_ACTIVE)) { // New calls must be active, so other calls need to be hold TELEPHONY_LOGI("DialGsm, GSM is have connection in active state."); CellularCallConnectionCS pConnection; // Delay dialing to prevent failure to add a new call while making a multi-party call // Will it block the main thread or other threads? Will the reception of messages be blocked during sleep? // - a call can be temporarily disconnected from the ME but the connection is retained by the network pConnection.SwitchCallRequest(callInfo.slotId); } return EncapsulateDialCommon(callInfo.slotId, newPhoneNum, clirMode);//调用了CSControl::EncapsulateDialCommon } int32_t CSControl::EncapsulateDialCommon(int32_t slotId, const std::string &phoneNum, CLIRMode &clirMode) { DialRequestStruct dialRequest; /** * <idx>: integer type; * call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1 * this number can be used in +CHLD command operations * <dir>: */ dialRequest.phoneNum = phoneNum; /** * <n> (parameter sets the adjustment for outgoing calls): * 0 presentation indicator is used according to the subscription of the CLIR service * 1 CLIR invocation * 2 CLIR suppression */ dialRequest.clirMode = clirMode; /** * An example of voice group call service request usage: * ATD*17*753#500; (originate voice group call with the priority level 3) * OK (voice group call setup was successful) */ CellularCallConnectionCS csConnection; return csConnection.DialRequest(slotId, dialRequest);//调用了CellularCallConnectionCS下DialRequest函数 }
6.14 cellular_call_connection_cs将Dial请求分发到coreservice层的CoreManagerInner::GetInstance().Dial以及布局Dial的响应处理handler
cellular_call\services\connection\src\cellular_call_connection_cs.cpp int32_t CellularCallConnectionCS::DialRequest(int32_t slotId, const DialRequestStruct &dialRequest) { TELEPHONY_LOGE("CellularCallConnectionCS::DialRequest start."); if (DelayedSingleton<CellularCallService>::GetInstance() == nullptr) { TELEPHONY_LOGE("DialRequest return, error type: GetInstance() is nullptr."); return CALL_ERR_RESOURCE_UNAVAILABLE; } *************base\telephony\cellular_call\services\manager\src\cellular_call_handler.cpp****** *************生产事件处理handler产生Dial请求的响应事件处理者CellularCallHandler****** *************requestFuncMap_[RadioEvent::RADIO_DIAL] = &CellularCallHandler::DialResponse;****** auto handle = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);//这个handle用来处理Dial请求下发后,下层的处理请求以后的反馈上来的信息 if (handle == nullptr) { TELEPHONY_LOGE("DialRequest return, error type: handle is nullptr."); return CALL_ERR_RESOURCE_UNAVAILABLE; } CoreManagerInner::GetInstance().Dial(//离开CellularCall这一层,CoreManagerInner::GetInstance().Dial进入到了CoreService层了 slotId, RadioEvent::RADIO_DIAL, dialRequest.phoneNum, dialRequest.clirMode, handle); return TELEPHONY_SUCCESS; }
7. coreservice层信号处理后调用到厂商库
7.1 生产事件处理handler,并传递到rilmanager中去处理
core_service\frameworks\native\src\core_manager_inner.cpp int32_t CoreManagerInner::Dial(int32_t slotId, int32_t eventId, std::string address, int clirMode, const std::shared_ptr<AppExecFwk::EventHandler> &handler) { if (telRilManager_ == nullptr) { TELEPHONY_LOGE("telRilManager is null!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } AppExecFwk::InnerEvent::Pointer response = AppExecFwk::InnerEvent::Get(eventId);//获取一个与Dial请求ID(eventId)值绑定的内部事件指针 response->SetOwner(handler);//将事件处理器对象绑定到内部事件指针的Owner上 return telRilManager_->Dial(slotId, address, clirMode, response);//将绑定了Dial请求ID以及对应的事件处理器内部事件指针与Dial参数一起分发给telRilManager_->Dial处理 }
7.2 TelRilManager转到TelRilCall中,通过IPC下发到了去处理
core_service\services\tel_ril\src\tel_ril_manager.cpp int32_t TelRilManager::Dial( int32_t slotId, std::string address, int32_t clirMode, const AppExecFwk::InnerEvent::Pointer &response) { return TaskSchedule(response, "TelRilCall", GetTelRilCall(slotId), &TelRilCall::Dial, address, clirMode);//通过这个函数进一步分发到TelRilCall::Dial函数处理 } int32_t TelRilCall::Dial(const std::string address, int32_t clirMode, const AppExecFwk::InnerEvent::Pointer &result) { std::shared_ptr<TelRilRequest> telRilRequest = CreateTelRilRequest(HREQ_CALL_DIAL, result); //通过这里创建一个唯一序列号telRilRequest->serialId_绑定到该请求,并保存到requestMap_,该序号用于FindTelRilRequest时(被响应处理或超时后)把该请求的从requestMap_移除。 if (telRilRequest == nullptr) { TELEPHONY_LOGE("telRilRequest is nullptr"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (cellularRadio_ == nullptr) { TELEPHONY_LOGE("%{public}s cellularRadio_ == nullptr", __func__); return TELEPHONY_ERR_LOCAL_PTR_NULL; } DialInfo dialInfo; dialInfo.address = address; dialInfo.clir = clirMode; dialInfo.serial = telRilRequest->serialId_; int32_t ret = SendBufferEvent(HREQ_CALL_DIAL, dialInfo);//通过IPC发送Dial请求到modem的HDF驱动服务去,最终经过modem的HDF驱动服务的分发会调用HRilCall::Dial函数 TELEPHONY_LOGI("Send (ID:%{public}d) return: %{public}d", HREQ_CALL_DIAL, ret); return ret; }
7.3 TelRilCall中的HREQ_CALL_DIAL响应绑定以及响应函数
memberFuncMap_[HREQ_CALL_DIAL] = &TelRilCall::DialResponse;//coreservice这个层级的Dial响应处理函数 int32_t TelRilCall::DialResponse(MessageParcel &data) { //IPC反序列化读取读取modem Hdf驱动服务端反馈的数据 const size_t readSpSize = sizeof(struct HRilRadioResponseInfo); const uint8_t *spBuffer = data.ReadUnpadBuffer(readSpSize); if (spBuffer == nullptr) { TELEPHONY_LOGE("TelRilCall DialResponse read spBuffer failed"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } const struct HRilRadioResponseInfo *radioResponseInfo = reinterpret_cast<const struct HRilRadioResponseInfo *>(spBuffer); if (radioResponseInfo == nullptr) { TELEPHONY_LOGE("ERROR :radioResponseInfo == nullptr !!!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } std::shared_ptr<TelRilRequest> telRilRequest = FindTelRilRequest(*radioResponseInfo); //从requestMap_成员变量中移除与radioResponseInfo->serial对应的telRilRequest,并返回该telRilRequest,当telRilRequest使用完后就被释放了。 if (telRilRequest == nullptr || telRilRequest->pointer_ == nullptr) { TELEPHONY_LOGE("ERROR : telRilRequest or telRilRequest->pointer_ == nullptr !!!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } //获取这个Dial请求对应的响应事件处理器(蜂窝调用时通过pointer_传递下来的) const std::shared_ptr<OHOS::AppExecFwk::EventHandler> &handler = telRilRequest->pointer_->GetOwner(); if (handler == nullptr) { TELEPHONY_LOGE("ERROR :handler == nullptr !!!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } //获取这个Dial请求对应的事件ID uint32_t eventId = telRilRequest->pointer_->GetInnerEventId(); std::shared_ptr<HRilRadioResponseInfo> result = std::make_shared<HRilRadioResponseInfo>(); result->error = radioResponseInfo->error; handler->SendEvent(eventId, result);//通过响应事件处理器的SendEvent发送结果给响应事件处理器的处理函数,并指定该结果为eventId事件的响应数据 return TELEPHONY_ERR_SUCCESS; }
7.4 HRilManager收到请求后拆解转到HRilCall中直接调用厂商库函数去处理
ril_adapter\services\hril\src\hril_call.cpp int32_t HRilCall::Dial(struct HdfSBuf *data) { if (callFuncs_ == nullptr || callFuncs_->Dial == nullptr || data == nullptr) { TELEPHONY_LOGE("callFuncs_:%{public}p or callFuncs_->Dial or data:%{public}p is nullptr!", callFuncs_, data); return HRIL_ERR_NULL_POINT; } DialInfo dialInfo = DialInfo(); MessageParcel *parcel = nullptr; //IPC反序列化coreservice层级发送过来的数据 if (SbufToParcel(data, &parcel)) { TELEPHONY_LOGE("RilAdapter failed to do SbufToParcel"); return HRIL_ERR_INVALID_PARAMETER; } if (!dialInfo.ReadFromParcel(*parcel)) { TELEPHONY_LOGE("RilAdapter failed to do ReadFromParcel!"); return HRIL_ERR_INVALID_PARAMETER; } HRilDial dial = {}; dial.address = StringToCString(dialInfo.address); dial.clir = (int32_t)dialInfo.clir; ReqDataInfo *requestInfo = CreateHRilRequest(dialInfo.serial, HREQ_CALL_DIAL); if (requestInfo == nullptr) { TELEPHONY_LOGE("RilAdapter failed to do Create Dial HRilRequest!"); return HRIL_ERR_NULL_POINT; } //callFuncs_存储厂商库call相关接口函数的结构体指针,通过这个指针里的Dial函数指针调用厂商库Dial函数 callFuncs_->Dial(requestInfo, &dial, sizeof(HRilDial)); return HRIL_ERR_SUCCESS; }
8. 通过HDF服务的初始化以及配置,来曝漏厂商库接口
8.1 配置并确定hdf驱动对外提供服务的名称
vendor\hisilicon\Hi3516DV300\hdf_config\uhdf\device_info.hcs riladapter :: host { hostName = "riladapter_host";//HDF驱动的进程名称 priority = 50; riladapter_device :: device { device0 :: deviceNode { policy = 2; priority = 100; moduleName = "libhril_hdf.z.so";//提供modem HDF驱动服务的库文件名称 serviceName = "cellular_radio1";//提供modem HDF驱动服务对外曝露的服务名称 } } }
8.2 驱动入口注册
base\telephony\ril_adapter\services\hril_hdf\src\hril_hdf.c struct HdfDriverEntry g_rilAdapterDevEntry = { .moduleVersion = 1, .moduleName = "hril_hdf", .Bind = RilAdapterBind,//modem HDF驱动绑定函数,在这个函数里绑定了HDF的服务对象,服务对象里保存有服务提供的各种功能分发处理函数,在这个分发处理函数中进行功能函数分派Dispatch .Init = RilAdapterInit,//modem HDF驱动初始化函数 .Release = RilAdapterRelease, }; HDF_INIT(g_rilAdapterDevEntry);
8.3 初始化加载厂商库
static int32_t RilAdapterInit(struct HdfDeviceObject *device) { ... TELEPHONY_LOGI("sbuf IPC obtain success!"); LoadVendor();//加载厂商库 return HDF_SUCCESS; }
8.4 通过bind将具体的服务函数绑定到HDF驱动服务上
static int32_t RilAdapterDispatch( struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) { int32_t ret; static pthread_mutex_t dispatchMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&dispatchMutex); TELEPHONY_LOGI("RilAdapterDispatch cmd:%{public}d", cmd); ret = DispatchRequest(cmd, data);//请求下来以后通过服务的Dispatch接口函数到这里,通过DispatchRequest函数在按服务的功能进行分类分发到不同处理函数进行处理 pthread_mutex_unlock(&dispatchMutex); return ret; } static struct IDeviceIoService g_rilAdapterService = { .Dispatch = RilAdapterDispatch,//服务对象里绑定服务功能分派函数 .Open = NULL, .Release = NULL, }; static int32_t RilAdapterBind(struct HdfDeviceObject *device) { if (device == NULL) { return HDF_ERR_INVALID_OBJECT; } device->service = &g_rilAdapterService;//绑定服务对象 return HDF_SUCCESS; }
9. coreservice中的ril管理层怎么使用riladapter hdf服务
9.1 ril管理层怎么获取 hdf服务,通过什么与HDF服务通讯
base\telephony\core_service\services\tel_ril\src\tel_ril_manager.cpp bool TelRilManager::OnInit() { bool res = false; int32_t i = 0; telRilCallback_ = this; death_ = sptr<OHOS::IPCObjectStub::DeathRecipient>(new HdfDeathRecipient(this)); do { res = ConnectRilAdapterService();//连接modem的HDF驱动服务,拿到能与modem的HDF驱动服务通讯的远端对象,并将自己告诉服务端,这样服务端的反馈信息也可以发送给自己(telRilCallback_,this) if (!res) { i++; sleep(1); } } while (!res && (i < RIL_INIT_COUNT_MAX)); if (res) { for (int32_t slotId = SIM_SLOT_0; slotId < SIM_SLOT_COUNT; slotId++) { InitTelModule(slotId); } } return res; } bool TelRilManager::ConnectRilAdapterService() { std::lock_guard<std::mutex> lock_l(mutex_); rilAdapterRemoteObj_ = nullptr; //获取驱动服务管理器 auto servMgr_ = OHOS::HDI::ServiceManager::V1_0::IServiceManager::Get(); if (servMgr_ == nullptr) { TELEPHONY_LOGI("Get service manager error!"); return false; } //通过服务名称获取能与该驱动服务通讯的远端对象 rilAdapterRemoteObj_ = servMgr_->GetService(RIL_ADAPTER_SERVICE_NAME.c_str()); if (rilAdapterRemoteObj_ == nullptr) { TELEPHONY_LOGE("bind hdf error!"); return false; } if (death_ == nullptr) { TELEPHONY_LOGE("create HdfDeathRecipient object failed!"); rilAdapterRemoteObj_ = nullptr; return false; } if (!rilAdapterRemoteObj_->AddDeathRecipient(death_)) { TELEPHONY_LOGE("AddDeathRecipient hdf failed!"); rilAdapterRemoteObj_ = nullptr; return false; } int32_t ret = SetCellularRadioIndication();//将自己发送给驱动服务端,告诉驱动服务端,通知消息发回给自己 if (ret != CORE_SERVICE_SUCCESS) { TELEPHONY_LOGE("SetCellularRadioIndication error, ret:%{public}d", ret); return false; } ret = SetCellularRadioResponse();//将自己发送给驱动服务端,告诉驱动服务端,响应消息发回给自己 if (ret != CORE_SERVICE_SUCCESS) { TELEPHONY_LOGE("SetCellularRadioResponse error, ret:%{public}d", ret); return false; } return true; }
9.2 调用Dial接口
base\telephony\core_service\services\tel_ril\src\tel_ril_base.cpp TelRilBase::TelRilBase( int32_t slotId, sptr<IRemoteObject> rilAdapterObj, std::shared_ptr<ObserverHandler> observerHandler) { observerHandler_ = observerHandler; cellularRadio_ = rilAdapterObj;//保存远端对象为成员变量 slotId_ = slotId; } base\telephony\core_service\services\tel_ril\src\tel_ril_call.cpp int32_t TelRilCall::Dial(const std::string address, int32_t clirMode, const AppExecFwk::InnerEvent::Pointer &result) { std::shared_ptr<TelRilRequest> telRilRequest = CreateTelRilRequest(HREQ_CALL_DIAL, result); if (telRilRequest == nullptr) { TELEPHONY_LOGE("telRilRequest is nullptr"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (cellularRadio_ == nullptr) { TELEPHONY_LOGE("%{public}s cellularRadio_ == nullptr", __func__); return TELEPHONY_ERR_LOCAL_PTR_NULL; } DialInfo dialInfo; dialInfo.address = address; dialInfo.clir = clirMode; dialInfo.serial = telRilRequest->serialId_; int32_t ret = SendBufferEvent(HREQ_CALL_DIAL, dialInfo);//调用的基类TelRilBase的SendBufferEvent发送IPC数据到HDF驱动服务端 TELEPHONY_LOGI("Send (ID:%{public}d) return: %{public}d", HREQ_CALL_DIAL, ret); return ret; } base\telephony\core_service\services\tel_ril\src\tel_ril_base.h template<typename T> int32_t SendBufferEvent(int32_t dispatchId, const T &eventData) { if (cellularRadio_ == nullptr) { TELEPHONY_LOGE("cellularRadio_ is nullptr!!!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } //序列化数据 MessageParcel data; MessageParcel reply; data.WriteInt32(slotId_); eventData.Marshalling(data); OHOS::MessageOption option = {OHOS::MessageOption::TF_ASYNC}; TELEPHONY_LOGI("Send event, dispatchId:%{public}d", dispatchId); //通过IPC发送序列化数据到服务端 return cellularRadio_->SendRequest(dispatchId, data, reply, option); } base\telephony\ril_adapter\services\hril_hdf\src\hril_hdf.c static int32_t RilAdapterDispatch( struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) { int32_t ret; static pthread_mutex_t dispatchMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&dispatchMutex); TELEPHONY_LOGI("RilAdapterDispatch cmd:%{public}d", cmd); //HDF驱动收到IPC请求后通过这里分派出去处理 ret = DispatchRequest(cmd, data); pthread_mutex_unlock(&dispatchMutex); return ret; }
10. 厂商库与HDF互调函数数据交换
10.1 厂商库将自己对外提供的接口函数数据绑定一个结构体对象
ril_adapter\services\vendor\src\vendor_adapter.c static const HRilCallReq g_callReqOps = { .GetCallList = ReqGetCallList, .Dial = ReqDial,//这里将g_callReqOps的.Dial绑定到了厂商库ReqDial函数 .Hangup = ReqHangup, .Reject = ReqReject, .Answer = ReqAnswer, .GetClip = ReqGetClip, .SetClip = ReqSetClip, .HoldCall = ReqHoldCall, .UnHoldCall = ReqUnHoldCall, .SwitchCall = ReqSwitchCall, .CombineConference = ReqCombineConference, .SeparateConference = ReqSeparateConference, .CallSupplement = ReqCallSupplement, .GetCallWaiting = ReqGetCallWaiting, .SetCallWaiting = ReqSetCallWaiting, .GetCallTransferInfo = ReqGetCallTransferInfo, .SetCallTransferInfo = ReqSetCallTransferInfo, .GetCallRestriction = ReqGetCallRestriction, .SetCallRestriction = ReqSetCallRestriction, .GetClir = ReqGetClir, .SetClir = ReqSetClir, .StartDtmf = ReqStartDtmf, .SendDtmf = ReqSendDtmf, .StopDtmf = ReqStopDtmf, .GetImsCallList = ReqGetImsCallList, .GetCallPreferenceMode = ReqGetCallPreferenceMode, .SetCallPreferenceMode = ReqSetCallPreferenceMode, .GetLteImsSwitchStatus = ReqGetLteImsSwitchStatus, .SetLteImsSwitchStatus = ReqSetLteImsSwitchStatus, .SetUssd = ReqSetUssd, .GetUssd = ReqGetUssd, .GetMute = ReqGetMute, .SetMute = ReqSetMute, .GetEmergencyCallList = ReqGetEmergencyCallList, .GetCallFailReason = ReqGetCallFailReason, };
10.2 加载厂商库通过rilInitOps并完成厂商库对外服务函数与HDF驱动数据接收处理函数的函数结构体对象交换
base\telephony\ril_adapter\services\hril_hdf\hril_hdf.c static void LoadVendor(void) { const char *rilLibPath = NULL; char vendorLibPath[PARAMETER_SIZE] = {0}; // Pointer to ril init function in vendor ril const HRilOps *(*rilInitOps)(const struct HRilReport *) = NULL; // functions returned by ril init function in vendor ril const HRilOps *ops = NULL; if (GetVendorLibPath(vendorLibPath) == HDF_SUCCESS) { rilLibPath = vendorLibPath; } else { rilLibPath = g_modem_list[MODEM_INDEX].path; } if (rilLibPath == NULL) { TELEPHONY_LOGE("dynamic library path is empty"); return; } g_dlHandle = dlopen(rilLibPath, RTLD_NOW); if (g_dlHandle == NULL) { TELEPHONY_LOGE("dlopen %{public}s is fail. %{public}s", rilLibPath, dlerror()); return; } //拿到厂商库的rilInitOps函数指针 rilInitOps = (const HRilOps *(*)(const struct HRilReport *))dlsym(g_dlHandle, "RilInitOps"); if (rilInitOps == NULL) { dlclose(g_dlHandle); TELEPHONY_LOGE("RilInit not defined or exported"); return; } ops = rilInitOps(&g_reportOps);//通过rilInitOps函数将存储厂商库的函数接口的对象交给HDF驱动服务端,并将HDF驱动服务端提供的信息上报函数接口交给厂商库。 HRilRegOps(ops);//将ops里存放的厂商库对外提供的功能接口函数指针保存到HDF驱动服务端,这样HDF驱动服务端就可以通过这些函数接口调用厂商库里的函数。 }
10.3 具体的厂商库执行接口函数ReqDial
ril_adapter\services\vendor\src\at_call.c void ReqDial(const ReqDataInfo *requestInfo, const HRilDial *data, size_t dataLen) { HRilDial *pDial = NULL; char cmd[MAX_CMD_LENGTH] = {0}; const char *clir = NULL; int32_t ret; int32_t err = HRIL_ERR_SUCCESS; struct ReportInfo reportInfo = {0}; ResponseInfo *pResponse = NULL; if (data == NULL) { TELEPHONY_LOGE("data is null!!!"); return; } pDial = (HRilDial *)data; switch (pDial->clir) { case CALL_CLIR_INVOCATION: clir = "I"; break; /* invocation */ case CALL_CLIR_SUPPRESSION: clir = "i"; break; /* suppression */ case CALL_CLIR_SUBSCRIPTION_DEFAULT: default: clir = ""; break; /* subscription default */ } //根据Dial参数生成AT指令 ret = GenerateCommand(cmd, MAX_CMD_LENGTH, "ATD%s%s;", pDial->address, clir); if (ret < 0) { TELEPHONY_LOGE("GenerateCommand is failed!"); OnCallReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL); return; } //发送AT指令并等待,直到拿到反馈信息或者超时 ret = SendCommandLock(cmd, NULL, 0, &pResponse); if (ret != 0) { err = HRIL_ERR_CMD_SEND_FAILURE; TELEPHONY_LOGE("ATD send failed"); } else { if (!pResponse->success) { TELEPHONY_LOGE("ReqDial return ERROR"); err = HRIL_ERR_CMD_NO_CARRIER; } } //创建上报的报告数据 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); //上报报告数据 OnCallReport(GetSlotId(requestInfo), reportInfo, NULL, 0); FreeResponseInfo(pResponse); }
10.4 厂商库执行接口函数ReqDial往modem写指令
ril_adapter\services\vendor\src\at_support.c int32_t SendCommandLock(const char *command, const char *prefix, long long timeout, ResponseInfo **outResponse) { const char *atCmd = "AT"; int32_t err; if (pthread_equal(g_reader, pthread_self()) != 0) { TELEPHONY_LOGE("The read thread prohibits sending commands."); return AT_ERR_INVALID_THREAD; } TELEPHONY_LOGI("command %{public}s, NeedATPause:%{public}d, atCmd:%{public}s", command, g_isNeedATPause, atCmd); pthread_mutex_lock(&g_commandmutex); if (g_isNeedATPause) { pthread_cond_signal(&g_commandcond); err = SendCommandNoLock(atCmd, timeout, outResponse); if (err != 0) { TELEPHONY_LOGI("NeedATPause err = %{public}d cmd:%{public}s", err, command); } if (g_atWatch != NULL) { g_atWatch(); } g_isNeedATPause = false; alarm(0); } g_prefix = prefix; //发送数据到下一层,并设置等待数据响应的超时时长 err = SendCommandNoLock(command, timeout, outResponse); pthread_mutex_unlock(&g_commandmutex); TELEPHONY_LOGI("err = %{public}d, cmd:%{public}s", err, command); // when timeout to process if (err == AT_ERR_TIMEOUT && g_onTimeout != NULL) { g_onTimeout(); } else if (err == AT_ERR_GENERIC) { TELEPHONY_LOGI("OnReaderClosed() err = %{public}d", err); OnReaderClosed(); } return err; } int32_t SendCommandNoLock(const char *command, long long timeout, ResponseInfo **outResponse) { long long defaultTimeOut = DEFAULT_LONG_TIMEOUT; int32_t err = 0; struct timespec time; err = NewResponseInfo(); if (err != VENDOR_SUCCESS) { TELEPHONY_LOGE("New responseInfo is fail, err:%{public}d.", err); return err; } //继续往下发送数据(这个函数调用了C库的write函数) err = WriteATCommand(command, 0, g_atFd); if (err != VENDOR_SUCCESS) { TELEPHONY_LOGE("send AT cmd is fail, err:%{public}d.", err); ClearCurCommand(); return err; } SetWaitTimeout(&time, (timeout != 0) ? timeout : defaultTimeOut); while (g_response->result == NULL && g_readerClosed == 0) { err = pthread_cond_timedwait(&g_commandcond, &g_commandmutex, &time); if (err == ETIMEDOUT) { err = AT_ERR_TIMEOUT; TELEPHONY_LOGE("pthread cond timedwait is timeout, err:%{public}d.", err); ClearCurCommand(); return err; } } if (outResponse == NULL) { FreeResponseInfo((ResponseInfo *)g_response); } else { *outResponse = (ResponseInfo *)g_response; } g_response = NULL; if (g_readerClosed > 0) { err = AT_ERR_CHANNEL_CLOSED; TELEPHONY_LOGE("g_readerClosed is closed, err:%{public}d.", err); ClearCurCommand(); return err; } err = 0; return err; } ril_adapter\services\vendor\src\vendor_channel.c int32_t WriteATCommand(const char *s, int32_t isPdu, int32_t atFd) { TELEPHONY_LOGI("cmd:%{public}s", s); ssize_t ret; size_t i = 0; size_t len = strlen(s); if (atFd < 0) { return AT_ERR_CHANNEL_CLOSED; } while (i < len) { do { //写数据到串口 ret = write(atFd, s + i, len - i); } while (ret < 0 && errno == EINTR); if (ret < 0) { return AT_ERR_GENERIC; } i += ret; } if (isPdu != 0) { do { ret = write(atFd, "\x1A", 1); } while ((ret < 0 && errno == EINTR) || (ret == 0)); } else { do { ret = write(atFd, "\r", 1); } while ((ret < 0 && errno == EINTR) || (ret == 0)); } if (ret < 0) { return AT_ERR_GENERIC; } return VENDOR_SUCCESS; }
10.5 厂商库循环读取modem的信息并处理
D:\OpenHarmony\base\telephony\ril_adapter\services\vendor\src\at_support.c int32_t ATStartReadLoop(int32_t fd, OnNotify func) { int32_t ret = 0; g_atFd = fd; g_onNotifyFunc = func; pthread_attr_t t; pthread_attr_init(&t); pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED); ret = pthread_create(&g_reader, &t, (void *(*)(void *))ReaderLoop, &t); if (ret < 0) { TELEPHONY_LOGE("create pthread error code: %{public}d", ret); return VENDOR_ERR_PROCESS; } return VENDOR_SUCCESS; } void ReaderLoop(void) {//循环读取串口的,获取modem对请求的响应信息以及主动上报信息 TELEPHONY_LOGI("%{public}s enter", __func__); g_readerClosed = 0; while (1) { const char *str = NULL; const char *pdu = NULL; str = ReadResponse(g_atFd);//读取modem的响应反馈信息或主动上报信息。 if (str == NULL) { TELEPHONY_LOGE("str is null"); break; } if (IsSmsNotify(str)) {//如果是短信,会继续读取拿到短信PDU内容数据 TELEPHONY_LOGI("new sms notify :%{public}s", str); pdu = ReadResponse(g_atFd);//读取PDU信息 TELEPHONY_LOGI("pdu :%{public}s", pdu); } ProcessResponse(str, pdu);//对信息进行拆解,分析,最后根据信息具体类型进行对应分发(主动上报或请求的响应反馈)。 } OnReaderClosed(); }
更多推荐
所有评论(0)