本文讲解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. load mainaccount

    static void LoadMainAccountCSV(Args _args) { /* SysExcelApplication        excel; SysExcelWorkbooks  ...

  3. GCC的gcc和g++区别

    看的Linux公社的一篇文章,觉得不错,内容复制过来了. 其实在这之前,我一直以为gcc和g++是一个东西,只是有两个不同的名字而已,今天在linux下编译一个c代码时出现了错误才找了一下gcc和g+ ...

  4. Salesforce 使用Js 调用Webservice实例

    1,创建 Custom Button 在页面上 2, 创建CustomJs 代码调用Webservice <!--参数名区分大小写,对于跨层object直接在Object名后直接加参字段名即可- ...

  5. Hash函数及其应用

    本文部分内容摘自网络,参考资料链接会在文后给出,在此感谢原作者的分享. 计算理论中,没有Hash函数的说法,只有单向函数的说法.所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数 ...

  6. 永久修改 CMD 的 PROMPT 显示结果/给cmd命令显示加上运行时间

    1.环境 windows10 系统 2.打开 cmd ,快捷键 Ctrl + x 然后a 3.输入 REG ADD "HKLM\SYSTEM\CurrentControlSet\Contro ...

  7. dede无子栏目的栏目直接调用顶级栏目(不让调用的解决方法) noself=\'yes\'

    大家在用dede做网站的时候经常会出现一个问题就是当调用子栏目的时候会出现无子栏目的栏目直接调用顶级栏目,   解决dede无子栏目时出现同级栏目的问题   {dede:channel type='s ...

  8. 老生长谈,温故知新:css实现右侧固定宽度,左侧宽度自适应

    反过来也可以:左侧宽度固定,右侧自适应.不管是左是右,反正就是一边宽度固定,一边宽度自适应. 这种布局比较常见,博客园很多默认主题就是这种.一般情况下,这种布局中宽度固定的区域是侧边栏,而自适应的区域 ...

  9. 查找jsp页面报错技巧

    在报错跳转页面打印错误信息<div>系统执行发生错误,信息描述如下:</div> <div>错误状态代码是:${pageContext.errorData.stat ...

  10. SE要有政治能力

    不光是SE,任何人都需要政治能力. 那么,什么是政治能力?政治能力就是让周围的人跟你一起,一条心,完成你想干的事情的能力. 我们任何人,生活也好,工作也好,学习也好,都不是一个人孤单进行的,都是通过几 ...