网络挂断一通电话​
网络挂断时,L4发送消息PRT_NWRK_CALL_RELEASE,进入回调函数:
void PsCBackNetworkCallDropped(void *info)
{
if (GetInternalAlert() == TRUE)
{
StopInternalOutgoingTone();
}

ProcessIncomingEvents(CM_PS_NWK_CALL_DROP, info);
}
g_bUserReject = FALSE; 表示不是用户拒接的,而是missed call
ACTION_RESULT ProcessEndCallIdAndGoBack(void *info)
{
/* when there's pending req on the dropped call, sync all call state with PS */
if (GetCallflag(handle, TRUE) & (~CM_HANGUP_REQUESTED) != 0)
{
SyncCallList();
}

switch(被挂断电话的当前状态)
{
case CM_INCOMING_STATE: 网络挂断的是来电(对方放弃)
SetCallEndCause(0); gCallEndCause
ProcessIncomingEvents(CM_PS_INCOMING_CALL_DROPPED, info);主动拒 接任何一种电话的时候,最后也是进入这个状态机中处理。 这里没有设置主动拒接的变量标志g_bUserReject
break;
case CM_OUTGOING_STATE: 网络挂断的是OUTGOING CALL,(对方拒接)
LogCallInfoForCallHistory(GetOutgoingCallHandle());
GetEndTimeAndLogUnconnectedMOCall();

if启动了自动重拨,
则设置一些参数
return;

设置CM以及CALL的状态。
EntryScr1004NotifyEndCallDuration( );
break;
case CM_HOLD_CALL:
case CM_ACTIVE_CALL:
SetCallflag(handle, CM_HANGUP_REQUESTED, TRUE);
OutgoingProcessCMEvent(CM_PS_HANGUPSUC, (void*)&handle);进入函数 ProcessPSHangupSucEvent()进行处理。(所有的挂断电话,放 弃呼出电话,最后都是进入这个函数进行处理)
}
}






重要总结:​
1. 只有1通ACTIVE CALL时的【暂停】,N通ACTIVE CALL的【保留所有通话】选项都是HiliteM2010ActiveHold(),响应函数是MakeActiveCallHold(),操作都是把ACTIVE CALL HOLD起来。​
2. 在1中的ACTIVE CALL变成HOLD CALL之后,如果再恢复通话,即恢复到1通ACTIVE CALL,或者恢复到N通ACTIVE CALL(电话会议),响应函数是:RetrieveHeldCall()。​

但是,当发生呼叫等待时,上面2种情况的响应函数都为:HiliteM2014Swap( )。即:​
在只有1通ACTIVE CALL时,发生呼叫等待,此时【暂停】的响应函数​
当有N通ACTIVE CALL时,发生呼叫等待,【保留所有通话】的响应函数​
只有1通HOLD CALL时,呼叫等待,【恢复通话】的响应函数​
有N通HOLD CALL时,呼叫等待,【恢复通话】的响应函数​
也就是说,在发生呼叫等待的情况下,电话的ACTIVE与HOLD这两种状态之间的切换,响应函数都是:HiliteM2014Swap()。​
另外:所有的【切换】的响应函数也是HiliteM2014Swap()。​
我的理解:​
MakeActiveCallHold()和RetrieveHeldCall()所发送到L4的消息都是:PRT_RETIEVECALL_EVENT,消息的opnode: CSMCC_HOLD_ACTIVE_AND_ACCEPT。可以看出,这个消息实际上是HOLD当前的ACTIVE CALL,然后接听来电(上面的接听呼叫等待的电话,就是这样的过程)。只不过在没有呼叫等待时,只能是ACTIVE CALL与HOLD CALL之间进行切换,换句话说,如果此时有来电的话,在L4层还是会接听的。正因为这个原因,在有呼叫等待时,如果仅仅是想ACTIVE与HOLD之间转换一下而不接听来电,才只有进行swap,即发送PRT_SWAPCALL_EVENT消息。​


详细如下:​
1.没有呼叫等待时,电话从ACTIVE——>HOLD​
void MakeActiveCallHold(void)
{
OutgoingProcessCMEvent(CM_KB_HOLDREQ, (void *)NULL);
}

