前记:
因为别人疑问和期望,而对Sim Lock发生兴趣,期望可以帮别人解Sim Lock 锁。·未有发现,不知何时会再拿起,故作整理。
问题:
对于手机Network锁——Sim Lock,指定的运营商的Sim Card有效,其它运营商的Sim Card无效。那各种手机水货是怎么解决Sim Lock问题,使得可以在大陆流行?
有一种说法为:找到手机Sim Lock写入位置,然后擦除。
条件:Android 4.0.4 定制后的framework code. 非原始code.
研究过程:
一. Sim Lock 界面
1. Sim Lock界面是一个Dialog, 由 IccDepersonalizationPanel 产生。
IccDepersonalizationPanel.java 位于 packages/apps/phone 中。
用Eclipse 观察 Sim Lock 界面,查看这个界面是谁产生的,布局如何。 通过 Hierarchy View 发现有一个id为perso_subtype_text的Text View. 对frameworks 和 Phone 的code 搜索,发现Sim Lock界面由 Sim_ndp.xml定义,由 IccDepersonalizationPanel.java 产生。
2. 对Unlock Button进行监听
//调用IccCard中supplyDepersonalization,检验输入的PIN,通过mHandler的handleMessage处理检验结果
mPhone.getIccCard().supplyDepersonalization(pin, mPersoSubtype, Message.obtain(mHandler,EVENT_ICC_DEPERSONALIZATION_RESULT));
//显示IN_PROGRESS过程信息
displayStatus(IN_PROGRESS);
3. mHandler
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == EVENT_ICC_DEPERSONALIZATION_RESULT) {
AsyncResult res = (AsyncResult) msg.obj;
if (res.exception != null) {
if (DBG) log("De-Personalization request failure.");
displayStatus(ERROR); // PIN输入错误
postDelayed(new Runnable() { // 重新显示Sim Lock输入界面
public void run() {
hideAlert();
mPinEntry.getText().clear();
mPinEntry.requestFocus();
}
}, 3000);
} else {
if (DBG) log("De-Personalization success.");
displayStatus(SUCCESS); // PIN 输入正确
postDelayed(new Runnable() { // 3秒后关闭Sim Lock Dialog
public void run() {
dismiss();
}
}, 3000);
}
}
}
};
二. Sim Lock 产生过程
1. PhoneApp.java 的onCreate()中通过IccCard注册监听
PhoneApp.java 位于 packages/apps/phone 中。在PhoneApp.java 的 onCreate() 中注册监听。
//通过IccCard的registerForPersoLocked注册监听,通过mHandler处理监听结果
// register for ICC status
IccCard sim = phone.getIccCard();
if (sim != null) {
if (VDBG) Log.v(LOG_TAG, "register for ICC status");
sim.registerForPersoLocked(mHandler, EVENT_PERSO_LOCKED, null);
}
Note: 没有sim card时,不进行Sim Lock监听.
2. mHandler处理Sim Lock消息EVENT_PERSO_LOCKED
case EVENT_PERSO_LOCKED:
if (mContext.getResources().getBoolean(R.bool.ignore_sim_perso_locked_events)) {
// Some products don't have the concept of a "SIM network lock"
Log.i(LOG_TAG, "Ignoring EVENT_PERSO_LOCKED event; " + "not showing 'SIM network unlock' PIN entry screen");
} else {
// Normal case: show the "perso unlock" PIN entry screen.
// The user won't be able to do anything else until
// they enter a valid PIN.
AsyncResult ar = (AsyncResult) msg.obj;
if (ar.result != null) {
initIccDepersonalizationPanel(ar); //初始化Sim Lock的界面
}
}
break;
3. initIccDepersonalizationPanel 初始化Sim Lock类IccDepersonalizationPanel, 并Show Sim Lock Dialog.
void initIccDepersonalizationPanel(AsyncResult ar) {
Log.i(LOG_TAG, "show sim depersonal panel");
int subtype = (Integer)ar.result;
IccDepersonalizationPanel dpPanel =
new IccDepersonalizationPanel(PhoneApp.getInstance(), subtype);
dpPanel.show();
}
三. IccCard 处理Sim Lock过程
1. IccCard.java、IccCardProxy.java
IccCard 是接口基类;IccCardProxy 是IccCard的实现类,并继承于Handler。都位于:
\frameworks\base\telephony\java\com\android\internal\telephony
2. IccCardProxy中的registerForPersoLocked
public void registerForPersoLocked(Handler h, int what, Object obj) {
//打包成登记者,加入SimLock监听队列
Registrant r = new Registrant (h, what, obj);
mPersoLockedRegistrants.add(r);
//检查目前的IccCard状态
if (getState() == State.PERSO_LOCKED) {
r.notifyRegistrant(new AsyncResult(null, mPersoSubState.ordinal(), null));
}
}
3. IccCardProxy中的supplyDepersonalization
/**
* Use invokeDepersonalization from PhoneBase class instead.
*/
public void supplyDepersonalization(String pin, int type, Message onComplete) {
if (mUiccApplication != null) {//双卡处理
mUiccApplication.supplyDepersonalization(pin, type, onComplete);
} else if (onComplete != null) {//单卡处理
Exception e = new RuntimeException("CommandsInterface is not set.");
AsyncResult.forMessage(onComplete).exception = e;
onComplete.sendToTarget();
return;
}
}
4. IccCardProxy接受到Sim Lock消息,并进行处理
case EVENT_PERSO_LOCKED:
mPersoSubState = mUiccApplication.getPersoSubState();
mPersoLockedRegistrants.notifyRegistrants((AsyncResult)msg.obj); // 通知Sim Lock注册队列中的所有登记者.
setExternalState(State.PERSO_LOCKED); //设置Sim card状态
break;
5. setExternalState设置Sim card状态,把Sim Card状态保存在系统属性中,并粘性广播Sim Card状态。
protected void setExternalState(State newState, boolean override) {
if (!override && newState == mExternalState) {
return;
}
mExternalState = newState; // 设置Sim card状态
SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString()); //把Sim Card状态保存到系统属性中
broadcastIccStateChangedIntent(mExternalState.getIntentString(), //粘性广播Sim card状态.
mExternalState.getReason());
// TODO: Need to notify registrants for other states as well.
if ( State.ABSENT == mExternalState) {
mAbsentRegistrants.notifyRegistrants();
}
}
Note: 可见有三种方式获得Sim Card状态
i) 通过IccCardProxy的getState() 可以获得Sim Card状态。
ii) 通过读取系统属性获得Sim Card状态: SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);
iii) 通过监听粘性广播TelephonyIntents.ACTION_SIM_STATE_CHANGED 来获得Sim Card状态。
粘性广播的意义在于持久保留,不会被系统删除,所有的receiver都能接受。无时间限制。
归纳总结:
Sim Lock产生过程:
PhoneApp通过IccCard注册监听 --> IccCard 收到Message, 通知登记者(Registrant) --> PhoneApp根据收到的Message显示相应界面
Sim Lock检验过程:
Sim Lock界面接受输入PIN --> IccCard检查PIN,并返回结果 --> Sim Lock界面收到Message,显示处理结果
待解决问题:
1. IccCardProxy是怎么获得相关Message通知的?
有人说IccCardProxy与RIL有关联,但是这关联不知体现在什么地方、什么方式上?
2. 获得相关Sim Lock PIN后,IccCardProxy是怎么匹配处理并返回结果的?
在supplyDepersonalization 中没发现。
3. 流程图