本文讲解SIMRecords

/frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java

构造方法:

    public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
super(app, c, ci);
mAdnCache = new AdnRecordCache(mFh);
mVmConfig = new VoiceMailConstants();
mSpnOverride = new SpnOverride(); mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);//消息注册,当Ci接收到EVENT_SMS_ON_SIM消息通知SIMRecords
mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null); // Start off by setting empty state
resetRecords();
mParentApp.registerForReady(this, EVENT_APP_READY, null);//当卡准备好,UiccCardApplication会通过notifyReadyRegistrantsifNeeded()通知SIMRecords
mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null);//EVENT_APP_LOCKED消息同样处理
if (DBG) log("SIMRecords X ctor this=" + this); IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
c.registerReceiver(mReceiver, intentfilter); //接收ACTION_CARRIER_CONFIG_CHANGED消息的处理
}

接收UiccCardApplication 的通知,消息EVENT_APP_READY、EVENT_APP_LOCKED 的处理:

        try { switch (msg.what) {
case EVENT_APP_READY:
onReady();
break; case EVENT_APP_LOCKED:
onLocked();
break;
}

onReady() 方法,直接调用fetchSimRecords(),到这里开始加载EF文件信息:

具体的读取SIM卡EF文件信息的过程是有IccFileHandler来实现的,根据EF文件的类型,调用不同的方法loadEFTransparent()和loadEFLinearFixed(),最终都会调用RILJ 的iccIOForApp() 方法;

    protected void fetchSimRecords() {
if (DBG) log("fetchSimRecords " + mRecordsToLoad); mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));//获取IMSI信息,返回的数据在该类handleMessage()中处理
mRecordsToLoad++;  //没读取一项信息,计数值就加1
mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));//获取ICCID
mRecordsToLoad++; // Same goes for Call Forward Status indicator: fetch both
// EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
loadCallForwardingRecords();
getSpnFsm(true, null);
loadEfLiAndEfPl(); if (CRASH_RIL) {
String sms = "0107912160130310f20404d0110041007030208054832b0120"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "ffffffffffffffffffffffffffffff";
byte[] ba = IccUtils.hexStringToBytes(sms);
mFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
}
if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
}

loadEFTransparent() 方法:

    public void loadEFTransparent(int fileid, Message onLoaded) {
Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
fileid, , onLoaded); mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
, , GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
}

消息EVENT_GET_IMSI_DONE、EVNET_GET_ICCID_DONE在handleMessage() 中处理,解析出IMSI、ICCID值:

            /* IO events */
case EVENT_GET_IMSI_DONE:
isRecordLoadResponse = true; ar = (AsyncResult)msg.obj; mImsi = (String) ar.result;//获取MCC、MNC、MSIN
// IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
// than 15 (and usually 15).
if (mImsi != null && (mImsi.length() < || mImsi.length() > )) {
loge("invalid IMSI " + mImsi);
mImsi = null;
} log("IMSI: mMncLength=" + mMncLength);
log("IMSI: " + mImsi.substring(, ) + "xxxxxxx");
.........
mImsiReadyRegistrants.notifyRegistrants();
break;
            case EVENT_GET_ICCID_DONE:
isRecordLoadResponse = true; ar = (AsyncResult)msg.obj;
data = (byte[])ar.result;
mIccId = IccUtils.bcdToString(data, , data.length);//转换BCD码
mFullIccId = IccUtils.bchToString(data, , data.length); log("iccid: " + SubscriptionInfo.givePrintableIccid(mFullIccId));
break;

handleMessage() 方法解析数据后,调用onRecordLoaded()方法,mRecordsToLoad减1:

    protected void onRecordLoaded() {
// One record loaded successfully or failed, In either case
// we need to update the recordsToLoad count
mRecordsToLoad -= 1;//SIM数据读取成功一次,该参数就减1
if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested); if (mRecordsToLoad == 0 && mRecordsRequested == true) {//mRecordsToLoad值为0,代表fetchSimRecords()中启动加载的数据都已异步读取完成
onAllRecordsLoaded();
} else if (mRecordsToLoad < 0) {
loge("recordsToLoad <0, programmer error suspected");
mRecordsToLoad = 0;
}
}

