1.IccFileHandler
IccFileHandler主要用于从SIM卡中读取相应文件的数据。
以下是IccFileHandler的一些主要方法,我们可以看出,这些方法基本上都是用于对SIM卡中EF文件进行读写的。 public void loadEFLinearFixed(int fileid,String path,int recordNum,Message onLoaded){public void loadEFImgLinearFixed(int recordNum,Message onLoaded){
public void getEFLinearRecordSize(int fileid,String path,Message onLoaded){
public void loadEFLinearFixedAll(int fileid,String path,Message onLoaded){
public void loadEFTransparent(int fileid,Message onLoaded){
public void loadEFImgTransparent(int fileid,int highOffset,int lowOffset,
public void updateEFLinearFixed(int fileid,String path,int recordNum,byte[] data,
public void updateEFTransparent(int fileid,byte[] data,Message onComplete){
IccFileHandler在初始化时会根据SIM卡中Application的类型创建不同的对象。
包括SIMFileHandler、RuimFileHandler、UsimFileHandler、CsimFileHandler以及IsimFileHandler。
这些子类都只是对getEFPath()方法进行了重写,以SIMFileHandler和UsimFileHandler为例,
SIMFileHandler.java
protected String getEFPath(int efid){switch(efid){
case EF_SMS:
return MF_SIM + DF_TELECOM;
case EF_EXT6:……
case EF_CSP_CPHS:
return MF_SIM + DF_GSM;
}String path = getCommonIccEFPath(efid);
if(path == null){
Rlog.e(LOG_TAG,“Error: EF Path being returned in null”);
}
return path;
}
UsimFileHandler.java protected String getEFPath(int efid){switch(efid){
case EF_SMS:
……
case EF_HPPLMN:
return MF_SIM + DF_ADF;
case EF_DIR:
return MF_SIM;
}
String path = getCommonIccEFPath(efid);
if(path == null){
return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
}
return path;
}
可以看出,之所以重写getEFPath()方法,就是因为不同Application的文件结构有所差异,从而导致我们在读写EF文件时传入的地址也不同,因此,针对不同的Application,就需要
重新计算EF文件的地址,这样才能保证读写EF文件时不会出错。
当我们读取EF文件的内容时,并不会一上来就去读,而是会先读取其长度,然后再去读取相应长度的值。
先读取记录的长度。
public void loadEFLinearFixed(int fileid,String path,int recordNum,Message onLoaded){
String efPath =(path == null)?getEFPath(fileid):path;
Message response= obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
new LoadLinearFixedContext(fileid,recordNum,efPath,onLoaded));
mCi.iccIOForApp(COMMAND_GET_RESPONSE,fileid,efPath,0,0,GET_RESPONSE_EF_SIZE_BYTES,null,null,mAid,response);
}
根据记录的长度再去读取具体的内容。public void handleMessage(Message msg){
……
case EVENT_GET_RECORD_SIZE_DONE:
……
lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
size =((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff)<< 8)+(data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
lc.mCountRecords = size / lc.mRecordSize; if(lc.mLoadAll){lc.results = new ArrayList<byte[]>(lc.mCountRecords);
}
if(path == null){path = getEFPath(lc.mEfid);
}
……mCi.iccIOForApp(COMMAND_READ_RECORD,lc.mEfid,path,
lc.mRecordNum,
READ_RECORD_MODE_ABSOLUTE,
lc.mRecordSize,null,null,mAid,
obtainMessage(EVENT_READ_RECORD_DONE,lc));
……
}
2.IccRecords
先来看看那IccRecords中定义的一些属性及方法。 protected String mIccId;// Includes only decimals(no hex)protected String mFullIccId;// Includes hex characters in ICCID
protected String mMsisdn = null;// My mobile number
protected String mMsisdnTag = null;
protected String mNewMsisdn = null;
protected String mNewMsisdnTag = null;
protected String mVoiceMailNum = null;
protected String mVoiceMailTag = null;
protected String mNewVoiceMailNum = null;
protected String mNewVoiceMailTag = null;
protected boolean mIsVoiceMailFixed = false;
protected String mImsi;
public String getIMSI(){
public void setImsi(String imsi){
public String getMsisdnNumber(){
public String getMsisdnAlphaTag(){
public String getVoiceMailNumber(){
public String getVoiceMailAlphaTag(){
public void registerForRecordsLoaded(Handler h,int what,Object obj){
public void registerForImsiReady(Handler h,int what,Object obj){
public void registerForRecordsEvents(Handler h,int what,Object obj){
public void registerForNewSms(Handler h,int what,Object obj){
public void registerForNetworkSelectionModeAutomatic(
从这些属性及方法可以看出,IccRecords主要就是维护了SIM卡的相关信息,并提供相应接口供其它对象操作,然后还注册了一些监听器,包或卡Loaded、IMSI ready、NewSms等。
与IccFileHandler类似,IccRecords在初始化时也会根据SIM卡中Application的类型创建不同的对象。包括SIMRecords、RuimRecords以及IsimUiccRecords。
接下来我们还是以SIMRecords为例来进行分析。先来看看其构造方法,会创建一个AdnRecordCache对象,用于缓存SIM卡联系人,
还会注册一些监听器。
public SIMRecords(UiccCardApplication app,Context c,CommandsInterface ci){super(app,c,ci);
mAdnCache = new AdnRecordCache(mFh); mVmConfig = new VoiceMailConstants();mSpnOverride = new SpnOverride();
mRecordsRequested = false;// No load request is made till SIM ready // recordsToLoad is set to 0 because no requests are made yetmRecordsToLoad = 0;
mCi.setOnSmsOnSim(this,EVENT_SMS_ON_SIM,null);mCi.registerForIccRefresh(this,EVENT_SIM_REFRESH,null);
// Start off by setting empty stateresetRecords();
mParentApp.registerForReady(this,EVENT_APP_READY,null);
mParentApp.registerForLocked(this,EVENT_APP_LOCKED,null);
if(DBG)log(“SIMRecords X ctor this=”+ this);
IntentFilter intentfilter = new IntentFilter();intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
c.registerReceiver(mReceiver,intentfilter);
}
当监听到SIM卡为READY状态后,就会去读取SIM卡的相关记录,而读取记录基本上都是通过IccFileHandler来进行的。
读取完成后,结果都是保存在IccRecords或其子类的相关属性中的。
protected void fetchSimRecords(){mRecordsRequested = true;
mCi.getIMSIForApp(mParentApp.getAid(),obtainMessage(EVENT_GET_IMSI_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_ICCID,obtainMessage(EVENT_GET_ICCID_DONE));mRecordsToLoad++;
new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN,getExtFromEf(EF_MSISDN),1,obtainMessage(EVENT_GET_MSISDN_DONE));
mRecordsToLoad++;
mFh.loadEFLinearFixed(EF_MBI,1,obtainMessage(EVENT_GET_MBI_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_AD,obtainMessage(EVENT_GET_AD_DONE));mRecordsToLoad++;
mFh.loadEFLinearFixed(EF_MWIS,1,obtainMessage(EVENT_GET_MWIS_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_VOICE_MAIL_INDICATOR_CPHS,
obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
mRecordsToLoad++;
loadCallForwardingRecords(); getSpnFsm(true,null); mFh.loadEFTransparent(EF_SPDI,obtainMessage(EVENT_GET_SPDI_DONE));mRecordsToLoad++;
mFh.loadEFLinearFixed(EF_PNN,1,obtainMessage(EVENT_GET_PNN_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_SST,obtainMessage(EVENT_GET_SST_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_INFO_CPHS,obtainMessage(EVENT_GET_INFO_CPHS_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_GID1,obtainMessage(EVENT_GET_GID1_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_GID2,obtainMessage(EVENT_GET_GID2_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_PLMN_W_ACT,obtainMessage(EVENT_GET_PLMN_W_ACT_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_OPLMN_W_ACT,obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_HPLMN_W_ACT,obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_EHPLMN,obtainMessage(EVENT_GET_EHPLMN_DONE));mRecordsToLoad++;
mFh.loadEFTransparent(EF_FPLMN,obtainMessage(EVENT_GET_FPLMN_DONE,HANDLER_ACTION_NONE,-1));
mRecordsToLoad++;
loadEfLiAndEfPl();}