一 概述
UICC Universal Integrated Circuit Card 通用集成电路卡是定义了物理特性的智能卡的总称。主要用于存储用户信息、鉴权密钥、短消、付费方式等信息。
二 android 系统中的使用
1、结构图。
* UiccController
* #
* |
* UiccCard
* # #
* | ------------------
* UiccCardApplication CatService
* # #
* | |
* IccRecords IccFileHandler
* ^ ^ ^ ^ ^ ^ ^ ^
* SIMRecords---- | | | | | | ---SIMFileHandler
* RuimRecords----- | | | | ----RuimFileHandler
* IsimUiccRecords--- | | -----UsimFileHandler
* | ------CsimFileHandler
* ----IsimFileHandler
* Legend : # stands for Composition</span>
* ^ stands for Generalization
2 代码信息
(1) makeDefaultPhone 的时候构造UIccController 单例。
public static void makeDefaultPhone(Context context) {
***************************************
// Instantiate UiccController so that all other classes can just call getInstance()
UiccController.make(context, sCommandsInterface);
**************************************
}
(2)注册 EVENT_ICC_STATUS_CHANGED EVENT_ICC_STATUS_CHANGED
public static UiccController make(Context c, CommandsInterface ci) {
synchronized (mLock) {
if (mInstance != null) {
throw new RuntimeException("UiccController.make() should only be called once");
}
mInstance = new UiccController(c, ci);
return mInstance;
}
}
private UiccController(Context c, CommandsInterface ci) {
if (DBG) log("Creating UiccController");
mContext = c;
mCi = ci;
mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
// TODO remove this once modem correctly notifies the unsols
mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
}
(3) 在卡状态改变的时候,会调用 Uicc Controller 中的 handleMessage处理状态
@Override
public void handleMessage (Message msg) {
synchronized (mLock) {
switch (msg.what) {
case EVENT_ICC_STATUS_CHANGED:
if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
// 获取卡的状态
mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
break;
case EVENT_GET_ICC_STATUS_DONE:
if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
// 得到卡的状态后, 调用相关的程序处理
AsyncResult ar = (AsyncResult)msg.obj;
onGetIccCardStatusDone(ar);
break;
default:
Log.e(LOG_TAG, " Unknown Event " + msg.what);
}
}
}
private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
if (ar.exception != null) {
Log.e(LOG_TAG,"Error getting ICC status. "
+ "RIL_REQUEST_GET_ICC_STATUS should "
+ "never return an error", ar.exception);
return;
}
IccCardStatus status = (IccCardStatus)ar.result;
//创建或者更新 <span style="font-family: Arial, Helvetica, sans-serif;">UiccCard</span>
if (mUiccCard == null) {
log("********* :mUiccCard == null");
//Create new card
mUiccCard = new UiccCard(mContext, mCi, status);
} else {
log("********* :mUiccCard != null");
// modify by kwan for test
//mUiccCard.dispose();
//mUiccCard = new UiccCard(mContext, mCi, status);
//Update already existing card
mUiccCard.update(mContext, mCi , status);
}
if (DBG) log("Notifying IccChangedRegistrants");
mIccChangedRegistrants.notifyRegistrants();
}
(4)UiccCard 对应实际的sim card 。负责管理和维护卡的状态,主要功能如下
<1> 维护卡的状态和PIN码锁定状态
<2> 创建卡的UiccCardApplication
<3> 创建 CatService,这个对象和 Stk有关。
public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) { // ci RIL ics get card status result
if (DBG) log("Creating");
mCardState = ics.mCardState;
update(c, ci, ics);
}
public void dispose() {
synchronized (mLock) {
if (DBG) log("Disposing card");
if (mCatService != null) mCatService.dispose();
for (UiccCardApplication app : mUiccApplications) {
if (app != null) {
app.dispose();
}
}
mCatService = null;
mUiccApplications = null;
}
}
<span style="white-space:pre"> </span>//卡状态变化时候调用
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(); //检测
<span style="white-space:pre"> </span> //卡状态更新
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;
}
}
(5)UiccCardApplication sim 应用信息,主要包括卡信息及其维护。
UiccCardApplication(UiccCard uiccCard,
IccCardApplicationStatus as,
Context c,
CommandsInterface ci) {
if (DBG) log("Creating UiccApp: " + as);
mUiccCard = uiccCard;
mAppState = as.app_state;
mAppType = as.app_type;
mPersoSubState = as.perso_substate;
mAid = as.aid;
mAppLabel = as.app_label;
mPin1Replaced = (as.pin1_replaced != 0);
mPin1State = as.pin1;
mPin2State = as.pin2;
mContext = c;
mCi = ci;
mIccFh = createIccFileHandler(as.app_type); //用于记录sim card EF 文件信息
mIccRecords = createIccRecords(as.app_type, mContext, mCi); // 用于读取 <span style="font-family: Arial, Helvetica, sans-serif;">sim card EF 文件信息</span>
if (mAppState == AppState.APPSTATE_READY) {
Log.i(LOG_TAG, "Kwan : **************************** mAppState == AppState.APPSTATE_READY");
queryFdn();
queryPin1State();
}
}
void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {
synchronized (mLock) {
if (mDestroyed) {
loge("Application updated after destroyed! Fix me!");
return;
}
if (DBG) log(mAppType + " update. New " + as);
mContext = c;
mCi = ci;
AppType oldAppType = mAppType;
AppState oldAppState = mAppState;
PersoSubState oldPersoSubState = mPersoSubState;
mAppType = as.app_type;
mAppState = as.app_state;
mPersoSubState = as.perso_substate;
mAid = as.aid;
mAppLabel = as.app_label;
mPin1Replaced = (as.pin1_replaced != 0);
mPin1State = as.pin1;
mPin2State = as.pin2;
if (mAppType != oldAppType) {
if (mIccFh != null) { mIccFh.dispose();}
if (mIccRecords != null) { mIccRecords.dispose();}
mIccFh = createIccFileHandler(as.app_type);
mIccRecords = createIccRecords(as.app_type, c, ci);
}
if (mPersoSubState != oldPersoSubState &&
mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
notifyNetworkLockedRegistrantsIfNeeded(null);
}
if (mAppState != oldAppState) {
if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);
// If the app state turns to APPSTATE_READY, then query FDN status,
//as it might have failed in earlier attempt.
if (mAppState == AppState.APPSTATE_READY) {
queryFdn();
queryPin1State();
}
notifyPinLockedRegistrantsIfNeeded(null);
notifyReadyRegistrantsIfNeeded(null);
}
}
}
void dispose() {
synchronized (mLock) {
if (DBG) log(mAppType + " being Disposed");
mDestroyed = true;
if (mIccRecords != null) { mIccRecords.dispose();}
if (mIccFh != null) { mIccFh.dispose();}
mIccRecords = null;
mIccFh = null;
}
}
private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) {
if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) {
return new SIMRecords(this, c, ci);
} else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){
return new RuimRecords(this, c, ci);
} else if (type == AppType.APPTYPE_ISIM) {
return new IsimUiccRecords(this, c, ci);
} else {
// Unknown app type (maybe detection is still in progress)
return null;
}
}
private IccFileHandler createIccFileHandler(AppType type) {
switch (type) {
case APPTYPE_SIM:
return new SIMFileHandler(this, mAid, mCi);
case APPTYPE_RUIM:
return new RuimFileHandler(this, mAid, mCi);
case APPTYPE_USIM:
return new UsimFileHandler(this, mAid, mCi);
case APPTYPE_CSIM:
return new CsimFileHandler(this, mAid, mCi);
case APPTYPE_ISIM:
return new IsimFileHandler(this, mAid, mCi);
default:
return null;
}
}