Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
来源:互联网 发布:京瓷1125mfp 网络配置 编辑:程序博客网 时间:2024/05/21 02:52
前置文章:
《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:<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.State.DIALING
- if (msgType == 130)
- {
- log("1.1. it is a MO call");
- mConnections[i] = mPendingMO;
- mPendingMO.mIndex = i;
- //GsmConnection根据DriverCall更新GsmCall
- mPendingMO.update(dc);
- mPendingMO = null;
- //... ...省略
- }
- //... ...省略
- }
- //DriverCall.State.INCOMING/DriverCall.State.WAITING
- else if (msgType == 0)
- {
- log("1.2 it is a MT call");
- //根据DriverCall新建GsmConnection对象,并根据DriverCall状态获取
- //对应的GsmCall对象
- mConnections[i] = new GsmConnection(mPhone.getContext(), dc, this, i);
- //... ...省略
- }
- //... ...省略
- }
- //... ...省略
从以上代码可以看出,针对MT和MO流程采用了不同的方式获取Call.State。
MO流程获取Call. State (Internal)
MO流程使用GsmConnection的update()方法来获取Call.State(internal),关键代码如下:
- update (DriverCall dc) {
- GsmCall newParent;
- //... ...省略
- //根据DriverCall.State获取与之对应的GsmCall对象
- newParent = parentFromDCState(dc.state);
- //... ...省略
- //更新Call.State
- if (newParent != mParent) {
- if (mParent != null) {
- //移除先前连接,并将State设置为Call.State.IDLE
- mParent.detach(this);
- }
- //增加当前连接,并更新State
- newParent.attach(this, dc);
- mParent = newParent;
- changed = true;
- } else {
- boolean parentStateChange;
- //更新State
- parentStateChange = mParent.update (this, dc);
- changed = changed || parentStateChange;
- }
- //... ...省略
- return changed;
- }
我们看到parentFromDCState()方法,这里实际上是根据DriverCall.State来获取对应的GsmCall对象,如下:
- private GsmCall
- parentFromDCState (DriverCall.State state) {
- switch (state) {
- case ACTIVE:
- case DIALING:
- case ALERTING:
- return mOwner.mForegroundCall;
- //break;
- case HOLDING:
- return mOwner.mBackgroundCall;
- //break;
- case INCOMING:
- case WAITING:
- return mOwner.mRingingCall;
- //break;
- default:
- throw new RuntimeException("illegal call state: " + state);
- }
- }
在根据DriverCall.State获取GsmCall对象之后,便根据GsmCall的detach()、attach()、update()方法来更新Call.State,而更新代码的关键是stateFromDCState(),关键代码如下:
- mState = stateFromDCState (dc.state);
- static State
- stateFromDCState (DriverCall.State dcState) {
- switch (dcState) {
- case ACTIVE: return State.ACTIVE;
- case HOLDING: return State.HOLDING;
- case DIALING: return State.DIALING;
- case ALERTING: return State.ALERTING;
- case INCOMING: return State.INCOMING;
- case WAITING: return State.WAITING;
- default: throw new RuntimeException ("illegal call state:" + dcState);
- }
- }
到这里完成了MO流程DriverCall.State和Call.State(internal)的映射。
MT流程获取Call. State (Internal)
MO的Call.State获取是通过pendingMO.update()方法发起的,而MT流程则是通过实例化GsmConnection对象发起的,代码如下:
- mConnections[i] = new GsmConnection(mPhone.getContext(), dc, this, i);
- GsmConnection (Context context, DriverCall dc, GsmCallTracker ct, int index) {
- //... ...省略
- //根据DriverCall.State获取GsmCall
- mParent = parentFromDCState (dc.state);
- //增加GsmConnection并更新Call.State
- mParent.attach(this, dc);
- }
后续和MO的流程一致,不在赘述。
在Call.State(internal)状态获取流程中,看起来似乎有些复杂,我们简单总结如下:1. 6种DriverCall.State分别对应GsmCall对象fgCall、bgCall以及ringingCall;
2. Call.State(internal)是由GsmConnection发起更新的;系统中有三个GsmCall对象,分别是fgCall、bgCall已经ringingCall,GsmConnection根据DriverCall.State的改变,将自己划分到不同的GsmCall对象中;
(PS:比如来电的时候建立一个GsmConnection,此时它属于ringingCall;在来电接通后它会将自己更为属于fgCall,如果此时你再拨打一通电话,那么该GsmConnection又会将自己更改为属于bgCall。)
通过以上分析我们可以知道DriverCall.State与Call.State的对应关系如下:
TelephonyManager. CALL_STATE状态获取
TelephonyManager状态用于给三方应用提供Phone状态,这一小节实际上可以分为两部分即:Phone.State和TelephonyManager.CallState,前者是内部使用,后者供外部使用;前者根据Call.State(Internal)获取对应状态,后者根据Phone.State获取对应状态。
在Android 4.4中并没有所谓的Phone.State,这是Android 4.0之前的称呼,实际指的是PhoneConstants.State。PhoneConstants.State就是Android 4.0以及之前版本中的Phone.State,其使用IDLE、RINGING、OFFHOOK来表示当前Phone的状态,这些状态将提供给TelephonyManager并暴露给三方应用。
在GsmCallTracker的handleCallProgressInfo()中,经过了DriverCall.State的获取与Call.State(internal)的获取之后,通过updatePhoneState()来更新PhoneConstants.State,关键代码如下:
- private void
- updatePhoneState() {
- PhoneConstants.State oldState = mState;
- if (mRingingCall.isRinging()) {
- mState = PhoneConstants.State.RINGING;
- } else if (mPendingMO != null ||
- !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())) {
- mState = PhoneConstants.State.OFFHOOK;
- } else {
- mState = PhoneConstants.State.IDLE;
- }
- if (mState == PhoneConstants.State.IDLE && oldState != mState) {
- //如果是IDLE状态则发起通知,语音通话结束,告知数据连接可用
- mVoiceCallEndedRegistrants.notifyRegistrants(
- new AsyncResult(null, null, null));
- } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
- //如果是非IDLE状态,语音通话开始,告知数据连接不可用
- mVoiceCallStartedRegistrants.notifyRegistrants (
- new AsyncResult(null, null, null));
- }
- log("updatePhoneState: old: " + oldState +" , new: " + mState);
- if (mState != oldState) {
- //通知三方应用
- mPhone.notifyPhoneStateChanged();
- }
- }
PhoneConstants. State. RINGING
根据前面的代码,我们需要查看GsmCall中的isRinging()方法的返回值,如下:
- public boolean isRinging() {
- return getState().isRinging();
- }
- //这里的mState是com.android.internal.telephony.State对象
- public State getState() {
- return mState;
- }
- public boolean isRinging() {
- return this == INCOMING || this == WAITING;
- }
PhoneConstants. State. OFFHOOK
这里就需要查看mPendingMO对象是否为null以及fgCall和bgCall的isIdle()方法的返回值,如下:- //如果mPendingMO不为null,则表示当前是MO流程。
- //后面的判断表示只要fgCall或者bgCall其中之一不是IDLE状态,则是Phone状态为OFFHOOK
- mPendingMO != null || !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())
- //isIdle与isAlive是互斥的
- public boolean isIdle() {
- return !getState().isAlive();
- }
- //如果Call.State是IDLE/DISCONNECTED/DISCONNECTING中的任意一种状态,则返回false
- //反之则为true
- public boolean isAlive() {
- return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING);
- }
PhoneConstants. State. IDLE
在updatePhoneState()方法的最后,调用了notifyPhoneStateChanged()将Phone状态向TelephonyManager传送,并最终通过mRegistry.notifyCallState()方法将Phone状态传递给所有注册了PhoneStateChangeListener。这里我们主要看到DefaultPhoneNotifier.notifyPhoneState()方法,在这里最终实现了Phone.State向TelePhonyManager.Call_STATE的过度,整个过程关键代码如下:
- //GsmCallTracker updatePhoneState()方法中调用
- if (mState != oldState) {
- mPhone.notifyPhoneStateChanged();
- }
- //这里的this是GSMPhone对象
- /*package*/ void notifyPhoneStateChanged() {
- updateCipherIndication();
- mNotifier.notifyPhoneState(this);
- }
- public void notifyPhoneState(Phone sender) {
- //这里是com.android.internal.telephony.Call, sender是GSMPhone对象
- Call ringingCall = sender.getRingingCall();
- String incomingNumber = "";
- if (ringingCall != null && ringingCall.getEarliestConnection() != null){
- incomingNumber = ringingCall.getEarliestConnection().getAddress();
- }
- try {
- //将Phone状态通知给所有注册了PhoneStateChange的Listener
- //根据conertCallState方法将PhoneConstants.State转换为TelephonyManager.CALL_STATE
- mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber);
- } catch (RemoteException ex) {
- // system process is dead
- }
- }
- //这里重点关注三个方法:
- //1. sender.getRingingCall()
- //2. sender.getState()
- //3. convertCallState(sender.getState())
- public GsmCall getRingingCall() {
- //mCT为GsmCalltracker对象,mRingingCall为GsmCall对象
- return mCT.mRingingCall;
- }
- public PhoneConstants.State getState() {
- //mCT为GsmCallTracker对象
- //mState为PhoneConstants.State对象初始值为PhoneConstants.State.IDLE
- //mState就是前面提到的Phone.State,也就是PhoneConstants.State
- return mCT.mState;
- }
- public static int convertCallState(PhoneConstants.State state) {
- switch (state) {
- case RINGING:
- return TelephonyManager.CALL_STATE_RINGING;
- case OFFHOOK:
- return TelephonyManager.CALL_STATE_OFFHOOK;
- default:
- return TelephonyManager.CALL_STATE_IDLE;
- }
- }
这里可以很清楚的看到它们之间的对应关系,普通APP便可以通过获取TelephonyManager对象的CALL_STATE来判断当前Phone的状态,这里我们还是用表格来直观的看看Phone.State与Call.State(internal)以及TelephonyManager.CALL_STATE之间的对应关系,如下:
Call. State (TeleService)状态获取
在《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》中我们已经分析了,通话状态从底层传递到上层的整个流程。在经过了Telephony Framework的处理之后,便传递到TeleService中,具体流程请参看本文开头的“通话状态更新时序图”。当更新流程来到CallModeler的onPhoneStateChanged()方法中时,我们注意到以下关键代码:
- private void onPhoneStateChanged(AsyncResult r) {
- Log.i(TAG, "onPhoneStateChanged: ");
- //这里为com.android.services.telephony.Call
- final List<Call> updatedCalls = Lists.newArrayList();
- //根据Call.State(internal)更新Call.State(TeleService)
- doUpdate(false, updatedCalls);
- //... ...省略
- // M: add skip update logic. When 1A + 1R, skip update calls to InCallUI while query is running.
- if (!ignoreUpdate()) {
- if (updatedCalls.size() > 0) {
- for (int i = 0; i < mListeners.size(); ++i) {
- //将状态改变向后继续传递,最终到达InCallUI
- mListeners.get(i).onUpdate(updatedCalls);
- }
- }
- }
- //... ...省略
- }
- private void doUpdate(boolean fullUpdate, List<Call> out) {
- //... ...省略
- //通过分析可以知道connection的getState()方法实际为,获取connection对应的
- //Call(Internal)的状态,也就是Call.State(Internal)
- //当Call.State(Internal)不属于IDLE/DISCONNECTED/INCOMING/WAITING时
- //shouldUpdate返回true,我们可以理解为Phone状态位OFFHOOK时才需要更新
- /*final*/ boolean shouldUpdate =
- (connection.getState() !=
- com.android.internal.telephony.Call.State.DISCONNECTED &&
- connection.getState() !=
- com.android.internal.telephony.Call.State.IDLE &&
- !connection.getState().isRinging())
- || fullUpdate;
- //... ...省略
- final boolean isDisconnecting = connection.getState() ==
- com.android.internal.telephony.Call.State.DISCONNECTING;
- //如果Phone状态位OFFHOOK,shouldCreate返回true
- final boolean shouldCreate = shouldUpdate && !isDisconnecting;
- //根据connection对象创建与之对应的TeleService Call对象
- final Call call = getCallFromMap(mCallMap, connection, shouldCreate /* create */);
- //... ...省略
- //跳转实现Call.State(Internal)和Call.State(TeleService)的映射
- boolean changed = updateCallFromConnection(call, connection, false);
- //... ...省略
- }
- private boolean updateCallFromConnection(Call call, Connection connection,
- boolean isForConference) {
- boolean changed = false;
- //根据GsmConnection对象,获取Call.State(Internal)并更新Call.State(TeleService)
- final int newState = translateStateFromTelephony(connection, isForConference);
- //... ...省略
- return changed;
- }
- private int translateStateFromTelephony(Connection connection, boolean isForConference) {
- //connection.getState实际上为connection所属的GsmCall的状态也就是Call.State(Internal)
- com.android.internal.telephony.Call.State connState = connection.getState();
- //... ...省略
- //Call.State(Internal)与Call.State(TeleService)对应关系
- int retval = State.IDLE;
- switch (connState) {
- case ACTIVE:
- retval = State.ACTIVE;
- break;
- case INCOMING:
- retval = State.INCOMING;
- break;
- case DIALING:
- case ALERTING:
- if (PhoneGlobals.getInstance().notifier.getIsCdmaRedialCall()) {
- retval = State.REDIALING;
- } else {
- retval = State.DIALING;
- }
- break;
- case WAITING:
- retval = State.CALL_WAITING;
- break;
- case HOLDING:
- retval = State.ONHOLD;
- break;
- case DISCONNECTING:
- retval = State.DISCONNECTING;
- break;
- case DISCONNECTED:
- retval = State.DISCONNECTED;
- default:
- }
- //获取ConferenceCall的Call.State(TeleService)
- if (!isForConference) {
- // 如果是conferenceCall则返回State.CONFERENCED
- if (isPartOfLiveConferenceCall(connection) && connection.isAlive()) {
- return State.CONFERENCED;
- }
- }
- return retval;
- }
- INVALID = 0;
- IDLE = 1; /* The call is idle. Nothing active */
- ACTIVE = 2; /* There is an active call */
- INCOMING = 3; /* A normal incoming phone call */
- CALL_WAITING = 4; /* Incoming call while another is active */
- DIALING = 5; /* An outgoing call during dial phase */
- REDIALING = 6; /* Subsequent dialing attempt after a failure */
- ONHOLD = 7; /* An active phone call placed on hold */
- DISCONNECTING = 8; /* A call is being ended. */
- DISCONNECTED = 9; /* State after a call disconnects */
- CONFERENCED = 10; /* Call part of a conference call */
InCallState状态获取
在Android 4.4中,因为原来的Phone已经被拆解为InCallUI和TeleService了,所以google又新增了一个InCallState用于标识InCallActivity的状态。InCallState的状态总共有4种,分别是NO_CALLS、INCOMING、INCALL、OUTGOING。通过查找我们可以在SourceCode/packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.java中找到InCallState的定义,如下:
- public enum InCallState {
- // InCall Screen is off and there are no calls
- // InCallUI界面退出并且没有通话
- NO_CALLS,
- // Incoming-call screen is up
- // 显示来电界面
- INCOMING,
- // In-call experience is showing
- // 处于通话中
- INCALL,
- // User is dialing out
- // 主动呼叫即MT
- OUTGOING;
- public boolean isIncoming() {
- return (this == INCOMING);
- }
- public boolean isConnectingOrConnected() {
- return (this == INCOMING ||
- this == OUTGOING ||
- this == INCALL);
- }
- }
无论当前通话是来电或者挂断或者是呼叫保持,这些都能够在CallList中找到与之对应的处理方法,如:onIncoming、onDisconnect、onUpdate。通过这些方法可以完成对状态信息的处理以及更新,它们的共通特点是都会调用updateCallInMap()方法。在该方法中完成对Call(TeleService)对象的创建以及和GsmConnection对象的关联,关键代码如下:
- private boolean updateCallInMap(Call call) {
- //... ...省略
- if (call.getState() == Call.State.DISCONNECTED) {
- //... ...省略
- mCallMap.put(id, call);
- } else if (!isCallDead(call)) {
- mCallMap.put(id, call);
- //... ...省略
- return updated;
- }
- @Override
- public void onCallListChange(CallList callList) {
- if (callList == null) {
- return;
- }
- //将Call.State(TeleService)转换成InCallState
- InCallState newState = getPotentialStateFromCallList(callList);
- newState = startOrFinishUi(newState);
- //... ...省略
- }
- public static InCallState getPotentialStateFromCallList(CallList callList) {
- //InCallState默认状态位NO_CALLS
- InCallState newState = InCallState.NO_CALLS;
- //如果calllist为null返回默认状态NO_CALLS
- if (callList == null) {
- return newState;
- }
- //INCOMING/OUTGOING/INCALL的对应
- if (callList.getIncomingCall() != null) {
- newState = InCallState.INCOMING;
- } else if (callList.getOutgoingCall() != null) {
- newState = InCallState.OUTGOING;
- } else if (callList.getActiveCall() != null ||
- callList.getBackgroundCall() != null ||
- callList.getDisconnectedCall() != null ||
- callList.getDisconnectingCall() != null) {
- newState = InCallState.INCALL;
- }
- return newState;
- }
InCallState. INCOMING
根据前面的代码,首先查看CallList中的getInComingCall()方法,可以看到:- public Call getIncomingCall() {
- Call call = getFirstCallWithState(Call.State.INCOMING);
- if (call == null) {
- call = getFirstCallWithState(Call.State.CALL_WAITING);
- }
- //... ...省略
- return call;
- }
- public Call getFirstCallWithState(int state) {
- return getCallWithState(state, 0);
- }
- //在HashMap<Integer, Call> mCallMap中查找valuses
- //是否有与对应state匹配的Call(TeleService)
- public Call getCallWithState(int state, int positionToFind) {
- Call retval = null;
- int position = 0;
- for (Call call : mCallMap.values()) {
- if (call.getState() == state) {
- if (position >= positionToFind) {
- retval = call;
- break;
- } else {
- position++;
- }
- }
- }
- return retval;
- }
InCallState. OUTGOING
- public Call getOutgoingCall() {
- Call call = getFirstCallWithState(Call.State.DIALING);
- if (call == null) {
- call = getFirstCallWithState(Call.State.REDIALING);
- }
- return call;
- }
InCallState. INCALL
- //ACTIVE
- public Call getActiveCall() {
- return getFirstCallWithState(Call.State.ACTIVE);
- }
- //ONHOLD
- public Call getBackgroundCall() {
- return getFirstCallWithState(Call.State.ONHOLD);
- }
- //DISCONNECTED
- public Call getDisconnectedCall() {
- return getFirstCallWithState(Call.State.DISCONNECTED);
- }
- //DISCONNECTING
- public Call getDisconnectingCall() {
- return getFirstCallWithState(Call.State.DISCONNECTING);
- }
InCallState. NO_CALLS
通过前面的分析,我们大致知道了InCallState的作用以及来源,还是用一张图来看看InCallState与Call.State(TeleService)的对应关系,如下:
这里大家可能会觉得奇怪,为什么Call.State.INVALID和Call.State.CONFERENCED没有与InCallState.NO_CALLS对应呢?INVALID是Call.State初始时赋的值,而实际状态不会为INVALID,而是IDLE。对于CONFERENCED来说,因为Conference Call会有自己单独的处理,这一点在CallModeler里面可以看到,因此也不属于NO_CALLS。
小结
通过以上分析,我们知道了Telephony中的各种状态,以及它们之间的对应关系,这里简单的总结一下本文所述的内容:
1. Telephony中关于Call、Phone的状态有如下几6种:
(1). DriverCall.State;
将Modem返回的通话状态转换成最基本的Call状态,DriverCall.State包含ACTIVE、HOLDING、DIALING、ALERTING、INCOMING、WAITING 6种。
(2). Call.State(internal);
在整个Telephony结构中,有且只有三种Call(internal)即:foregroundCall、backgroundCall、ringingCall,这三种类型描述了系统中所有存在的Call(internal)类型,而这三种Call的状态用Call.State(internal)来描述,包含ACTIVE、HOLDING、DIALING、ALERTING、INCOMING、WAITING、IDEL、DISCONNECTING、DISCONNECTED,总共9种类型。
在实际使用中,我们并不会直接使用Call.State(internal),取而代之的是GsmConnection对象的getState方法。一个GsmCall对象可以拥有多个GsmConnection,比如在使用会议电话时,一路通话中拥有多个连接。GsmConnection对象会根据DriverCall.State的状态,将自己分配到不同的Call( fgCall、bgCall、ringingCall )对象中。比如当有一路来电时,此时会建立GsmConnection对象,并归属于ringingCall对象;而当来电被接听后,该GsmConnection对象会将自己分配到foregroundCall对象中。
(3). PhoneConstants.State;
在Android 4.0以及之前叫做Phone.State,用于描述手机在通话过程中的状态,其状态更新来源于Call.State(internal)。根据Call.State(internal)的状态划分为三类:IDLE、RINGING、OFFHOOK。这些状态供系统以及系统级APP使用。
(4). TelephonyManager.CALL_STATE_XX;
该状态源自PhoneConstants.State,并与其一一对应,即包含类型TelephonyManager.CALL_STATE_IDLE、TelephonyManager.CALL_STATE_RINGING、TelephonyManager.CALL_STATE_OFFHOOK。这些将会通过“广播”以及“PhoneStateChanged回调”通知给三方应用,该状态的主要目的也是暴露给三方使用。
(5). Call.State(TeleService);
在Android 4.4中,Phone模块被划分为InCallUI和TeleService两部分,而这里的Call.State(TeleService)正是通话状态在TeleService中的表现,同时该状态也将为后面的InCallState提供参考基准。Call.State(TeleService)包含了基本的11种类型:ACTIVE、ONHOLD、DIALING、REDIALING、INCOMING、CALL_WAITING、DISCONNECTED、DISCONNECTING、IDLE、CONFERENCE、INVALID。
我们知道com.android.internal.telephony.Call也就是前面提及的Call(internal),GsmCall和CDMACall都是其子类,主要作用是对通话这种属性的一种抽象。而Call(TeleService)实际上是com.android.services.telephony.common.Call,在Telephony Framework中完成了GsmCall对象的处理和操作之后,会将相关的信息在TeleService中转换为Call(TeleService)对象,并存储在HashMap中。com.android.services.telephony.common.Call实现了Parcelable接口,其作用是描述一路通话及其状态,在这里能够获得许多关于该路通话的详细信息。
(6). InCallPresenter.InCallState;
InCallState是用于决定InCallActivity所处状态,其包含类型为4种:NO_CALLS、INCALL、OUTGOING、INCOMING。该类型是首次出现在Android Telephony中,InCallUI的显示则依赖于此状态。
特别注意:InCallState.INCALL等价于Call.State(TeleService)的ACTIVE、ONHOLD、DISCONNECTING、DISCONNECTED;而PhoneConstants.State.OFFHOOK对应于Call.State(TeleService)的ACTIVE、ONHOLD、DIALING、REDIALING。
2. Telephony中的各种状态并不是独立存在的,它们之间是一种由底向上的依赖关系,即底层Modem端通话状态发生了改变,那么顶层的InCallSate状态也会随之而变化,不同的状态具有不同的作用。
最后,用两张图来反应本文的分析结论,分别是Telephony架构中各种State的映射关系,如图1:
图 1
下图2为Call.State(internal)各个状态之间的切换流程以及与PhoneConstants.State之间的对应关系,如下:
- Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
- Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
- Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
- Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析
- Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析
- Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析
- 转(Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析)
- 转(Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析)
- Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析
- C++宽字符处理函数 与 普通函数 对照表
- 几张ppt总结一下mock测试(java)
- 数据源BasicDataSource
- 黑马程序员_反射
- px dip dp sp
- Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
- android adapter getItemViewType, getViewTypeCount 越界问题
- 基于 libmad 的简单 MP3 流媒体播放器的实现
- 个人学习总结一面向对象2
- JAVA读取与导出EXCEL(poi)
- WIN7(32)位+OPENCV2.3.1+VS2008配置
- DML、DDL、DCL区别
- VXLAN and NVGRE
- POI导入2007EXCEL中遇到的文件描述符错误的问题