3.1 Call.State状态更新
调用流程图如下,
GsmConnection的update方法逻辑如下,
1,首先调用parentFromDCState方法对通话状态进行映射,获取GsmCall对象,
newParent = parentFromDCState(dc.state);
2,然后调用GsmCall的detach,update或者attach方法对通话状态进行进一步映射,
if (newParent != mParent) {
if (mParent != null) {
mParent.detach(this);
}
newParent.attach(this, dc);
•••
} else {
boolean parentStateChange;
parentStateChange = mParent.update (this, dc);
GsmConnection的构造方法也有和update方法相似的逻辑,如下,
mParent = parentFromDCState (dc.state);//调用parentFromDCState方法对通话状态进行映射
mParent.attach(this, dc); //调用GsmCall的attach方法对通话状态进行进一步映射,
parentFromDCState方法如下,
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);
}
}
mOwner是GsmCallTracker对象,并且在GsmCallTracker中,初始化了三个GsmCall对象,
GsmCall mRingingCall = new GsmCall(this);
// A call that is ringing or (call) waiting
GsmCall mForegroundCall = new GsmCall(this);
GsmCall mBackgroundCall = new GsmCall(this);
因此, DriverCall. State与GsmCall映射关系表如下,
DriverCall. State | GsmCall |
State.ACTIVE |
mForegroundCall |
State. DIALING | |
State. ALERTING | |
State. INCOMING | mRingingCall |
State. WAITING | |
State. HOLDING | mBackgroundCall |
GsmCall的detach,update或者attach方法都会更新通话状态的映射,
detach方法如下,
detach(GsmConnection conn) {
mConnections.remove(conn);
if (mConnections.size() == 0) {
mState = State.IDLE;
}
}
直接将当前的GsmConnection对象从mConnections的ArrayList中删除,
mConnections定义在GsmCall的父类Call中,保存着当前的所有Connection 通话连接,
public ArrayList<Connection> mConnections = new ArrayList<Connection>();
如果mConnections 为空,即没有任何通信连接,则将mState置为State.IDLE状态。
mState 变量也是在父类Call中定义的,是一个内部State枚举类型,
public State mState = State.IDLE;
State枚举类型定义如下,
public enum State {
IDLE, ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING, DISCONNECTED, DISCONNECTING;
public boolean isAlive() {
return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING);
}
public boolean isRinging() {
return this == INCOMING || this == WAITING;
}
public boolean isDialing() {
return this == DIALING || this == ALERTING;
}
}
State定义了9种状态,并且有三个方法。
update方法如下,
State newState;
boolean changed = false;
newState = stateFromDCState(dc.state);
if (newState != mState) {
mState = newState;
changed = true;
}
return changed;
首先调用stateFromDCState方法获取新的状态,然后将新状态和当前状态对比,更新当前的状态并且判断状态是否有变化。
attach方法如下,
mConnections.add(conn);
mState = stateFromDCState (dc.state);
首先将GsmConnection对象添加到mConnections中,也就是添加一路通话。然后调用stateFromDCState更新当前的通话状态。
stateFromDCState方法如下,
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);
}
因此, DriverCall.State与Call.State的对应关系如下,
DriverCall. State | Call.State |
State.ACTIVE | State.ACTIVE |
State. DIALING | State. DIALING |
State. ALERTING | State. ALERTING |
State. INCOMING | State. INCOMING |
State. WAITING | State. WAITING |
State. HOLDING | State. HOLDING |
| DISCONNECTED |
| DISCONNECTING |
| IDLE |
简单总结如下,
1. 6种DriverCall.State分别对应GsmCall对象mForegroundCall、mBackgroundCall以及mRingingCall;
2. Call.State是由GsmConnection发起更新的;系统中有三个GsmCall对象,分别是mForegroundCall、
mBackgroundCall和mRingingCall,GsmConnection根据DriverCall.State的状态,将自己划分到不同的GsmCall对象中;
比如来电的时候建立一个GsmConnection,此时它属于ringingCall;在来电接通后它会将自己更为属于mForegroundCall,
如果此时你再拨打一通电话,那么该GsmConnection又会将自己更改为属于mBackgroundCall。