mRecordsToLoad 值为0,进入onAllRecordsLoaded() 方法,对读取的数据进行处理与存储:

    protected void onAllRecordsLoaded() {
if (DBG) log("record load complete"); Resources resource = Resources.getSystem();
if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) {
setSimLanguage(mEfLi, mEfPl);
} else {
if (DBG) log ("Not using EF LI/EF PL");
} setVoiceCallForwardingFlagFromSimRecords(); if (mParentApp.getState() == AppState.APPSTATE_PIN ||
mParentApp.getState() == AppState.APPSTATE_PUK) {
// reset recordsRequested, since sim is not loaded really
mRecordsRequested = false;
// lock state, only update language
return ;
} // Some fields require more than one SIM record to set String operator = getOperatorNumeric();
if (!TextUtils.isEmpty(operator)) {
log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
operator + "'");
log("update icc_operator_numeric=" + operator);
mTelephonyManager.setSimOperatorNumericForPhone(
mParentApp.getPhoneId(), operator);
final SubscriptionController subController = SubscriptionController.getInstance();
subController.setMccMnc(operator, subController.getDefaultSubId());
} else {
log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
} if (!TextUtils.isEmpty(mImsi)) {
log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + mImsi) : ""));
mTelephonyManager.setSimCountryIsoForPhone(
mParentApp.getPhoneId(), MccTable.countryCodeForMcc(
Integer.parseInt(mImsi.substring(0,3))));
} else {
log("onAllRecordsLoaded empty imsi skipping setting mcc");
} setVoiceMailByCountry(operator); mRecordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
}

到此sim卡初始化基本流程就结束了。

Android 7.0 UICC 分析(四)的更多相关文章

  1. Android 7.0 UICC 分析(二)

    本文讲解UiccCard类 /frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/UiccCard.java U ...

  2. Android 7.0 UICC 分析(三)

    本文讲解UICCCardApplication /frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/UiccC ...

  3. Android 7.0 UICC 分析(一)

    UICC(Universal Intergrated Circuit Card) 框架 * Following is class diagram for uicc classes: * * UiccC ...

  4. Android 5.0 Uicc框架分析

    已同步更新至个人blog:   dxjia.cn Uicc框架 UICC框架是Android在4.1引入的,使的对卡的管理控制更加清晰.要了解这个UICC框架,需要从UiccController开始, ...

  5. Android 8.1 源码_启动篇(二) -- 深入研究 zygote(转 Android 9.0 分析)

    前言 在Android中,zygote是整个系统创建新进程的核心进程.zygote进程在内部会先启动Dalvik虚拟机,继而加载一些必要的系统资源和系统类,最后进入一种监听状态.在之后的运作中,当其他 ...

  6. Android 7.0 启动篇 — init原理(二)(转 Android 9.0 分析)

    ========================================================          ================================== ...

  7. Android指纹识别深入浅出分析到实战(6.0以下系统适配方案)

    指纹识别这个名词听起来并不陌生,但是实际开发过程中用得并不多.Google从Android6.0(api23)开始才提供标准指纹识别支持,并对外提供指纹识别相关的接口.本文除了能适配6.0及以上系统, ...

  8. Android 6.0权限全面详细分析和解决方案

    原文: http://www.2cto.com/kf/201512/455888.html http://blog.csdn.net/yangqingqo/article/details/483711 ...

  9. Android深入四大组件(四)Android8.0 根Activity启动过程(前篇)

    前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...

随机推荐

  1. Javascript猜数字游戏

    <!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...

  2. 自己用c语言实现字符串处理库函数以及扩展

    1.实现基本的c语言库函数: int myStrlen( const char* str);//根据传入的字符串首地址获取字符串长度:返回值为长度 int myStrlen(const char* s ...

  3. Android: R cannot be resolved to a varia...

    Android: R cannot be resolved to a varia... 2012-07-27 10:58:32     上传者: wangdao下载(0) 浏览(57568) 评论(0 ...

  4. 1、win32创建窗口函数(windows程序内部运行机制)

    利用win32创建窗口函数,主要操作步骤为: 1.设计一个窗口类 2.注册窗口类 3.创建窗口 4.显示及窗口更新 5.消息循环 6.窗口过程函数   (1)设计一个窗口类 设计窗口类,这样的类型已经 ...

  5. 样式:让div里的两个控件在一行的操作

    table的td里如果放一个text,希望在右侧再放一个按钮,让这两个控件在一行,但是放了之后总是底部不能对齐,这样的话,加上下边这句样式就可以了 position:relative; top:17p ...

  6. linux ssh publickey登录

    一.公钥认证的基本思想: 对信息的加密和解密采用不同的key,这对key分别称作private key和public key,其中,public key存放在目标服务器上,而private key为特 ...

  7. Orcle基本语句(六)

    -- Created on 2017/1/5 by ADMINISTRATOR DECLARE -- Local variables here i ; v_name ) := '张晓风'; v_age ...

  8. 怎样去除SVN中的某个版本之前的所有版本

    地狱门神 在某些时候,我们可能需要一个存放二进制文件的SVN库,用来保存每日构建的结果等.但是这种库会趋于越来越大,最后会占用很多磁盘空间.这时我们会想到能不能删掉某个版本之前的所有版本,以节省磁盘空 ...

  9. 如何优雅的实现INotifyPropertyChanged接口

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ...

  10. EM算法(4):EM算法证明

    目录 EM算法(1):K-means 算法 EM算法(2):GMM训练算法 EM算法(3):EM算法运用 EM算法(4):EM算法证明 EM算法(4):EM算法证明 1. 概述 上一篇博客我们已经讲过 ...