zoukankan      html  css  js  c++  java
  • Android 7.0 UICC 分析(四)

    本文讲解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, 0, onLoaded);
    
            mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
                            0, 0, 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() < 6 || mImsi.length() > 15)) {
                        loge("invalid IMSI " + mImsi);
                        mImsi = null;
                    }
    
                    log("IMSI: mMncLength=" + mMncLength);
                    log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxx");
                    .........
                    mImsiReadyRegistrants.notifyRegistrants();
                break;
                case EVENT_GET_ICCID_DONE:
                    isRecordLoadResponse = true;
    
                    ar = (AsyncResult)msg.obj;
                    data = (byte[])ar.result;
                    mIccId = IccUtils.bcdToString(data, 0, data.length);//转换BCD码
                    mFullIccId = IccUtils.bchToString(data, 0, 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卡初始化基本流程就结束了。

  • 相关阅读:
    CSS复合选择器
    模块之shutil模块模块详解
    模块之sys模块详解
    模块之os模块详解
    map遍历
    java完美处理表情符
    死磕设计模式—建造者模式
    Java String getChars()方法
    Java知识系统回顾整理01基础06数组05复制数组
    Java知识系统回顾整理01基础06数组04增强型for循环
  • 原文地址:https://www.cnblogs.com/kaifyou/p/6178881.html
Copyright © 2011-2022 走看看