1. 程式人生 > 其它 >關於RILJ多次發出GET_CURRENT_CALLS請求的問題分析

關於RILJ多次發出GET_CURRENT_CALLS請求的問題分析

技術標籤:Telephonyjavaandroid

本文來自本文來自http://blog.csdn.net/linyongan

在剛接觸Qcril的時候,特別是在研究接電話和打電話的流程的時候,可能會有小夥伴跟我一樣,被RILJ發出的GET_CURRENT_CALLS請求搞暈了。有時候會RILJ會多次發出GET_CURRENT_CALLS請求,兩次或者三次,不確定。
舉個例子,每次出現GET_CURRENT_CALLS error之後,RILJ會再發出一次GET_CURRENT_CALLS請求,所以,我們先假設“GET_CURRENT_CALLS error會導致RILJ重新發出GET_CURRENT_CALLS請求”,下面我們就根據程式碼去驗證一下唄。



下面是打電話的一段log

09-09 17:32:03.599 D/RILJ    ( 2795): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
09-09 17:32:03.607 D/RILJ    ( 2795): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
09-09 17:32:03.686 D/RILJ    ( 2795): [5658]> GET_CURRENT_CALLS
09-09 17:32:03.688 D/RILJ    ( 2795): [5659]> GET_CURRENT_CALLS
09-09 17:32:03.691 D/RilRequest( 2795): [5659]< GET_CURRENT_CALLS error: 
com.android.internal.telephony.CommandException: GENERIC_FAILURE ret=
09-09 17:32:03.693 I/RILQ    (  268): (0/268):RIL[0][event] 
qcril_qmi_get_call_list_to_send: RILVI: calls rep:[qmi call id 1, 
android call id 1, qmi call state 3] reported/skipped 1/0 calls
09-09 17:32:03.696 V/RILJ    ( 2795): Incoming UUS : NOT present!
09-09 17:32:03.696 D/RILJ    ( 2795): InCall VoicePrivacy is disabled
09-09 17:32:03.696 D/RILJ    ( 2795): [5658]< GET_CURRENT_CALLS  
[id=1,ACTIVE,toa=129,norm,mo,0,voc,noevp,,cli=1,,0] 
09-09 17:32:03.745 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received
09-09 17:32:03.745 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received
09-09 17:32:03.751 D/CallStateMonitor( 2795): handleMessage(10)
09-09 17:32:03.751 D/CallNotifier( 2795): PHONE_ENHANCED_VP_OFF...
09-09 17:32:03.752 I/Timeline( 2795): Timeline: Activity_idle id: 
[email protected]
time:5637716 09-09 17:32:03.995 D/RILJ ( 2795): [5660]> GET_CURRENT_CALLS 09-09 17:32:03.999 I/RILQ ( 268): (0/268):RIL[0][event] qcril_qmi_get_call_list_to_send: RILVI: calls rep: [qmi call id 1, android call id 1, qmi call state 3] reported/skipped 1/0 calls 09-09 17:32:04.001 V/RILJ ( 2795): Incoming UUS : NOT present! 09-09 17:32:04.002 D/RILJ ( 2795): InCall VoicePrivacy is disabled 09-09 17:32:04.002 D/RILJ ( 2795): [5660]< GET_CURRENT_CALLS [id=1,ACTIVE,toa=129,norm,mo,0,voc,noevp,,cli=1,,0] 09-09 17:32:04.002 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received

從上面log可以看到,連續發出兩次GET_CURRENT_CALLS請求之後,後面緊跟著會發出第三次,而且第二次查詢失敗了:

09-09 17:32:03.691 D/RilRequest( 2795): [5659]< GET_CURRENT_CALLS error: 
com.android.internal.telephony.CommandException: 
GENERIC_FAILURE ret=

首先,RILRequest是RILJ的內部類,在RILJ的processSolicited方法裡也有:

   if (error != 0) {
       switch (rr.mRequest) {
         case RIL_REQUEST_ENTER_SIM_PIN:
         case RIL_REQUEST_ENTER_SIM_PIN2:
         case RIL_REQUEST_CHANGE_SIM_PIN:
         case RIL_REQUEST_CHANGE_SIM_PIN2:
         case RIL_REQUEST_SET_FACILITY_LOCK:
           if (mIccStatusChangedRegistrants != null) {
              if (RILJ_LOGD) {
              riljLog("ON some errors fakeSimStatusChanged: reg count="
                      + mIccStatusChangedRegistrants.size());
              }
              mIccStatusChangedRegistrants.notifyRegistrants();
            }
         break;
     }
    rr.onError(error, ret);
} 

當RILJ發出去的請求出錯之後會進入這個if語句,最後進入RILRequest的onError方法。

 void onError(int error, Object ret) {
        CommandException ex;
        ex = CommandException.fromRilErrno(error);
        if (RIL.RILJ_LOGD) Rlog.d(LOG_TAG, serialString() + "< "
            + RIL.requestToString(mRequest)
            + " error: " + ex + " ret=" + RIL.retToString(mRequest, ret));

        if (mResult != null) {
            AsyncResult.forMessage(mResult, ret, ex);
            mResult.sendToTarget();
        }

        if (mParcel != null) {
            mParcel.recycle();
            mParcel = null;
        }
}

看到了吧,是在onError方法裡打印出出錯的log,mResult != null,所以下一步會回到CdmaCallTracker的handleMessage方法裡,這個例子是打電話,所以這裡處理的是EVENT_POLL_CALLS_RESULT的邏輯,下面這兩行log也證明了會進入這裡。

public void handleMessage (Message msg) {
     ...
   case EVENT_POLL_CALLS_RESULT:{
        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;
     ...
}


09-09 17:32:03.745 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received
09-09 17:32:03.745 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received

最後會進入handlePollCalls方法裡。

protected void handlePollCalls(AsyncResult ar) {
        List polledCalls;
        if (ar.exception == null) {
            polledCalls = (List)ar.result;
        } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
            // just a dummy empty ArrayList to cause the loop
            // to hang up all the calls
            polledCalls = new ArrayList();
        } else {
            // Radio probably wasn't ready--try again in a bit
            // But don't keep polling if the channel is closed
            pollCallsAfterDelay();
            return;
        }
}

GET_CURRENT_CALLS error對應的是CommandException,所以跳過if和else if,進入else裡,也就是進入pollCallsAfterDelay方法裡,pollCallsAfterDelay方法在CdmaCallTracker的父類CallTracker中實現

 protected void pollCallsAfterDelay() {
        Message msg = obtainMessage();
        msg.what = EVENT_REPOLL_AFTER_DELAY;
        sendMessageDelayed(msg, POLL_DELAY_MSEC);
}

POLL_DELAY_MSEC的值是250,也就是說RILJ在250秒之後會重新發出GET_CURRENT_CALLS請求,所以我們最開始的假設是正確的!!!也就是說,在GET_CURRENT_CALLS失敗之後,RILJ會重新發出GET_CURRENT_CALLS請求!

09-09 17:32:03.745 D/CdmaCallTracker( 2795): Event EVENT_POLL_CALLS_RESULT Received
...
09-09 17:32:03.995 D/RILJ    ( 2795): [5660]> GET_CURRENT_CALLS

從log中也可以看到“17:32:03.745”與“17:32:03.995”相差了250毫秒,我們上面的程式碼分析也是正確的!
這個問題也就講到這裡啦~