SystemUI之SIMLock 锁卡UI界面流程梳理

一、锁卡背景介绍

  锁卡即SIMLock,当手机开机启动或者插入SIM卡时,手机modem侧预置在NV项中的配置信息会与SIM卡中的信息做比对,检测是否匹配。若匹配,则SIM卡可以正常使用。若不匹配,则SIM卡相关功能均无法正常使用,例如拨打电话、发送短信及上网等;或者是只能注册2G网,不能注册4G。

  锁卡的目的:一些运营商会要求控制某一类卡的使用,从而保护自己的利益(运营商定制机)

  SIMLock锁和图案锁,数字密码锁,PIN码锁,PUK锁一样,是Keyguard模块中的一种锁。

二、锁卡的需求

  锁卡的需求方式有7种之多,常见的有NP锁,NS锁,CP锁,SP锁等

  从安卓机器来看,目前最常用的是SP锁(MCC/MNC),本文将解析SP锁的加锁流程

三、锁卡流程解析

  1.首先modem侧检测SIM卡的配置信息并与之作比对,若匹配则继续加载SIM卡,若不匹配,则上报加锁信息

  2.RIL层检测到modem上报的加锁信息,然后发送给framework层,最终在AP层监测到事件:

  3.AP层显示出锁卡界面,要求用户输入解锁码进行解锁

四、相关流程图

1.加锁流程图

2.解锁流程图

五、上层UI界面流程

       1.与锁卡界面相关类主要有:1.KeyguardUpdateMonitor:监听各种广播,比如时间、SIM卡状态、电池电量等。

                                                2.KeyguardSimPinPukMeView:锁卡UI界面的显示类。如下图


                                                3.KeyguardViewMediator:在SIM卡被锁卡之后的dialog显示。

                                       

                                                4.KeyguardUtils    :工具类。

        2.他们之间的关系:

                                 他们采用观察者模式,KeyguardUpdateMonitor是所有类的监控器,KeyguardSimPinPukMeView和KeyguardViewMediator通过registerCallback注册监听。

      3.锁卡UI界面的逻辑流程

         KeyguardUpdateMonitor  ->onReceive()监听SIM卡变化广播,对SIM的状态进行判断,最终会回调之前registerCallback注册的监听接口.KeyguardSimPinPukMeView  ->onSimStateChangedUsingPhoneId

    注释:SIM卡的状态:IccCardConstants->

                      UNKNOWN,        /** ordinal(0) == {@See TelephonyManager#SIM_STATE_UNKNOWN} */
                    ABSENT,         /** ordinal(1) == {@See TelephonyManager#SIM_STATE_ABSENT} */
                 PIN_REQUIRED,   /** ordinal(2) == {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} */
                PUK_REQUIRED,   /** ordinal(3) == {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} */
                 NETWORK_LOCKED, /** ordinal(4) == {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} */
                  READY,          /** ordinal(5) == {@See TelephonyManager#SIM_STATE_READY} */
               NOT_READY,      /** ordinal(6) == {@See TelephonyManager#SIM_STATE_NOT_READY} */
             PERM_DISABLED,  /** ordinal(7) == {@See TelephonyManager#SIM_STATE_PERM_DISABLED} */
             CARD_IO_ERROR,  /** ordinal(8) == {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} */

              CARD_RESTRICTED;/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */

      这些状态的意思,具体的可以查看TelephonyManager里面的注释。

    4.一些UI界面的显示


