UiccController 是对SIM卡管理的控制器,它通过 UiccCard 来更新SIM卡的信息。
1.UiccController 注册了两个监听器,来监听RIL的消息。分别监听 UNSOL_RESPONSE_RADIO_STATE_CHANGED 和 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,当radio 和 sim卡状态发生变化时,它会第一时间得到消息。
2. 开机后,RIL 会上报 Radio off,然后上报 radio on,一旦 radio on ,mOnRegistrants.notifyRegistrants(),这个语句就会被调用,具体实现如下,
protected void setRadioState(RadioState newState) {
.....
mRadioStateChangedRegistrants.notifyRegistrants();
if (mState.isAvailable() && !oldState.isAvailable()) {
Log.d(LOG_TAG,"Notifying: radio available");
mAvailRegistrants.notifyRegistrants();
onRadioAvailable();
}
if (!mState.isAvailable() && oldState.isAvailable()) {
Log.d(LOG_TAG,"Notifying: radio not available");
mNotAvailRegistrants.notifyRegistrants();
}
if (mState.isOn() && !oldState.isOn()) {
Log.d(LOG_TAG,"Notifying: Radio On");
mOnRegistrants.notifyRegistrants();
}
if ((!mState.isOn() || !mState.isAvailable())
&& !((!oldState.isOn() || !oldState.isAvailable()))
) {
Log.d(LOG_TAG,"Notifying: radio off or not available");
mOffOrNotAvailRegistrants.notifyRegistrants();
}
}
}
notify 后,会通知相关对象,相关对象就会进行处理,UiccController 就是其中一个对象,处理事件 EVENT_ICC_STATUS_CHANGED.
因为 UiccController的构造方法中存在如下代码。
private UiccController(Context c, CommandsInterface[] ci) {
if (DBG) log("Creating UiccController");
mContext = c;
mCi = ci;
for (int i = 0; i < mCi.length; i++) {
Integer index = new Integer(i);
//意思是说 RIL 中收到 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 消息,notify 所有监听器后,UiccController 就会处理 EVENT_ICC_STATUS_CHANGED 事件
mCi[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
mCi[i].registerForOff(this, EVENT_RADIO_OFF, index);
// TODO remove this once modem correctly notifies the unsols
// 意思是说 RIL 中收到 Radio ON 消息,notify 所有的监听器后,UiccController 就会处理 EVENT_ICC_STATUS_CHANGED 事件。
mCi[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index);
}
}
同样 当SIM卡状态发生变化后,上报RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED后,UiccController 也将处理事件 Event_ICC_STATUS_CHANGED,所以当手机信号不好或者SIM卡本身的状态发生变化的时候,消息都会集中到UiccConroller这里进行处理,然后传播到所有对SIM卡数据感兴趣的地方。UiccController 就是SIM卡管理的最为核心的类。
<1> 通知 UiccController,UiccControl 处理EVENT_ICC_STATUS_CHANGED的消息
case EVENT_ICC_STATUS_CHANGED:
if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
break;
<2> UiccControl 发出 RIL_REQUEST_GET_SIM_STATUS的请求,获取SIM卡的状态信息。
case EVENT_GET_ICC_STATUS_DONE:
if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
AsyncResult ar = (AsyncResult)msg.obj;
onGetIccCardStatusDone(ar);
break;
onGetIccCardStatusDone:
IccCardStatus status = (IccCardStatus)ar.result;
if (mUiccCard == null) {
//Create new card
mUiccCard = new UiccCard(mContext, mCi, status);
} else {
//Update already existing card
mUiccCard.update(mContext, mCi , status);
}
if (DBG) log("Notifying IccChangedRegistrants");
mIccChangedRegistrants.notifyRegistrants();
<3> RIL 返回SIM卡的状态信息,UiccControl 处理返回的SIM卡的信息,创建 UiccCard和 UiccCardApplication 对象。具体的实现过程如下
主要是在 UiccCard 的update 方法当中
public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
synchronized (mLock) {
if (mDestroyed) {
loge("Updated after destroyed! Fix me!");
return;
}
CardState oldState = mCardState;
mCardState = ics.mCardState;
mUniversalPinState = ics.mUniversalPinState;
mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
mContext = c;
mCi = ci;
//update applications
if (DBG) log(ics.mApplications.length + " applications");
for ( int i = 0; i < mUiccApplications.length; i++) {
if (mUiccApplications[i] == null) {
//Create newly added Applications
if (i < ics.mApplications.length) {
mUiccApplications[i] = new UiccCardApplication(this,
ics.mApplications[i], mContext, mCi);
}
} else if (i >= ics.mApplications.length) {
//Delete removed applications
mUiccApplications[i].dispose();
mUiccApplications[i] = null;
} else {
//Update the rest
mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
}
}
if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
// Initialize or Reinitialize CatService
mCatService = CatService.getInstance(mCi,
mContext,
this);
} else {
if (mCatService != null) {
mCatService.dispose();
}
mCatService = null;
}
sanitizeApplicationIndexes();
RadioState radioState = mCi.getRadioState();
if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
+ mLastRadioState);
// No notifications while radio is off or we just powering up
if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
if (oldState != CardState.CARDSTATE_ABSENT &&
mCardState == CardState.CARDSTATE_ABSENT) {
if (DBG) log("update: notify card removed");
mAbsentRegistrants.notifyRegistrants();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
} else if (oldState == CardState.CARDSTATE_ABSENT &&
mCardState != CardState.CARDSTATE_ABSENT) {
if (DBG) log("update: notify card added");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
}
}
mLastRadioState = radioState;
}
}
3.系统中其他对象对SIM卡的状态,SIM卡的数据信息很感兴趣,他们通过UiccController来监听SIM卡的状态变化。所以当UiccCard更新完成后,它就通知 ServiceStateTracker(Gsm or Cdma),IccCardProxy,DataConnectionTracker,PhoneBase,SIM卡的状态已经发生了变化。
DataConnectionTracker
GsmDataConnectionTracker
protected void onUpdateIcc() {
if (mUiccController == null ) {
return;
}
IccRecords newIccRecords = mUiccController.getIccRecords(UiccController.APP_FAM_3GPP);
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
if (r != null) {
log("Removing stale icc objects.");
r.unregisterForRecordsLoaded(this);
mIccRecords.set(null);
}
if (newIccRecords != null) {
log("New records found");
mIccRecords.set(newIccRecords);
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
}
}
}
更新所持有的mIccRecords 对象的数据
IccCardProxy
private void updateIccAvailability() {
synchronized (mLock) {
UiccCard newCard = mUiccController.getUiccCard();
CardState state = CardState.CARDSTATE_ABSENT;
UiccCardApplication newApp = null;
IccRecords newRecords = null;
if (newCard != null) {
state = newCard.getCardState();
newApp = newCard.getApplication(mCurrentAppType);
if (newApp != null) {
newRecords = newApp.getIccRecords();
}
}
if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) {
if (DBG) log("Icc changed. Reregestering.");
unregisterUiccCardEvents();
mUiccCard = newCard;
mUiccApplication = newApp;
mIccRecords = newRecords;
registerUiccCardEvents();
}
updateExternalState();
}
}
更新所持有的 mUiccCard,mUiccApplication,mIccRecords 对象。
当sim卡状态变化时,会发出广播
private void broadcastIccStateChangedIntent(String value, String reason) {
synchronized (mLock) {
if (mQuietMode) {
log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ " reason " + reason);
return;
}
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ " reason " + reason);
ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
UserHandle.USER_ALL);
}
}
如果应用程序或者系统服务对SIM卡的状态有兴趣,那么可以监听这个广播
PhoneBase
GsmPhone
protected void onUpdateIccAvailability() {
if (mUiccController == null ) {
return;
}
UiccCardApplication newUiccApplication =
mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
UiccCardApplication app = mUiccApplication.get();
if (app != newUiccApplication) {
if (app != null) {
if (LOCAL_DEBUG) log("Removing stale icc objects.");
if (mIccRecords.get() != null) {
unregisterForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(null);
}
mIccRecords.set(null);
mUiccApplication.set(null);
}
if (newUiccApplication != null) {
if (LOCAL_DEBUG) log("New Uicc application found");
mUiccApplication.set(newUiccApplication);
mIccRecords.set(newUiccApplication.getIccRecords());
registerForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(mIccRecords.get());
}
}
}
更新所持有的mUiccApplication,mIccRecords,mSimPhoneBookIntManager 对象。
ServiceStateTracker
GsmServiceStateTracker
protected void onUpdateIccAvailability() {
if (mUiccController == null ) {
return;
}
UiccCardApplication newUiccApplication =
mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
if (mUiccApplcation != newUiccApplication) {
if (mUiccApplcation != null) {
log("Removing stale icc objects.");
mUiccApplcation.unregisterForReady(this);
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(this);
}
mIccRecords = null;
mUiccApplcation = null;
}
if (newUiccApplication != null) {
log("New card found");
mUiccApplcation = newUiccApplication;
mIccRecords = mUiccApplcation.getIccRecords();
mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
if (mIccRecords != null) {
mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
}
}
}
}
更新 所持有的mIccRecords,mUiccApplication,等对象。
与UiccController 相关的数据流程如下图所示