写在前面的话
本文主要分析Android 接电话的流程,研究的代码是Android 4.4的,现在我们只关注framework层,以CDMA为例,GSM同理。
如果图片看不清的话,可以右键选择在新标签中打开图片
1. RILJ的processUnsolicited方法
接电话的流程是由底层传送到应用层的。首先RIL接收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息,我们进入RIL.java里查找RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED的消息的处理逻辑,在RIL.java文件里有两个方法processUnsolicited和responseToString进行该消息的处理。我们重点关注processUnsolicited方法,该方法会对底层传过来的数据进行收集和整理,然后再完成对应response的逻辑处理和消息通知
private void processUnsolicited (Parcel p) {
...
try {switch(response) {
...
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
ret = responseVoid(p); break;
...
}
switch(response) {
...
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD)
unsljLog(response);//打印log日志
//发出通知(RegistrantList消息处理机制)
mCallStateRegistrants.notifyRegistrants(new
AsyncResult(null, null, null));
...
}
}
对应的log:
//RIL.java接收到Call状态变化的通知
08-04 13:22:18.174 D/RILJ ( 3034): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
2. 找出mCallStateRegistrants的调用者
(在Source Insight这个编译器中,选中mCallStateRegistrants,然后按快捷键Ctrl+/),我们找到BaseCommands.java的registerForCallStateChanged方法,接着继续找它的调用者,最后我们来到CdmaCallTracker.java的构造方法里
public CdmaCallTracker(CDMAPhone phone) {
...
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
...
}
发觉是CdmaCallTracker.java向RIL注册了一个EVENT_CALL_STATE_CHANGE类型的Handler消息
因此,我们在CdmaCallTracker.java的handleMessage方法里可以找到响应EVENT_CALL_STATE_CHANGE消息类型的处理逻辑,如下:
public void
handleMessage (Message msg) {
...
case EVENT_CALL_STATE_CHANGE:
//调用父类CallTracker查询Call List方法
pollCallsWhenSafe();
break;
...
}
pollCallsWhenSafe()方法是在它的父类CallTracker.java中实现的,所以,RIL.java接收到Modem发出的Call状态变化后,是由CallTracker发起Call List查询,下面我们来到CallTracker.java的pollCallsWhenSafe方法里。
protected void pollCallsWhenSafe() {
...
if (checkNoOperationsPending()) {
//注意mLastRelevantPoll对象的消息类型,后面会用到
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
mCi.getCurrentCalls(mLastRelevantPoll);
}
}
3. RIL.java的getCurrentCalls方法
mCi是RIL.java的实例对象,这也就回到了RIL.java的getCurrentCalls方法里,它将RIL_REQUEST_GET_CURRENT_CALLS 消息封装成RILRequest 类型并发送。
public void getCurrentCalls (Message result) {
//注意rr对象的消息类型,后面会用到
RILRequest rr = RILRequest.obtain(
RIL_REQUEST_GET_CURRENT_CALLS, result);
//打印log日志
if (RILJ_LOGD)
riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
打印出相应的log是
//RIL.java向底层发起查询当前Call列表
08-04 13:22:18.183 D/RILJ ( 3034): [5542]> GET_CURRENT_CALLS
4. RIL.java的processSolicited方法
RIL向底层发送了查询Call List的请求,底层处理完成之后,就会把处理的结果返回给RIL,RIL.java 有三处接收处理RIL_REQUEST_GET_CURRENT_CALLS消息,真正的逻辑处理在processSolicited方法里
private RILRequest processSolicited (Parcel p) {
...
case RIL_REQUEST_GET_CURRENT_CALLS:
ret = responseCallList(p); break;
...
//打印log日志
if (RILJ_LOGD) riljLog(rr.serialString() + "< " +
requestToString(rr.mRequest)
+ " " + retToString(rr.mRequest, ret));
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, null, tr);
rr.mResult.sendToTarget();//发出handler消息通知
}
responseCallList方法会对数据进行收集整理,返回Object类型的ret对象,这里会打出下面两条log
08-04 13:22:18.214 V/RILJ ( 3034): Incoming UUS : NOT present!
08-04 13:22:18.215 D/RILJ ( 3034): InCall VoicePrivacy is disabled
走到下一步又会打印出一条log
08-04 13:22:18.216 D/RILJ ( 3034): [5541]< GET_CURRENT_CALLS
[id=1,INCOMING,toa=129,norm,mt,0,voc,noevp,,cli=1,,0]
5. CdmaCallTracker中的handleMessage方法
rr.mResult.sendToTarget()发出handler消息通知后,会在CdmaCallTracker中的handleMessage方法中响应。并且它的消息类型是”EVENT_POLL_CALLS_RESULT”(在本文的第2个小标题的末尾提到)。这里根据Message获取传递的Object数据对象,再调用handlePollCalls处理数据
public void
handleMessage (Message msg) {
...
switch (msg.what) {
case EVENT_POLL_CALLS_RESULT:{
//打印log日志
Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
ar = (AsyncResult)msg.obj;
if(msg == mLastRelevantPoll) {
if(DBG_POLL) log(
"handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
mNeedsPoll = false;
mLastRelevantPoll = null;
handlePollCalls((AsyncResult)msg.obj);
}
}
break;
...
}
打印出来的log是
08-04 13:22:18.232 D/CdmaCallTracker( 3034): Event EVENT_POLL_CALLS_RESULT Received
接着进入handlePollCalls方法里,handlePollCalls方法根据RIL发出的Call List对象,判断Call的状态并发出通知,这里发出的是新来电通知Phone.notifyNewRingingConnection
protected void
handlePollCalls(AsyncResult ar){
...
if (newRinging != null) {
mPhone.notifyNewRingingConnection(newRinging);
...
}
6.1 CDMAPhone.java的notifyNewRingingConnection方法
void notifyNewRingingConnection(Connection c) {
/* we'd love it if this was package-scoped*/
super.notifyNewRingingConnectionP(c);
}
6.2 PhoneBase.java的notifyNewRingingConnectionP方法
/** * Notify registrants of a new ringing Connection. * Subclasses of Phone probably want to replace this with a * version scoped to their packages */
protected void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
6.3 CallManager.java的registerForPhoneStates方法
好了,下面我们要找出mNewRingingConnectionRegistrants的调用者是谁。先来到CallManager的registerForNewRingingConnection方法里,继续找registerForNewRingingConnection的调用者,来到CallManager的registerForPhoneStates方法里,看到“phone.XXXX”
private void registerForPhoneStates(Phone phone) {
// for common events supported by all phones
...
phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null);
...
}
6.4 CallManager.java的handleMessage方法
在CallManager里搜索EVENT_NEW_RINGING_CONNECTION,来到handleMessage方法里
case EVENT_NEW_RINGING_CONNECTION:
if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
if (getActiveFgCallState().isDialing()
|| (hasMoreThanOneRingingCall() && !isRingingDuplicateCall())) {
Connection c = (Connection) ((AsyncResult) msg.obj).result;
try {
Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
c.getCall().hangup();
} catch (CallStateException e) {
Rlog.w(LOG_TAG, "new ringing connection", e);
}
} else {
mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
}
break;
...
6.5 CallStateMonitor.java的registerForNotifications方法
继续找mNewRingingConnectionRegistrants的调用者,注意我们现在在CallManager.java里,我们要找的是“CallManager.XXXX”
在CallStateMonitor的registerForNotifications方法里
protected void registerForNotifications() {
callManager.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
...
}
接着就会在CallStateMonitor的handleMessage方法里处理。CallStateMonitor已经是应用层的文件了,所以本文就讲到这里
最后贴出上面所有流程的log片段
08-04 13:22:18.174 D/RILJ ( 3034): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
08-04 13:22:18.181 D/RILJ ( 3034): [5543]> GET_CURRENT_CALLS
08-04 13:22:18.214 V/RILJ ( 3034): Incoming UUS : NOT present!
08-04 13:22:18.215 D/RILJ ( 3034): InCall VoicePrivacy is disabled
08-04 13:22:18.492 D/RILJ ( 3034): [5543]< GET_CURRENT_CALLS
[id=1,INCOMING,toa=129,norm,mt,0,voc,noevp,,cli=1,,0]
08-04 13:22:26.982 D/RILJ ( 3034): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
08-04 13:22:26.984 D/RILJ ( 3034): [5547]> GET_CURRENT_CALLS
08-04 13:22:26.986 V/RILJ ( 3034): Incoming UUS : NOT present!
08-04 13:22:26.986 D/RILJ ( 3034): InCall VoicePrivacy is disabled
08-04 13:22:26.986 D/RILJ ( 3034): [5546]< GET_CURRENT_CALLS
[id=1,ACTIVE,toa=129,norm,mt,0,voc,noevp,,cli=1,,0]