android 通话的log分析,Android Telephony 接电话流程分析

写在前面的话

本文主要分析Android 接电话的流程,研究的代码是Android 4.4的,现在我们只关注framework层,以CDMA为例,GSM同理。

0818b9ca8b590ca3270a3433284dd417.png

如果图片看不清的话,可以右键选择在新标签中打开图片

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]

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值