这个逻辑界面的显示是在KeyguardSimPinPukMeView  ->resetState

  

 if (count < 2) {
            if (simState == IccCardConstants.State.PIN_REQUIRED) {
                msg = rez.getString(R.string.kg_sim_pin_instructions);
                mUnlockEnterState = STATE_ENTER_PIN;
            } else if (simState == IccCardConstants.State.PUK_REQUIRED) {
                msg = rez.getString(R.string.kg_puk_enter_puk_hint);
                mUnlockEnterState = STATE_ENTER_PUK;
            } else if ((IccCardConstants.State.NETWORK_LOCKED == simState) &&
                KeyguardUtils.isMediatekSimMeLockSupport()) {
                int category = mUpdateMonitor.getSimMeCategoryOfPhoneId(mPhoneId);
                msg = rez.getString(R.string.simlock_entersimmelock)
                    + strLockName[category]
                    + getRetryMeString(mPhoneId);
                mUnlockEnterState = STATE_ENTER_ME;
            }
        } else {

     看这段代码就知道界面的显示会有两个分支,一个是count>=2,一个是count<2.count是什么鬼呢?它表示机器可以支持几个卡槽。也就我们说的单卡还是双卡。MTK平板的是双卡曹,所以走else。Wrong Code Enter SIM ME lock 由R.string.simlock_entersimmelock定义。[NP] 由strLockName [category]定义。

  strLockName = {" [NP]", " [NSP]", " [SP]", " [CP]", " [SIMP]"};  它表示锁卡类型。Remains:2  由getRetryMeString(mPhoneId)定义,最开始是5次随着输入错误次数最后会变成0,此卡也就被锁了。那么次数是如何决定的呢?一开始初始化 KeyguardUpdateMonitor  ->DEFAULT_ME_RETRY_COUNT = 5 后面由run方法校准。

 public void run() {
            try {
                mSimMeCategory.put(simArgs.phoneId, simArgs.simMECategory);
                Log.d(TAG, "queryNetworkLock, phoneId =" + simArgs.phoneId + ", simMECategory ="
                        + simArgs.simMECategory);

                if (simArgs.simMECategory < 0 || simArgs.simMECategory > 5) {
                    return;
                }

                int subId = KeyguardUtils.getSubIdUsingPhoneId(simArgs.phoneId) ;
                Bundle bundle = IMtkTelephonyEx.Stub.asInterface(
                         ServiceManager.getService("phoneEx"))
                        .queryNetworkLock(subId, simArgs.simMECategory);
                boolean query_result = bundle.getBoolean(QUERY_SIMME_LOCK_RESULT, false);

                Log.d(TAG, "queryNetworkLock, " + "query_result =" + query_result);
                if (query_result) {
                    mSimMeLeftRetryCount.put(simArgs.phoneId,
                                             bundle.getInt(SIMME_LOCK_LEFT_COUNT, 5));//锁卡次数
                } else {
                    Log.e(TAG, "queryIccNetworkLock result fail");
                }
                mHandler.sendMessage(mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, simArgs));
            } catch (Exception e) {
                Log.e(TAG, "queryIccNetworkLock got exception: " + e.getMessage());
            }

那么每次输入错误它由如何递减呢?KeyguardSimPinPukMeView  ->minusRetryMeCount 调用KeyguardUpdateMonitor  ->minusSimMeLeftRetryCountOfPhoneId(phoneId)。

    按enter键,它由如何验证输入的密码是否正确?

     KeyguardPinBasedInputView是所有按键的逻辑处理类,

 mOkButton = findViewById(R.id.key_enter);
        if (mOkButton != null) {
            mOkButton.setOnTouchListener(this);
            mOkButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mPasswordEntry.isEnabled()) {
                        verifyPasswordAndUnlock();
                    }
                }
            });

会调用verifyPasswordAndUnlock(),verifyPasswordAndUnlock()是一个抽象方法最终由KeyguardSimPinPukMeView  实现

 protected void verifyPasswordAndUnlock() {
        String entry = mPasswordEntry.getText().toString();//获取输入密码。

        ///M: here only for PIN code
        if ((false == validatePin(entry, false)//密码格式判断是否正确) &&
            (mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) == IccCardConstants.State.PIN_REQUIRED ||
            (mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) == IccCardConstants.State.NETWORK_LOCKED)
             && KeyguardUtils.isMediatekSimMeLockSupport())) {

            // otherwise, display a message to the user, and don't submit.
            if (mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) ==
                IccCardConstants.State.PIN_REQUIRED) {
                mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint);
            } else {
                // hint to enter 4-8 digits for network_lock mode
                mSecurityMessageDisplay.setMessage(R.string.keyguard_code_length_prompt);
            }

            mPasswordEntry.reset(true, true);
            mPasswordEntry.setEnabled(true);
            mCallback.userActivity();

            return;
        }
        mPasswordEntry.setEnabled(true);//对输入的密码进行验证
        dealWithPinOrPukUnlock();
    }
 