ACTION_RESULT ProcessKBHoldReqEvent(void *MsgStruct)
{
在HOLD之前,必须确保:gChldReqSent=CM_ACTION_NONE
if (GetChldReqSent() != CM_ACTION_NONE)
{
return CM_CALL_FAILURE;
}

保证所有的电话没有:
CM_SWAP_REQUESTED,CM_CONF_REQUESTED,CM_ECT_REQUESTED这些标志。

switch (GetCurrentState()) //此时,只可能是ACTIVE STATE
{
case CM_ACTIVE_STATE:
SetHoldFlag(); 设置当前所有的ACTIVE CALL的 status_flag=CM_HOLD_REQESTED
MakePsActiveHold((void*)HoldReqSucess);
提醒:在ACTIVE状态下发生呼叫等待,如果接听的话,要先HOLD这个ACTIVE CALL,然后才能接听。那么HOLD这个ACTIVE CALL的时候,也是调用MakePsActiveHold()这个函数,但是传送的CBACK函数不一样。
break;
}
}void MakePsActiveHold(void *callBack)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
发送到L4的消息是:PRT_RETIEVECALL_EVENT
消息的opnode是:CSMCC_HOLD_ACTIVE_AND_ACCEPT
}
L4返回消息是:PRT_END_CHLD_RSP,进入CBACK函数:
void HoldReqSucess(void *MsgStruct)
{
OutgoingProcessCMEvent(CM_PS_HOLDSUC, (void*)MsgStruct);
}
ACTION_RESULT ProcessPSHoldSucEvent(void *MsgStruct)
{
MakeHold(); 对所有当前状态为ACTIVE的CALL,清除其CM_HOLD_REQUESTED标志,并且设置其当前状态为CM_HOLD_STATE。如果所有的CALL都为HOLD状态,那么就设置CM的当前状态为CM_HOLD_STATE。

EntryScr1005NotiryHoldSucess()
}

2.没有发生呼叫等待时,电话从HOLD——>ACTIVE
void RetrieveHeldCall(void)
{
OutgoingProcessCMEvent(CM_KB_RETRIEVEREQ, (void*)NULL);
}
ACTION_RESULT ProcessKBRetrieveReqEvent(void *MsgStruct)
{
确定gChldReqSent==CM_ACTION_NONE
确定所有的CALL都没有:
CM_SWAP/CONF/ECT_REQUESTED这3个标志
SetRetrieveFlag(); 对所有当前状态为CM_HOLD_STATE的CALL,设置它的 status_flag=CM_RETRIEVE_REQUESTED
MakePsActiveHold((void*)RetrieveReqSucess);与上面的HOLD一个ACTIVE CALL,发 送到L4的消息是一样的,仅仅是CBACK函数不一样
}
void MakePsActiveHold(void *callBack)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
发送到L4的消息是:PRT_RETRIEVECALL_EVENT
消息的opnode:CMSCC_HOLD_ACTIVE_AND_ACCEPT
}
L4返回消息:PRT_END_CHLD_RSP,进入:
void RetrieveReqSucess(void *MsgStruct)
{
OutgoingProcessCMEvent(CM_PS_RETRIEVESUC, (void*)MsgStruct);
}
ACTION_RESULT ProcessPSRetrieveSucEvent(void *MsgStruct)
{
MakeRetrieve();清除上面设置的:所有HOLD CALL的status_flag标志,并且设置CALL 的当前状态为ACTIVE STATE。
EntryScr1006NotifyRetrieveSucess();
设置CM的当前状态为CM_ACTIVE_STATE。注意:如果此时刚好开始发生呼叫等 待,那么要设置CM的prev_state=CM_ACTIVE_STATE(当前状态在呼 叫等待的处理中已经设置了)。
}

