OpenHarmony 通话应用源码剖析

Posted hhy1823799

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenHarmony 通话应用源码剖析相关的知识,希望对你有一定的参考价值。

一、简介

通话应用主要提供通话相关用户交互界面,根据电话服务子系统提供的通话数据和状态显示语音去电界面、语音来电界面、语音通话界面、语音多方通话界面、会议通话界面、会议管理界面;并根据用户界面上的操作完成接听、挂断、拒接、静音、保持、音频通道切换、DTMF键盘指令等下发电话服务子系统。
二、架构图
三、代码结构
/applications_call
├── callui # 通话应用主Ability,提供拉起应用入口
│ └── src
│ └── main
│ ├── ets # ets代码目录
│ ├── default
│ ├── assets # 图片资源
│ ├── common # 公共组件或方法配置目录
│ ├── components # 公共组件
│ ├── configs # 应用配置对象目录
│ ├── constant # 应用常量对象目录
│ ├── utils # 公共方法
│ ├── model # Model层代码目录
│ ├── pages # 通话页面目录
| ├── app.ets # 全局ets逻辑和应用生命周期管理文件
│ ├── ServiceAbility # 服务ability
│ ├── callManagerService.ets # ServiceAbility方法
│ ├── service.ts # ServiceAbility方法
│ ├── telephonyApi.ets # ServiceAbility方法
│ ├── resources # 资源配置文件存放目录
| ├── base # 默认图片资源,字体大小,颜色资源存放目录
| ├── zh_CN # 中文语言场景资源内容存放目录
│ ├── config.json # 全局配置文件
├── figures # 架构图目录
│ └── callui_en.png # 架构设计图
├── signature # 签名证书文件目录
│ └── com.ohos.callui.p7b # 签名文件
├── LICENSE # 许可证
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
四、流程图
五、时序图
六、源码分析
1、启动通话常驻服务
开机启动 通话应用常驻服务PA, 由元能力子系统拉起 代码路径/foundation/aafwk/standard/services/abilitymgr/src/ability_manager_service.cpp
void AbilityManagerService::StartingPhoneServiceAbility()

HILOG_DEBUG("%publics", __func__);
auto bms = GetBundleManager();
CHECK_POINTER_IS_NULLPTR(bms);
AppExecFwk::AbilityInfo phoneServiceInfo;
Want phoneServiceWant;
phoneServiceWant.SetElementName(AbilityConfig::PHONE_SERVICE_BUNDLE_NAME,
AbilityConfig::PHONE_SERVICE_ABILITY_NAME);
auto userId = GetUserId();
int attemptNums = 1;
HILOG_DEBUG("%publics, QueryAbilityInfo, userId is %publicd", __func__, userId);
IN_PROCESS_CALL_WITHOUT_RET(
while (!(bms->QueryAbilityInfo(phoneServiceWant,
OHOS::AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT, userId, phoneServiceInfo)) &&
attemptNums <= MAX_NUMBER_OF_CONNECT_BMS)
HILOG_INFO("Waiting query phone service ability info completed.");
usleep(REPOLL_TIME_MICRO_SECONDS);
attemptNums++;

);
(void)StartAbility(phoneServiceWant, userId, DEFAULT_INVAL_VALUE);

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
2、服务注册监听
service ability 应用启动加载入口文件service.ts文件, 执行onStart钩子函数, 实例化CallManagerService类时添加注册监听, registerCallStateCallback 调用注册电话子系统接口function on(type: ‘callDetailsChange’, callback: Callback<CallAttributeOptions>): void;
添加注册监听子系统上报的状态
/**

  • add register listener

*/
addRegisterListener()
this.mTelephonyCall.registerCallStateCallback(this.getCallData.bind(this));


public registerCallStateCallback(callBack)
call.on(callDetailsChange, (data) =>
if (!data)
HiLog.i(TAG,prefixLog + call.on registerCallStateCallback + JSON.stringify(data))
return;

HiLog.i(TAG,prefixLog + call.on registerCallStateCallback callState: + JSON.stringify(data.callState))
callBack(data);
);

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
根据上报通话当前状态校验是来电还是去电如果是就做拉起操作, 否则通话发布公共事件;
getCallData(callData)
this.callData = callData;
this.updateCallList();
const callState = this.callData;
/**

  • single call or dialing pull up the application

*/
if ((callState = CALL_STATUS_INCOMING && this.callList.length = 1) || callState === CALL_STATUS_DIALING)

this.startAbility(callData);
else if (callState !== CALL_STATUS_DISCONNECTING)
this.publishData(callData);


publishData(callData)
commonEvent.publish(callui.event.callDetailsChange,
bundleName: CALL_BUNDLE_NAME,
isOrdered: false,
data: JSON.stringify(callData)
, (res) =>
HiLog.i(TAG, "callUI service commonEvent.publish callback res : %s")
);

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
3、服务注册公共事件广播
在启动注册监听后同时也注册添加公共事件广播, 其中’callui.event.callEvent’事件监听通话FA获取初始化数据, ‘callui.event.click’ 事件监听systemui 通知栏操作按钮事件;
const events = [callui.event.callEvent, callui.event.click];
async addSubscriber()
subscriber = await new Promise((resolve) =>
commonEvent.createSubscriber(
events
, (err, data) =>
HiLog.i(TAG, "addSubscriber %s")
resolve(data);
);
);
commonEvent.subscribe(subscriber, (err, res) =>
if (err.code === 0)
if (res.event === events[0])
const obj = JSON.parse(res.data);
if (obj && obj.key === getInitCallData)
this.publishData(this.callData);


if (res.event === events[1])
const callId,btnType = res.parameters
this.btnclickAgent(callId, btnType)

else
HiLog.i(TAG, "callui service commonEvent.subscribe failed err : %s" + JSON.stringify(err))

subscriber.finishCommonEvent()
.then(() =>
HiLog.i(TAG, "addSubscriber finishCommonEvent : %s")
)
);

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
4、拉起通话应用初始化数据
在service中通过 PA.startAbility方法拉起 通话FA应用, 通话应用FA在启动入口页面index, 实例化CallManager类,调用initCallData方法, 获取初始通话数据, 调用update更新通话状态;
private initCallData()
featureAbility.getWant().then((want) =>
if (want && want.parameters && (callState in want.parameters))
this.update(want.parameters);
HiLog.i(TAG, "initCallData featureAbility.getWant : %s")
else
this.mCallServiceProxy.publish(
key: getInitCallData,
params: []
);

)
.catch((error) =>
HiLog.i(TAG, "initCallData catch error : %s" + JSON.stringify(error))
);

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
5、更新通话状态
在CallManger类实例化时候, 添加公共事件广播监听’callui.event.callDetailsChange’, 应用中订阅到数据调用callDataManager中的update方法,更新callData和callList校验通话状态, 是单方通话或者是多方通话;

以上是关于OpenHarmony 通话应用源码剖析的主要内容,如果未能解决你的问题,请参考以下文章

《OpenHarmony 3GPP协议开发深度剖析》之--PLMN业务源码解读

v78.01 鸿蒙内核源码分析(消息映射篇) | 剖析LiteIpc(下)进程通讯机制 | 百篇博客分析OpenHarmony源码

v78.01 鸿蒙内核源码分析(消息映射篇) | 剖析LiteIpc(下)进程通讯机制 | 百篇博客分析OpenHarmony源码

《OpenHarmony 3GPP协议开发深度剖析》--不得不弄明白的RIL

OpenHarmony 源码解析之DFX子系统-Hiview(上)

OpenHarmony 源码解析之DFX子系统-标准系统接口使用说明