private void dealWithPinOrPukUnlock() {
        if (mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) == IccCardConstants.State.PIN_REQUIRED) {
            Log.d(TAG, "onClick, checkPin, mPhoneId=" + mPhoneId);
            checkPin(mPhoneId);
        } else if (mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) ==
                 IccCardConstants.State.PUK_REQUIRED) {
            Log.d(TAG, "onClick, checkPuk, mPhoneId=" + mPhoneId);
            checkPuk(mPhoneId);
        } else if ((mUpdateMonitor.getSimStateOfPhoneId(mPhoneId) ==
                  IccCardConstants.State.NETWORK_LOCKED)
            && KeyguardUtils.isMediatekSimMeLockSupport()) {
            Log.d(TAG, "onClick, checkMe, mPhoneId=" + mPhoneId);
            checkMe(mPhoneId);
        } else {
            Log.d(TAG, "wrong status, mPhoneId=" + mPhoneId);
        }
    }

SIM的状态是IccCardConstants.State.NETWORK_LOCKED,所以走checkMe。

    private void checkMe(int phoneId) {
        getSimUnlockProgressDialog().show();
        if (!mSimCheckInProgress) {
            mSimCheckInProgress = true; // there should be only one
            new CheckSimMe(mPasswordEntry.getText().toString(), phoneId) {
                void onSimMeCheckResponse(final int ret) {
                    Log.d(TAG, "checkMe onSimChangedResponse, ret = " + ret);
                    if (VERIFY_RESULT_PASS == ret) {
                        Log.d(TAG, "checkMe VERIFY_RESULT_PASS == ret(we had sent runnable before");
                        mUpdateMonitor.reportSimUnlocked(mPhoneId);
                        mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
                    } else if (VERIFY_INCORRECT_PASSWORD == ret) {
                        mSb.delete(0, mSb.length());
                        minusRetryMeCount(mPhoneId);//减少错误次数


                        if (mSimUnlockProgressDialog != null) {
                            mSimUnlockProgressDialog.hide();
                        }
                        if (mUnlockEnterState == STATE_ENTER_ME) {
                            if (0 == getRetryMeCount(mPhoneId)) { //permanently locked
                                setInputInvalidAlertDialog(mContext.getText(
                                        R.string.simlock_slot_locked_message), true);//弹出对话框
                                mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
                            } else {
                                int category = mUpdateMonitor.getSimMeCategoryOfPhoneId(mPhoneId);
                                mSb.append(mContext.getText(R.string.keyguard_wrong_code_input));
                                mSb.append(mContext.getText(R.string.simlock_entersimmelock));
                                mSb.append(strLockName[category] + getRetryMeString(mPhoneId));
                            }
                            Log.d(TAG, "checkMe() - VERIFY_INCORRECT_PASSWORD == ret, "
                                + "mSecurityMessageDisplay.setMessage = " + mSb.toString()) ;
                            mSecurityMessageDisplay.setMessage(mSb.toString());
                            mPasswordEntry.reset(true, true);//刷新界面
                        }
                    } else if (VERIFY_RESULT_EXCEPTION == ret) {
                        if (mSimUnlockProgressDialog != null) {
                            mSimUnlockProgressDialog.hide();
                        }
                        setInputInvalidAlertDialog("Exception happen, fail to unlock", true);
                        mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
                    }
                    mCallback.userActivity();
                    mSimCheckInProgress = false;
                }
            } .start();
        }

     SIM锁卡后,每次开机都会谭一个dialog

KeyguardViewMediator ->onSimStateChangedUsingPhoneId

  

 if (IccCardConstants.State.NETWORK_LOCKED == simState
                                    && 0 == mUpdateMonitor.getSimMeLeftRetryCountOfPhoneId(phoneId)
                            ) {
                            //add xiao
                            if(LOCK_TIMES<2){
								LOCK_TIMES++;
                            Log.d(TAG, "SIM ME lock retrycount is 0, only to show dialog");
                            mDialogManager.requestShowDialog(new MeLockedDialogCallback());//锁卡后弹出的对话框,弹出的对话框次数依据回调onSimStateChangedUsingPhoneId次数决定。
                            	}
                            break;
                        }




  

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值