3.所有状态下的【切换】响应函数+在已经存在呼叫等待时,ACTIVE CALL与HOLD CALL之间的单向切换(【暂停】,【恢复通话】等)
void SwapCall(void)
{
OutgoingProcessCMEvent(CM_KB_SWAPREQ, (void*)NULL);
}
ACTION_RESULT ProcessKBSwapReqEvent(void *MsgStruct)
{
确定所有的CALL中都没有CM_SWAP/CONF/ECT_REQUESTED这3个标志
对当前的所有状态为ACTIVE和HOLD的CALL,设置其
status_flag=CM_SWAP_REQUESTED
MakePsSwapCallRequest((void*)SwapReqSucess);
}
void MakePsSwapCallRequest(void *callBack)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
发送的消息是:PRT_SWAPCALL_EVENT
消息的opnode是:CSMCC_SWAP_CALL
}
L4返回消息:PRT_END_CHLD_RSP,进入CBACK函数:
void SwapReqSucess(void *MsgStruct)
{
OutgoingProcessCMEvent(CM_PS_SWAPSUC, (void*)MsgStruct);
}
ACTION_RESULT ProcessPSSwapSucEvent(void *MsgStruct)
{
首先与L4同步电话
if (GetTotalCallCount() > 0)
{
SyncCallList();
}

MakeSwap();检查当前所有CALL的当前状态:如果是ACTIVE,就设置为HOLD;如 果是HOLD,就设置为ACTIVE。清除他们的status_flag的 CM_SWAP_REQUESTED标志。然后,根据当前存在的CALL的不同状 态来设置CM的当前和之前状态。要注意的是,如果有呼叫等待的电话, 那么CM的当前状态是为CM_INCOMING_STATE。
EntryScr1007NotifySwapSucess();
}


挂断电话:包括挂断所有电话,挂断ACTIVE CALL,挂断HOLD CALL。。。。。。​

1.在只有1通ACTIVE CALL,或者只有1通HOLD CALL时,【结束】菜单的响应函数
2.大于1通电话时(不论有几通ACTIVE CALL,几通HOLD CALL),【所有结束】菜单的响应函数
3.大于1通电话时,并且发生呼叫等待,【所有结束】菜单的响应函数
以上3种情况的响应函数都是:KbCBackEndAllCallsExceptIncoming():结束所有的电话
void KbCBackEndAllCallsExceptIncoming(void)
{
UnSilencethePhone();
OutgoingProcessCMEvent(CM_KB_HANGUPALLREQ, (void*)NULL);
}
ACTION_RESULT ProcessKBHangupallReqEvent(void *MsgStruct)
{
SetAllHangupFlag();对所有的CALL,如果当前状态为:HOLD,ACTIVE,OUTGOING, 那么就设置其status_flag=CM_HANGUP_REQUESTED.
SetAllExceptWaitingCallState(CM_DISCONNECTING_STATE); 对所有的CALL,如果当 前状态为:HOLD,ACTIVE,OUTGOING,那么就设置其当前状 态为:CM_DISCONNECTING_STATE.
MakePsHangupallRequest((void*)HangupallReqSucess);
}
void MakePsHangupallRequest(void *callBack)
{
ClearInputEventHandler(MMI_DEVICE_ALL);
SetChldReqSent(CM_HANGUPALL_REQ_SENT);设置gChldReqSent

发送到L4的消息是:PRT_ENDALLCALL_EVENT
消息的opnode:CMSCCD_REL_ALL_EXCEPT_WAITING_CALL
L4返回的消息是:PRT_ENDALLCALLREQ_SUCCESS.

提醒:挂断一通电话时的消息是:
PRT_CALLENDSPECIFIC_EVENT
opcode=CSMCC_REL_SPECIFIC_CALL
L4返回:PRT_CALLENDSPECIFIC_SUCCESS

SetProtocolEventHandler((PsFuncPtr) callBack, PRT_ENDALLCALLREQ_SUCCESS);
SetProtocolEventHandler((PsFuncPtr) CheckFailureChld, PRT_END_CHLD_RSP);
这里注册了2个CBACK函数。​
}
进入CBACK函数:
void HangupallReqSucess(void *MsgStruct)
{
gMyhandle = DeriveCallHandle(MsgStruct);
OutgoingProcessCMEvent(CM_PS_HANGUPALLSUC, (void*)&gMyhandle);
}
ACTION_RESULT ProcessPSHangupallSucEvent(void *MsgStruct)
{
LogCallInfoForCallHistory(*handle);
GetEndTimeAndNotifyEndCallDuration(*handle);
SetCallState((*handle), CM_IDLE_STATE, TRUE);
设置CM的状态。
}

小结:当有N通电话时,如果选择结束所有,那么在CBACK函数HangupallReqSucess()中,只处理第一通电话,也就是call handle=1的电话。其他的电话挂断处理都是通过L4返回消息:PRT_NWRK_CALL_RELEASE,进入PsCBackNetworkCallDropped(void *info),最后进入ProcessPSHangupSucEvent()进行处理的,相当于一通一通的挂断电话。​