本文主要讲USIM卡插入手机后读取卡中contacts信息的流程。
整体流程总结
- 每次插拔SIM卡都会将联系人数据库中关于SIM卡的联系人删除
- SimStateReceiver 通过接收 RIL 上报的关于 SIM 卡状态变化的广播去启动 SimContactsService
- SimContactsService 异步启动 IccProvider 去查询 SIM 卡联系人
- 通过 IccPhoneBookInterfaceManager 一层层调用到 RIL 然后层层返回,最后构造MatrixCursor 插入数据库
先介绍几个类的作用:
- IccProvider:对外暴露的接口,我们通过它来查询SIM卡中的contacts信息
- IccPhoneBookInterfaceManager: PhoneBook操作的服务
- IccPhoneBookInterfaceManagerProxy:对外的PhoneBook操作服务, 上面类的代理.
- IccRecord:存储与卡相关的一些信息
- AdnRecord:一条联系人信息读取后被封装的类型
- AdnRecordCache:对SIM卡中联系人信息进行Cache
- AdnRecordLoader:实际通过IccFileHandler去获取adn信息的类
- IccFileHandler:向RIL发起请求,或者接受反馈
- RIL:向底层发起请求,并接收反馈
大体流程图如下:
重要的几个方法:
public List<AdnRecord> getAdnRecordsInEf(int efid) {
if (mPhone.getContext().checkCallingOrSelfPermission(
android.Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"Requires android.permission.READ_CONTACTS permission");
}
synchronized(mLock) {
checkThread();
AtomicBoolean status = new AtomicBoolean(false);
Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status);
efid = updateEfForIccType(efid);
if (DBG) logd("getAdnRecordsInEF: efid=" + efid);
if (mAdnCache != null) {
mAdnCache.requestLoadAllAdnLike(efid,
mAdnCache.extensionEfForEf(efid), null, response);
waitForResult(status);
} else {
loge("Failure while trying to load from SIM due to uninitialised adncache");
}
if (mRecords == null && efid == IccConstants.EF_PBR && !mAdnCache.isPbrPresent()) {//如果通过EF_PBR得不到值就通过EF_ADN的路径拿数据
logd("getAdnRecordsInEF: Load from EF_ADN as pbr is not present");
mForceAdnUsage = true;
return getAdnRecordsInEf(IccConstants.EF_ADN);
}
}
return mRecords;
}
private int updateEfForIccType(int efid) {
// Check if we are trying to read ADN records
if (efid == IccConstants.EF_ADN && !mForceAdnUsage) {
if (mPhone.getCurrentUiccAppType() == AppType.APPTYPE_USIM ||
mPhone.getCurrentUiccAppType() == AppType.APPTYPE_CSIM) {
return IccConstants.EF_PBR; //SIM卡返回:EF_ADN 、USIM卡返回EF_PBR 这个返回值影响着我们应该读取UICC中的那个文件路径
}
}
return efid;
}
public ArrayList<AdnRecord> loadEfFilesFromUsim() {
synchronized (mLock) {
if (!mPhoneBookRecords.isEmpty()) {
if (mRefreshCache) {
mRefreshCache = false;
refreshCache();
}
return mPhoneBookRecords;
}
if (!mIsPbrPresent) return null;
// Check if the PBR file is present in the cache, if not read it
// from the USIM.
if (mPbrFile == null) {
readPbrFileAndWait();
}
if (mPbrFile == null) return null;
int numRecs = mPbrFile.mFileIds.size();
if ((mAnrFlagsRecord == null) && (mEmailFlagsRecord == null)) {
mAnrFlagsRecord = new ArrayList[numRecs];
mEmailFlagsRecord = new ArrayList[numRecs];
for (int i = 0; i < numRecs; i++) {
mAnrFlagsRecord[i] = new ArrayList<Integer>();
mEmailFlagsRecord[i] = new ArrayList<Integer>();
}
}
for (int i = 0; i < numRecs; i++) { //一直读取里面的信息,并放mPhoneBookRecords当中,这个值会影响到contacts里面MemoryStatusActivity中显示sim 卡total的值
readAdnFileAndWait(i);
readEmailFileAndWait(i);
readAnrFileAndWait(i);
}
// All EF files are loaded, post the response.
}
return mPhoneBookRecords;
}
重要的log信息
Line 10831: 07-15 18:52:30.427 D/IccProvider( 3714): [IccProvider] query
Line 10835: 07-15 18:52:30.427 D/IccProvider( 3714): [IccProvider] loadFromEf: efType=28474, subscription=3 //ADN
Line 10837: 07-15 18:52:30.429 D/SimPhoneBookIM( 3714): [SimPbInterfaceManager] getAdnRecordsInEF: efid=20272 //PBR
Line 10843: 07-15 18:52:30.429 D/UsimFH ( 3714): Using Global Phonebook
Line 10845: 07-15 18:52:30.429 D/UsimFH ( 3714): Using Local Phonebook
Line 10847: 07-15 18:52:30.429 D/IccProvider( 3714): [IccProvider] adnRecords.size=500
Line 10849: 07-15 18:52:30.429 D/IccProvider( 3714): [IccProvider] loadRecord: Luoyi, 15202863711,
Line 33763: 07-15 18:54:38.049 D/UsimPhoneBookManager( 3714): Loading PBR done
Line 53039: 07-15 18:55:34.067 D/AdnRecordCache( 3714): Using Local Phonebook
SIM卡基础知识
SIM卡上的所有数据都是以文件的形式存放在卡片数据存储区中的,如下图所示:
MF:代表根目录,DF:代表目录,EF:代表文件
三种EF文件:透明文件Transparent/记录文件Linear fixed/循环文件Cydic
卡片上,每个目录或文件都有自己的ID,称为FID
SIM 看文件结构如下:
SIM卡文件系统结构如下:
其中:
- 3F Master file (MF,文件系统根目录)
- 7F Dedicated file (DF,专用文件目录)
- 2F Elementary file(MF,位于主文件目录下)
- 6F Elementary file(MF,位于专用文件目录下)
- SIM: 用户识别模块(Subscriber Identity Module) (GSM/WCDMA/TD-SCDMA) UICC卡上存储GSM用户签约信息的一个应用
- USIM: 通用用户识别模块(Universal Subscriber Identity Module) (GSM/WCDMA/TD-SCDMA) UICC卡上存储3G用户签约信息的一个应用。
- USIM可以同时包括USIM和SIM两个逻辑模块,也可以只包括USIM逻辑模块,第一种叫做复合USIM卡,也就是说可以兼容2G与3G终端,第二种是纯粹的USIM卡,只能在3G终端中使用。
USIM与SIM对比
- USIM采用双向鉴权,SIM采用单向鉴权,所以USIM的安全性能更高;
- USIM卡机卡接口的速率约为230bits/s,远优于SIM;
- USIM可以同时支持4个并发的逻辑应用,优于SIM;
- 相对与SIM对STK功能的支持,USIM支持更丰富的STK逻辑通道,也让基于USIM主动发起多业务变成可能(USAT)。
- 相对于SIM,USIM中的电话号码簿每个联系人都可以对应有多个号码以及多个昵称