前置文章:
《 Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划》《Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析》
《Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析》
《Android 4.4 Kitkat Phone工作流程浅析(四)__RILJ工作流程简析》
《Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析》
《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》
《Android 4.4 Kitkat Phone工作流程浅析(七)__来电(MT)响铃流程》
概述
通过前面一系列的文章,我们对整个Phone模块有了基本的了解,本文主要目的是分析在整个Telephony架构中Phone的状态以及它们之间的关系。关于Phone状态改变后的通知流程,请大家参看《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》。
在《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》的概述中,我们提到Call的状态分为6种:ACTIVE、HOLDING、DIALING、ALERTING、INCOMING、WAITING。这里的依据是什么呢?在Google AOSP代码中,我们可以看到google使用的是AT+CLCC的方式来获取当前通话信息的,CLCC的状态描述总共有6种,也就是:active(0)、held(1)、dialing(2)、alterting(3)、incoming(4)、waiting(5),括号里为状态对应的数值,关于AT+CLCC的指令描述,请大家参考相关AT文档。这些状态值由Modem端返回,也就是说所有Call状态的源头在Modem端。
但是,MTK并没有使用CLCC查询方式,而是改用了AT+ECPI的方式,根据ECPI的msg_type来判断当前Modem的状态,归根结底还是上面提到6种状态。详细请参看《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》中Telephony Framework接收处理反馈部分,该部分有简单分析MTK自己添加的AT指令ECPI。
我们还是按照自底向上的方式分析状态改变的流程,从Telephony Framework开始,然后是TeleService,最后是InCallUI,整个流程如下图:
状态来源—— Modem
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: AT< +ECPI: 1,130,0,0,0,0,"13800138000",129,""
ECPI的格式如下:
+ECPI:<call_id>,<msg_type>,<is_ibt>,<is_tch>,<dir>,<call_mode>,[<number>,<type>],[<disc_cause>]
对应的信息如下图:
DriverCall. State状态获取
//... ...省略
if (msgType == 132 || msgType == 6)
dc.state = DriverCall.State.ACTIVE;
else if (msgType == 131)
dc.state = DriverCall.State.HOLDING;
else if (msgType == 130 && callId != 254)
dc.state = DriverCall.State.DIALING;
else if (msgType == 2)
dc.state = DriverCall.State.ALERTING;
else if (msgType == 0)
{
for (j = 0; j < MAX_CONNECTIONS; j++) {
if (mConnections[j] != null) {
count ++;
}
}
if (mState == PhoneConstants.State.IDLE ||
(count == 0 && mForegroundCall.getState() == GsmCall.State.DIALING))
{
dc.state = DriverCall.State.INCOMING;
}
else
dc.state = DriverCall.State.WAITING;
}
//... ...省略
也就是说DriverCall.State由ECPI的msg_type和callId值共同决定,这里我们主要看msg_type,它们之间的对应关系如下图:
Call. State (Internal)状态获取
这里的Call指的是com.android.internal.telephony.Call,源码路径在SourceCode/frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java。该类是一个抽象类,其子类有GsmCall、CDMACall,这里我们只关心GsmCall。
在GsmCallTracker的handleCallProgressInfo()方法中,完成DriverCall.State的转换后,便开始执行DriverCall.State和Call.State的转换了,关键代码如下:
//... ...省略
if (conn == null)
{
log("1. new connection appeared!!");
if (mPendingMO != null)
{
//DriverCall.S