本文讲解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. 【转载】变更MySql数据存储路径的方法

    1.在mysql安装目录下找到my.ini文件,更改#Path to the database root datadir="希望存放数据的地址" 2.将默认存放路径(一般为&quo ...

  2. Modelsim-altera 仿真 顶层原理图设计的FPGA

    我的原理图采用的是bdf的顶层原理图的设计,仿真工具用的是modelsim-altera,调用仿真后的错误提示: # ** Error: (vsim-3033) C:/Users/lenovo/Des ...

  3. Ubuntu16.04 apache2 wsgi 部署django

    在Ubuntu16.04上部署django其实还算简单直观,最重要的问题就是路径设置正确,并且保证版本统一,这个测试是在 Apache/2.4.18 (Ubuntu)  apt-get install ...

  4. appium移动端测试之滑动(二)

    在ios测试中,需要用到滑动,所以用java封装了一套滑动的方法,不多说,贴代码 /** * 上滑1/4屏幕 */ public void slideUP1_4() { int x = driver. ...

  5. (转)关于URLDownloadToFile下载文件

    转自:http://zhouhaijiang3.blog.163.com/blog/static/43477220200931981322497/ 在下载文件时,下载文件的目录大小写要注意和虚拟目录的 ...

  6. svn记录删除

    Delete SVN Folders.reg 批量删除文件夹里的SVN 文件 ------------------------------------------------------------- ...

  7. Ubuntu更改鼠标灵敏度

    需要命令:xinput 清自行用 man xinput 查询 xinput 帮助文档 1.插入鼠标,打开终端,输入命令:xinput 查询当前已挂在设备 2.拔出鼠标,打开终端,再输入命令:xinpu ...

  8. Word自动生成目录

    博主最近在写报告的时候要在Word里面做个目录,再做个页码,然后上网搜了一些方法,非常零散,我弄了好久才弄好.在这里我把整套方法分享一下. 声明:内容完全独创! 工具:Word 2016. 效果:如下 ...

  9. vs签入签出--TFS进行源代码管理

    工作项是项目管理的基本元素.工作项说明了要做什么事(例如任务),出了什么问题(例如Bug),除此之外,我们还需要将程序一行一行地写出来,TFS的源代码管理控制系统,就能帮助我们管理这一行行的代码,一个 ...

  10. Java白皮书的关键术语

    “白皮书”可以在http://www.oracle.com/technetwork/java/langenv-140151.html上找到. 1.简单性. 2.面向对象. 3.网络技能(Network ...