赞
踩
关于call模块的设计文档可以在服务器上(\Documents\MTK\From MTK\MMI\MMI_Features),这里笔者就不做重复劳动了,主要从实际的项目开发角度讲一讲call模块的开发。
首先,从大的概念上来说call模块维护了一个状态机,伴随着不同的action在不同状态(idle,active,hold,outgoing,incoming)之间翻转,这里的action指的是1.来自协议层的异步事件,比如说MSG_ID_MMI_CC_CALL_RING_IND这个消息就是协议层通知mmi有一个来电发生了,mmi这时候就会进行相应的状态翻转(idle à incoming),并做出界面上的显示,以达到和用户交互的作用。2.用户发起服务请求后,来自协议层的回馈消息,比如说来电后用户按接听键就会给协议层发一个
MSG_ID_MMI_CC_ATA_REQ请求,协议层响应此请求成功后,就回给mmi层一个MSG_ID_MMI_CC_ATA_RSP消息,此时mmi就会又一次进行状态的翻转(incoming à active),此时屏幕也将由来电窗口进入通话窗口。
在实际开发中修改的最多就是ucmui.c,ucmacthdlr.c了,ucmui.c里面几乎囊括了所有与界面显示相关的函数,其中最重要就是mmi_ucm_entry_incoming_call(来电),mmi_ucm_entry_outgoing_call(去电),mmi_ucm_entry_in_call(通话中),因为是做的mmi的嘛,所以界面上的修改大部分都集中在这三个函数里。Ucmacthdlr.c里主要是处理来自协议层的消息,发负责消息的派发以及逻辑上的处理,下面再详细讲解。
另外有些常用的函数如下:
isInCall(void); 这个函数通常被其他模块调用来判断是否有电话业务存在
mmi_ucm_app_total_call(mmi_ucm_call_type_enum call_type) 这个函数通常用来判断当前是否是单个电话
mmi_ucm_conference_option(void) 这个函数用来判断当前是否是电话会议状态
MakeCall(PS8 strNumber) 单卡向外拨打电话的接口
mmi_ucm_app_entry_dial_option(U8 *num_uri, mmi_ucm_callback_func_ptr callback_after_dial, void* callback_para)
双卡向外拨打电话的接口,它会显示一个sim卡选择窗口
mmi_ucm_app_active_call(mmi_ucm_call_type_enum call_type) 当前处于激活状态的电话有多少个
mmi_ucm_app_held_call(mmi_ucm_call_type_enum call_type) 当前处于保持状态的电话有多少个
mmi_ucm_ring_ind(void *act_struct) 来电消息处理的地方
mmi_ucm_connect_ind(void *act_struct) 接通消息处理的地方
mmi_ucm_release_ind(void *act_struct) 当有电话挂断处理的地方
mmi_ucm_alert_ind(void *act_struct) 拨号成功,对方提示播回铃音的地方
mmi_ucm_accept_act_rsp(void *act_struct) 接通来电处理的地方
dt_update_duration(void) 通话过程中计时处理的地方
mmi_ucm_log_call_history(S32 group_index, S32 call_index, MMI_BOOL is_connect)
电话模块用来保存通话纪录的接口
mmi_ucm_log_call_duration(S32 group_index, S32 call_index) 用来保存通话时长的接口
mmi_ucm_end_single_action(void) 挂断单个电话的接口
mmi_ucm_end_conference_action(void) 挂断电话会议的接口
mmi_ucm_conference_action(void) 组建电话会议的接口
mmi_ucm_hold_action(void) 保持电话的接口
mmi_ucm_retrieve_action(void) 恢复电话的接口
mmi_ucm_play_incoming_tone(void) 播放来电铃音的地方
mmi_ucm_play_inband_tone(void) 播放呼叫回铃音的地方
mmi_ucm_is_sos_number(mmi_ucm_call_type_enum call_type, U8 *num_uri) 判断是否紧急呼叫的接口
mmi_ucm_make_voice_call_from_incall_dialer_plus(void) 在通话中再次发起呼叫的接口
mmi_ucm_play_connect_notice(void) 进行接通提示的地方
mmi_ucm_entry_processing_screen(void) 界面切换时(如:来电 à 通话中)的进度条,注意这里不单纯是一个进度条窗口,它也屏蔽了按键响应,防止在协议栈回馈消息之前的误操作
mmi_ucm_master_incoming_call_present_ind_hdlr(void *inMsg) 开启黑名单,来电自动拒接的地方。
mmi_phb_call_get_data_for_call_mgnt(PU8 number, BOOL is_mo_call, U8 simInterface)
电话本模块提供给查找电话纪录信息的接口。
mmi_ucm_sync_call_list(void *act_struct) 电话模块维护了一个call_list数组用来保存每个电话的状态信息,
这个接口用来更新这些状态信息,当某个电话的状态发生改变的时候
下面结合“电话会议一键通”的功能再来讲讲call模块:
此功能是为了方便用户先预存一组号码,然后只按一次拨号键,就可以自动地将这一组号码组成电话会议的功能。
涉及的全局变量:
U8 g_subsequent_dial; //这个flag用来标记是否正在执行“电话会议一键通”
U8 g_subsequent_dial_total; //这是一个计数量,用来纪录还有多少号码没有拨完
U8 SubsequentDialNum[5][41 * ENCODING_LENGTH]; //这个数组纪录了所有待拨的号码
首先,当用户在拨号列表界面按下拨号键,手机会去拨预置的第一个号码,如果拨号成功会在mmi_ucm_connect_ind(void *act_struct)里处理,
void mmi_ucm_connect_ind(void *act_struct)
{
……
if((TRUE == g_subsequent_dial) && (g_subsequent_dial_total > 0) &&
(mmi_ucm_app_total_call(MMI_UCM_CALL_TYPE_NO_CSD) == 1)) /*第一次拨号*/
{
StartTimer(UCM_SUBSEQUENT_DIAL_TIMER, 1, mmi_ucm_make_voice_call_from_incall_dialer_plus);
/*使用timer这样的异步事件进行下一次拨号*/
}
……
}
如果第一次拨号不成功,则做如下处理
void mmi_ucm_dispatch_rsp(mmi_ucm_act_opcode_enum op_code, mmi_ucm_call_type_enum call_type, void *act_struct)
{
……
case MMI_UCM_DIAL:
mmi_ucm_dial_act_rsp(act_struct);
if((FALSE == ((mmi_ucm_act_rsp_struct*)act_struct)->result_info.result) && /*拨号不成功*/
(TRUE == g_subsequent_dial) && (g_subsequent_dial_total > 0))
{
StartTimer(UCM_SUBSEQUENT_DIAL_TIMER, 1, mmi_ucm_make_voice_call_from_incall_dialer_plus);
/*使用timer这样的异步事件进行下一次拨号*/
}
break;
……
}
当第二通电话打通,并形成multiparty-call的时候,在通话中界面做如下处理:
void mmi_ucm_entry_in_call(void)
{
……
if(TRUE == g_subsequent_dial)
{
if(mmi_ucm_conference_option() == TRUE) /*可以组建电话会议*/
{
StartTimer(UCM_SUBSEQUENT_DIAL_TIMER, 1, mmi_ucm_conference_action);
/*使用timer这样的异步事件进行电话会议的组建*/
return;
}
Else if((mmi_ucm_app_active_call(MMI_UCM_CALL_TYPE_NO_CSD)
== mmi_ucm_app_total_call(MMI_UCM_CALL_TYPE_NO_CSD)) ||
(mmi_ucm_app_held_call(MMI_UCM_CALL_TYPE_NO_CSD)
== mmi_ucm_app_total_call(MMI_UCM_CALL_TYPE_NO_CSD)))
{
if(g_subsequent_dial_total > 0)
return; /*如果还有电话未拨完,直接返回,不进入通话中的界面*/
else
{
g_subsequent_dial = FALSE;
if((mmi_ucm_retrieve_conference_option() == TRUE) ||
(mmi_ucm_retrieve_single_option() == TRUE))
{
StartTimer(UCM_SUBSEQUENT_DIAL_TIMER, 1, mmi_ucm_retrieve_action);
/*如果所有电话都已拨号完毕,使用timer这样的异步事件进行电话会议的恢复*/
}
}
}
else
return;
}
……
}
当通话会议建立完毕,接着进行下一次拨号
void mmi_ucm_dispatch_rsp(mmi_ucm_act_opcode_enum op_code, mmi_ucm_call_type_enum call_type, void *act_struct)
{
……
case MMI_UCM_CONFERENCE:
if(FALSE == ((mmi_ucm_act_rsp_struct*)act_struct)->result_info.result)
{
g_subsequent_dial = FALSE;
g_subsequent_dial_total = 0; /*如果通话会议建立不成功,则停止拨号过程*/
}
mmi_ucm_act_rsp(act_struct);
if((TRUE == g_subsequent_dial) && (g_subsequent_dial_total > 0))
{
StartTimer(UCM_SUBSEQUENT_DIAL_TIMER, 1, mmi_ucm_make_voice_call_from_incall_dialer_plus);
/*如果电话会议组建成功,则使用timer这样的异步事件进行下一次拨号*/
}
break;
……
}
重复以上过程,最后即可建立电话会议。
This function is to handle the indication sent from ucm srv
mmi_ret mmi_ucm_ind_hdlr(mmi_event_struct* para)
void mmi_ucm_entry_in_call(void) 没有用
void mmi_ucm_accept_act_rsp(srv_ucm_act_rsp_struct *rsp, srv_ucm_act_type_enum act_type)
if ((IsBacklightOn() == MMI_FALSE))
{
TurnOnBacklight(1);
}
跟踪记录
第一次事件
SRV_UCM_OUTGOING_CALL_IND:
第二次事件
SRV_UCM_RELEASE_IND:
mmi_ucm_release_ind(release_ind);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。