關於RILJ多次發出GET_CURRENT_CALLS請求的問題分析
本文來自本文來自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毫秒,我們上面的程式碼分析也是正確的!
這個問題也就講到這裡啦~