600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > SIM PIN Lock

SIM PIN Lock

时间:2018-09-21 23:59:28

相关推荐

SIM PIN Lock

独角兽企业重金招聘Python工程师标准>>>

PIN,全称Personal Identification Number,即个人识别码,用来认证使用者的身份。

当用户启用PIN后,手机在加载SIM卡时(开机或插卡)就会要求用户输入PIN,这时用户有3次输入PIN的机会,

但若3次都输入错误的话,就会要求输入PUK,即PIN Unlocking Key,PUK是PIN的解锁码,需要注意的是,

PUK总共只有10次输入机会,也就是说,只要输入了10次错误的PUK,该SIM卡就报废了,而这里所说的10次

并非指连续10次,而是只要输错一次,SIM卡内部计数器就减1,即使输入正确的PUK后,计数器的值也不会被

恢复,直到计数器减为0后,该卡报废。

PIN的种类

Universal PIN:多个Application共用一个PIN

Application PIN:Application自己的PIN

Local PIN:某个DF特有的PIN

手机在读取启用了PIN的SIM卡时,读到的状态为PIN,可通过如下的RIL log查看APPSTATE字段。

RILJ : [3775]< GET_SIM_STATUS IccCardState {CARDSTATE_PRESENT,PINSTATE_ENABLED_NOT_VERIFIED,num_apps=1,gsm_id=0{APPTYPE_USIM,APPSTATE_PIN,pin1=PINSTATE_ENABLED_NOT_VERIFIED,pin2=PINSTATE_ENABLED_NOT_VERIFIED},cdma_id=-1,ims_id=-1} [SUB0]

而APPSTATE在IccCardApplicationStatus.AppState进行了定义,一共有以下几种状态:

public enum AppState{

APPSTATE_UNKNOWN,

APPSTATE_DETECTED,

APPSTATE_PIN,

APPSTATE_PUK,

APPSTATE_SUBSCRIPTION_PERSO,

APPSTATE_READY;

}

由于之前在UICC开机初始化的流程中已经对卡状态上报流程进行了一些分析,因此我们在这里就只简单说明下。

首先,在IccCardProxy中会注册监听EVENT_ICC_LOCKED事件。

private void registerUiccCardEvents() {

......

if (mUiccApplication != null) {

......

mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null);

......

}

......

}

当modem上报PIN_LOCKED后,在UiccCardApplication.update()方法中,会执行通知监听者的操作。

public void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {

......

if (mAppState != oldAppState) {

......

notifyPinLockedRegistrantsIfNeeded(null);

......

}

然后就是在IccCardProxy中处理EVENT_ICC_LOCKED事件。

public void handleMessage(Message msg) {

......

case EVENT_ICC_LOCKED:

processLockedState();

break;

......

}

将ExternalState设置为PIN_REQUIRED,为啥叫ExternalState?我也不知道!

private void processLockedState() {

......

AppState appState = mUiccApplication.getState();

switch (appState) {

case APPSTATE_PIN:

mPinLockedRegistrants.notifyRegistrants();

setExternalState(State.PIN_REQUIRED);

break;

......

}

private void setExternalState(State newState) {

setExternalState(newState, false);

}

对于ICC_LOCKED这种状态,我们需要发送InternalIccStateChanged的广播,为啥又是Internal?跟ExternalState啥关系?不知道!

private void setExternalState(State newState, boolean override) {

......

// For locked states, we should be sending internal broadcast.

if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(getIccStateIntentString(mExternalState))) {

broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState),

getIccStateReason(mExternalState));

} else {

broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),

getIccStateReason(mExternalState));

}

......

}

我们来看看广播的内容,包含了ICC_STATE、LOCKED_REASON,以及PhoneId。

private void broadcastInternalIccStateChangedIntent(String value, String reason) {

......

Intent intent = new Intent(ACTION_INTERNAL_SIM_STATE_CHANGED);

intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING

| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");

intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);

intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);

intent.putExtra(PhoneConstants.PHONE_KEY, mPhoneId); // SubId may not be valid.

log("Sending intent ACTION_INTERNAL_SIM_STATE_CHANGED" + " for mPhoneId : " + mPhoneId);

ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);

}

}

