571
社区成员




电话子系统各子模块业务比较繁杂,本文解析梳理的侧重点不是厘清电话子系统详细业务流程,重点是明晰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的。
源码位于源码根目录下的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:负责运营商网络的基础通话实现
./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
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服务
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",
]
./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服务
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);
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;
}
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。
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>
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服务
举例:下面使用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:
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对端反馈的返回码
}
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;
}
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;
}
}
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;
}
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;
}
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;
}
上面发出的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函数
}
如果是用到运营商蜂窝基站来打电话,还要蜂窝通话的核心服务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;
}
}
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;
}
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;
}
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;
}
如何跳转到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;
}
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;
}
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
}
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函数
}
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;
}
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处理
}
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;
}
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;
}
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;
}
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驱动服务对外曝露的服务名称
}
}
}
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);
static int32_t RilAdapterInit(struct HdfDeviceObject *device)
{
...
TELEPHONY_LOGI("sbuf IPC obtain success!");
LoadVendor();//加载厂商库
return HDF_SUCCESS;
}
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;
}
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;
}
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;
}
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,
};
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驱动服务端就可以通过这些函数接口调用厂商库里的函数。
}
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);
}
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;
}
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();
}
你好,请问这篇文章可以转载吗?会标注作者及来源的