上一篇是去电流程,接下来自然是来电流程,按消息的接收顺序,我们关心来电消息最开始是从哪来的,所以先RIL层开始,这里如果有涉及AT命令,均以android源码所使用的AT命令为准(即 3gpp 27.007文档中AT命令)。
首先在RIL会先出现类似下面的消息
<<====[Recv AT] RING, time=….//电话来了
<<====[Recv AT] +CLIP: "18812345678 time=….//类似来电显示功能,可查3gpp27.007
同时也向RIL.java上报UNSOL_RESPONSE_CALL_STATE_CHANGED消息,RIL.java收到将才标志转换为RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,这告诉我们真正处理代码在哪个分支里,看下面代码:
processUnsolicited (Parcel p) {//主动上报的命令 …省略代码…… case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: mCallStateRegistrants .notifyRegistrants(new AsyncResult(null, null, null)); break; }上面这个通知发给谁呢,这就要先回头先看下GsmCallTracker.java的构造函数了,相信看了下面两段代码,也就知道了我们后面要找的东西(EVENT_CALL_STATE_CHANGE)了,类似的用法在phone里面很常见。
GsmCallTracker (GSMPhone phone) { this.phone = phone; cm = phone.mCM; cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); ………. } public void registerForCallStateChanged(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); mCallStateRegistrants.add(r); }
当然EVENT_CALL_STATE_CHANGE这个消息的上会有很多原因,除了来电消息RING,还有挂断消息NOCARRIER、电话状态改变消息CLCC等,RIL都会作为EVENT_CALL_STATE_CHANGE报给GsmCallTracker.java,GsmCalTracker.java收到之后会,在handleMessage()对应分支中进行处理,代码如下:
case EVENT_CALL_STATE_CHANGE: pollCallsWhenSafe(); break;
进入pollCallsWhenSafe()方法中,又见消息,这回是主动查询CLCC,查询一下通话列表,即查询所有的通话详情,在这个分支 EVENT_POLL_CALLS_RESULT里获得查询结果,
lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); cm.getCurrentCalls(lastRelevantPoll), case EVENT_POLL_CALLS_RESULT: ar =(AsyncResult)msg.obj; if (msg ==lastRelevantPoll) { needsPoll = false; lastRelevantPoll =null; handlePollCalls((AsyncResult)msg.obj); } break;
进入handlePollCalls()方法中,在这个方法里将揭开CLCC命令返回参数和connections集合里的元素的是什么关系?handlePollCalls()方法中会进行一个for循环操作,底层查的通话列表用DriverCall类表示,FrameWork层则抽象为GsmConnection类,在这里先看一个关于CLCC命令的例子
CLCC : 1、0、2、0、0 1881234578 …..
先是CLCC这个command,后面
第一个参数表示 index序号,
每二个如是0表示来电、1表示去电,
第三个是电话状态,
第四个表示是数据业务还是语音业务,
第五个表示是否是视频会议,后面再跟着号码。简单说这么多,详细请参考3gpp 27.007,现在可以回笿前面的问题了,CLCC返回的电话列表中,第一个参数就是没路通话的编号,从1开始编号,同样可以看到GsmCallTracker中保存的GsmConnection的集合connections集合对象是一个数组,数组编号是从0开始的,所以我们会看到会有一个dc.index == i+1;的操作,对应关系就是这里建立的。之后会把底层查的DriverCall对象和GsmCallTracker中保存的GsmConnection对象进行比较。如DriverCall对象为空,我们本地保持的GsmConnection对象存在,很显然,是这路电话挂断了,反之如过DriverCall对象有,GsmConnection对象不存在,则是一个来电,本文关注来电,代码看这里
if (conn == null && dc != null){ if (newRinging != null) { phone.notifyNewRingingConnection(newRinging); }} 在phoneBase.java里发出通知 protected void notifyNewRingingConnectionP(Connection cn) { if (!mIsVoiceCapable) return; AsyncResult ar = new AsyncResult(null, cn, null); mNewRingingConnectionRegistrants.notifyRegistrants(ar); }
再后面的代码就离开Framework层了,这里把来电消息通知给上层应用,还记得前面EVENT_CALL_STATE_CHANGE这个消息的注册和接收过程吗?,这里又用到了同样的方法,在CallNotifer.java里
private void registerForNotifications() { mCM.registerForNewRingingConnection(this,PHONE_NEW_RINGING_CONNECTION, null); ….后面的代码省略 } public void registerForNewRingingConnection( Handler h, int what, Object obj) { checkCorrectThread(h); mNewRingingConnectionRegistrants.addUnique(h, what, obj); }
后面我们找PHONE_NEW_RINGING_CONNECTION这个消息的对应分支就好了,后面的工作就是设置铃声和更新来电界面等一些操作,剩下的代码流程在网上就比较容易找到了,给出一个链接http://www.cnblogs.com/chenxian/archive/2010/09/28/1837489.html,还是不要重复造轮子了,来电的流程的分析就写就么多吧,如有写错的地方要告诉我哦。