接下来我们再来看看接受广播的地方,在SubscriptionInfoUpdater中,

发送消息让Handler处理EVENT_SIM_LOCKED事件。

private final BroadcastReceiver sReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {

......

} else if (action.equals(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED)) {

if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(simStatus)) {

String reason = intent.getStringExtra(

IccCardConstants.INTENT_KEY_LOCKED_REASON);

sendMessage(obtainMessage(EVENT_SIM_LOCKED, slotIndex, -1, reason));

......

}

logd("[Receiver]-");

}

};

public void handleMessage(Message msg) {

......

case EVENT_SIM_LOCKED:

handleSimLocked(msg.arg1, (String) msg.obj);

break;

......

}

接下来会去读取IccId。

private void handleSimLocked(int slotId, String reason) {

......

if (fileHandler != null) {

String iccId = mIccId[slotId];

if (iccId == null) {

logd("Querying IccId");

fileHandler.loadEFTransparent(IccConstants.EF_ICCID,

obtainMessage(EVENT_SIM_LOCKED_QUERY_ICCID_DONE,

new QueryIccIdUserObj(reason, slotId)));

......

}

读取完IccId后,会再发送广播TelephonyIntents.ACTION_SIM_STATE_CHANGED。

public void handleMessage(Message msg) {

switch (msg.what) {

case EVENT_SIM_LOCKED_QUERY_ICCID_DONE: {

......

broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED,

uObj.reason);

......

}

private void broadcastSimStateChanged(int slotId, String state, String reason) {

Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);

......

i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");

i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state);

i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);

SubscriptionManager.putPhoneIdAndSubIdExtra(i, slotId);

logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " + reason +

" for mCardIndex: " + slotId);

ActivityManager.broadcastStickyIntent(i, UserHandle.USER_ALL);

rebroadcastIntentsOnUnlock.put(slotId, i);

}

再往后就是SystemUI处理广播,然后弹出输入PIN的界面。

在KeyguardSimPinView中,当用户输入PIN并点击确定后,就会调用PhoneInterfaceManager.supplyPinReportResultForSubscriber()

将PIN发送给modem尝试解锁。

public int[] supplyPinReportResultForSubscriber(int subId, String pin) {

enforceModifyPermission();

final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());

checkSimPin.start();

return checkSimPin.unlockSim(null, pin);

}

继续将请求发送给IccCard,完成后会处理SUPPLY_PIN_COMPLETE事件。

synchronized int[] unlockSim(String puk, String pin) {

......

Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);

if (puk == null) {

mSimCard.supplyPin(pin, callback);

} else {

......

}

......

}

而这里的IccCard是通过GsmCdmaPhone获取到的,实际上是一个IccCardProxy对象,

因此实际调用的方法是IccCardProxy的supplyPin().

public void supplyPin(String pin, Message onComplete) {

synchronized (mLock) {

if (mUiccApplication != null) {

mUiccApplication.supplyPin(pin, onComplete);

......

}

继续到UiccApplication处理,通过调用RIL的接口将PIN发送给modem。

public void supplyPin (String pin, Message onComplete) {

synchronized (mLock) {

mCi.supplyIccPinForApp(pin, mAid, mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE,

onComplete));

}

}

modem返回的结果最终会到达PhoneInterfaceManager,并将结果返回给SystemUI。

public void handleMessage(Message msg) {

AsyncResult ar = (AsyncResult) msg.obj;

switch (msg.what) {

case SUPPLY_PIN_COMPLETE:

Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");

synchronized (UnlockSim.this) {

mRetryCount = msg.arg1;

if (ar.exception != null) {

if (ar.exception instanceof CommandException &&

((CommandException)(ar.exception)).getCommandError()

== CommandException.Error.PASSWORD_INCORRECT) {

mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;

} else {

mResult = PhoneConstants.PIN_GENERAL_FAILURE;

}

} else {

mResult = PhoneConstants.PIN_RESULT_SUCCESS;

}

mDone = true;

UnlockSim.this.notifyAll();

}

break;

}

}

而SIM卡解锁后,就会开始进行正常的初始化流程了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。