OpenHarmony开发者论坛

标题: OpenHarmony电话子系统源码流程解析 [打印本页]

作者: Laval社区小助手    时间: 2023-12-26 15:50
标题: OpenHarmony电话子系统源码流程解析
[md]## 前言

**电话子系统各子模块业务比较繁杂,本文解析梳理的侧重点不是理清电话子系统详细业务流程,重点是明晰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/:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/image/%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E5%9C%A8OpenHarmony%E6%9E%B6%E6%9E%84%E4%B8%AD%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%9B%BE.png?lastModify=1686125309)

![](https://devpress.csdnimg.cn/aaf6056702a44b1c95d07b4ae2899f89.png)

### 电话子系统通话管理主流程图以及分层说明

**通话模块->蜂窝模块->coreservice模块->riladapter以及厂商库模块**

**通话模块:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/image/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%A1%86%E5%9B%BE1.png?lastModify=1686125309)

![](https://devpress.csdnimg.cn/e5dab6a625354b7f82e128103ccea2b6.png)

**蜂窝模块:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/image/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%A1%86%E5%9B%BE2.png?lastModify=1686125309)

![](https://devpress.csdnimg.cn/c0bfa55586304466831aaeb3cbb7c524.png)

**CoreService模块:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/image/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%A1%86%E5%9B%BE3.png?lastModify=1686125309)

![](https://devpress.csdnimg.cn/68c95654c4d1443ba0d7353229c23f27.png)

**riladapter以及厂商库模块:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%BA%90%E7%A0%81%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/image/OpenHarmony%E7%94%B5%E8%AF%9D%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%A1%86%E5%9B%BE4.png?lastModify=1686125309)

![](https://devpress.csdnimg.cn/3e532ef1fceb4e71b7bfebcf662925d0.png)

**分层说明: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:ialCall(std::u16string number, AppExecFwk:acMap &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:ialCall(std::u16string number, AppExecFwk:acMap &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:acMap 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:ialCall(std::u16string number, AppExecFwk:acMap &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("ermission denied!");
     return TELEPHONY_ERR_PERMISSION_ERR;
  }

  if (callControlManagerPtr_ != nullptr) {
     return callControlManagerPtr_->DialCall(number, extras);//调用CallControlManager:ialCall
  } 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:ialCall(std::u16string &number, AppExecFwk:acMap &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:ialCall
  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:ialCall()
{
  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:ialCallEvent(const AppExecFwk::InnerEvent:ointer &event)
{
  if (event == nullptr) {
     TELEPHONY_LOGE("CallRequestHandler:rocessEvent parameter error");
     return;
  }
  if (callRequestProcessPtr_ == nullptr) {
     TELEPHONY_LOGE("callRequestProcessPtr_ is nullptr");
     return;
  }
  callRequestProcessPtr_->DialRequest();//调用CallRequestProcess:ialRequest函数
}
```

#### 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:ialRequest()
{
  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("ackCellularCallInfo 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:HONE_TYPE_IS_GSM) {
     return DialGsm(callInfo);//根据netType来决定调用GSM拨号,还是其它。我们以DialGsm来拉通流程
  }
  if (netType == PhoneType:HONE_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:ointer 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();
}
```
[/md]




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5