下面为RIL工作框图:
呼叫转移中对RIL层返回的response,具体流程图如下
1. GsmCdmaPhone
一般向RIL请求request的类中含有对应的handleMessage方法会对RIL返回的response做出回应
case EVENT_GET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
handleCfuQueryResult((CallForwardInfo[])ar.result);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
AsyncResult.forMessage(onComplete, ar.result, ar.exception);
onComplete.sendToTarget();
}
break;
在GsmCdmaPhone.handleMessage中如果消息为EVENT_GET_CALL_FORWARD_DONE则表示返回得到返回的消息,得到了呼叫转移的状态,
如果onComplete不为空,则发送消息,发送到3.GsmUmtsCallForwardOption的handler中,进行消息处理;
同时调用
GsmCdmaPhone.handleCfuqueryresult(CallForwardInfo[] infos)通知已经得到了呼叫转移的结果
2. SIMrecords
Phone.setVoiceCallForwardingFlag(int line, boolean enable)
R为IccRecords的实例,但IccRecords中的setVoiceCallForwardingFlag函数具体实现是在子类SIMrecords中。
SIMrecords为Iccrecords的子类,实际调用SIMRecords中的setVoiceCallForwardingFlag方法
@Override
public void setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber) {
if (line != 1) return; // only line 1 is supported
mCallForwardingStatus = enable ? CALL_FORWARDING_STATUS_ENABLED :
CALL_FORWARDING_STATUS_DISABLED;
mRecordsEventsRegistrants.notifyResult(EVENT_CFI);
try {
if (validEfCfis(mEfCfis)) {
// lsb is of byte f1 is voice status
if (enable) {
mEfCfis[1] |= 1;
} else {
mEfCfis[1] &= 0xfe;
}
log("setVoiceCallForwardingFlag: enable=" + enable
+ " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis));
// Update dialNumber if not empty and CFU is enabled.
// Spec reference for EF_CFIS contents, TS 51.011 section 10.3.46.
if (enable && !TextUtils.isEmpty(dialNumber)) {
logv("EF_CFIS: updating cf number, " + Rlog.pii(LOG_TAG, dialNumber));
byte[] bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(dialNumber);
System.arraycopy(bcdNumber, 0, mEfCfis, CFIS_TON_NPI_OFFSET, bcdNumber.length);
mEfCfis[CFIS_BCD_NUMBER_LENGTH_OFFSET] = (byte) (bcdNumber.length);
mEfCfis[CFIS_ADN_CAPABILITY_ID_OFFSET] = (byte) 0xFF;
mEfCfis[CFIS_ADN_EXTENSION_ID_OFFSET] = (byte) 0xFF;
}
mFh.updateEFLinearFixed(
EF_CFIS, 1, mEfCfis, null,
obtainMessage (EVENT_UPDATE_DONE, EF_CFIS));
} else {
log("setVoiceCallForwardingFlag: ignoring enable=" + enable
+ " invalid mEfCfis=" + IccUtils.bytesToHexString(mEfCfis));
}
if (mEfCff != null) {
if (enable) {
mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET)
| CFF_UNCONDITIONAL_ACTIVE);
} else {
mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET)
| CFF_UNCONDITIONAL_DEACTIVE);
}
mFh.updateEFTransparent(
EF_CFF_CPHS, mEfCff,
obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
}
} catch (ArrayIndexOutOfBoundsException ex) {
logw("Error saving call forwarding flag to SIM. "
+ "Probably malformed SIM record", ex);
}
}
3. RegistrantList消息机制
下面为消息的发送需要参考RegistrantList的消息处理机制
消息不断传递,最后在Registrant.java中的internalNotifyRegistrant方法中发送消息
代码中使用了RegistrantList,如何快速分析下一步流程走到哪里?
这是一个回调的过程,所以核心就是在哪里注册就在哪里处理,我们要找到调用register方法的地方。 我们看到在SIMRecords类中的
mRecordsEventRegistrants.notifyResult(EVENT_CFI);
先搜索mRecordsEventRegistrants,找到registerForRecordsEvent的方法;
再找到调用registerForRecordsEvent方法的地方,注册了事件EVENT_ICC_RECORD_EVENTS
最后搜索”EVENT_ICC_RECORD_EVENTS”,找到handleMessage()方法对消息的处理,所以下一步代码流程就应该是走这里了。
4. GamCdmaPhone.hangdleMessage
在GamCdmaPhone的hangdleMessage中有对以下消息的处理语句,可以看到会调用processIccRecordEvents方法
case EVENT_ICC_RECORD_EVENTS:
ar = (AsyncResult)msg.obj;
processIccRecordEvents((Integer)ar.result);
break;
在GsmCdmaPhone.java中processIccRecordEvents
private void processIccRecordEvents(int eventCode) {
switch (eventCode) {
case IccRecords.EVENT_CFI:
notifyCallForwardingIndicator();
break;
}
}
5. DefaultPhoneNotifier
notifyCallForwardingChanged方法为PhoneNotify接口的函数,具体实现在DefaultPhoneNotifier.java类中
@Override
public void notifyCallForwardingChanged(Phone sender) {
int subId = sender.getSubId();
try {
if (mRegistry != null) {
mRegistry.notifyCallForwardingChangedForSubscriber(subId,
sender.getCallForwardingIndicator());
}
} catch (RemoteException ex) {
// system process is dead
}
}
6. TelephonyRegistry
调用TelephonyRegistry.java的notifyCallForwardingChangedForSubscriber
public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) {
if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
return;
}
if (VDBG) {
log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
mCallForwarding[phoneId] = cfi;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) &&
idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCallForwardingIndicatorChanged(cfi);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
}
}
handleRemoveListLocked();
}
}
Callback为IPhoneStateListener,onCallForwardingIndicatorChanged函数实现要在phoneStateListener中
621 public void onCallForwardingIndicatorChanged(boolean cfi) {
622 send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
623 }
看send
private void send(int what, int arg1, int arg2, Object obj) {
603 PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
604 if (listener != null) {
605 Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
606 }
607 }
Handle传递消息LISTEN_CALL_FORWARDING_INDICATOR,处理消息在
PhoneStateListener中。
317 case LISTEN_CALL_FORWARDING_INDICATOR:
318 PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
319 break;
调用函数具体的实现代码,具体的实现过程要去看他的子类CallNotifierPhoneStateListener
7. CallNotifier
598 for (int i = 0; i < subInfos.size(); i++) {
599 int subId = subInfos.get(i).getSubscriptionId();
600 if (!mPhoneStateListeners.containsKey(subId)) {
601 CallNotifierPhoneStateListener listener = new CallNotifierPhoneStateListener(subId);
602 mTelephonyManager.listen(listener,
603 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
604 | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
605 mPhoneStateListeners.put(subId, listener);
606 }
607 }
608 }
CallNotifierPhoneStateListener继承自PhoneStateListener,重写oncallForwardingIndicatorChanged方法;会调用updataPhoneStateListeners函数updataPhoneStateListeners函数中注册到Phone进程中
8.NotificationMgr
并且会调用函数updataCfi,此方法是用来发送通知 ,设置呼叫转移成功
763 @Override
764 public void onCallForwardingIndicatorChanged(boolean visible) {
765 Log.i(LOG_TAG, "onCallForwardingIndicatorChanged(): subId=" + this.mSubId
766 + ", visible=" + (visible ? "Y" : "N"));
767 mApplication.notificationMgr.updateCfi(this.mSubId, visible);
768 }
769 };