android -- phone (三)来电流程

        上一篇是去电流程,接下来自然是来电流程,按消息的接收顺序,我们关心来电消息最开始是从哪来的,所以先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,还是不要重复造轮子了,来电的流程的分析就写就么多吧,如有写错的地方要告诉我哦。











你可能感兴趣的:(android -- phone (三)来电流程)