基本的思路是想在解鎖畫面的地方,緊鄰緊急電話按鈕的旁邊加上一個按鈕,用以解鎖,並且可以參考緊急電話的程序,來撥打上面提到的特殊電話號碼來解鎖。
依據這篇:Android中PIN和PUK碼解鎖研究的追蹤過程進行追蹤,可以知道:
- KeyguardViewMediator.java 的 onSimStateChanged() 裡有對 PUK_REQUIRED 做處理,dokeyguard()會顯示鎖定畫面,而dokeyguard()裡則是先檢查是不是被鎖住,是的話,就送訊息出去,表明該要顯示鎖定的畫面,送出去以後,handleShow()會收到並處理。
- handleShow()裡會先播放音效,然後呼叫mKeyguardViewManager.show(),這裡會去建View,並設置View相關Layout參數。從這邊可以追蹤到LockPatternKeyguardView.createLockScreen(),這個函數就直接回傳LockScreen,LockScreen是在frameworks/base/policy/src/com/android/internal/policy/impl/LockScreen.java。
- LockScreen則是去解析frameworks/base/core/res/res/layout 下的 keyguard_screen_tab_unlock 與 Keyguard_screen_tab_unlock_land 其中之一(依橫或直來決定)。裡面的emergencyCallButton有註解說在sim card為PUKd時,才顯示。至此,已經知道該改哪個畫面才可以多一個按鈕出來。
那麼多了按鈕之後,能否再帶一個畫面出來輸入PUK與PIN呢?
這邊繼續參考takeEmergency()的部分,takeEmergency()是直接送帶有ACTION_EMERGENCY_DIAL的Intent出去。ACTION_EMERGENCY_DIAL是一個字串’com.android.phone.EmergencyDialer.DIAL’,以這個字串去搜索,可以在packages/apps/Phone/src/com/android/phone/EmergencyDialer.java與Phone app的AndroidManifest.xml中找到,那麼這就表示是由Phone app在處理。
因此,決定仿效這樣的方法,在Settings app裡加上輸入PUK、PIN的畫面,並且在AndroidManifest.xml裡該畫面activity的intent filter裡加上客製的Intent字串。
Framework 層,則先在畫面加上新的按鈕,並且在按鈕的處理裡,仿效takeEmergency(),加上送出客製的Intent字串,這樣就可以串到Settings app的畫面去了。
程式都撰寫好之後,進行測試,首先遇到的問題是,按下按鈕以後,位於Settings app的畫面並沒有顯示出來,利用 adb logcat 進行追蹤,發現的確有送出 Intent,要求 Settings app 裡的 activity 啟動,可是畫面卻出不來,參考EmergencyDialer.java,發現需要在 onCreate() 裡加上 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED),這樣才可以在被鎖定時顯示出來。
第二個遇到的問題是,使用特殊的電話號碼去進行撥號,並沒有反應,也因此無法解鎖。這裡去搜索IccCard.java,發現有supplyPUK()函式,既然supplyPIN()是解鎖PIN,那麼supplyPUK()就應該是解鎖PUK。於是在畫面補上取得IccCard的必要程序,然後去試,這次根本連畫面都出不來了,參考 adb logcat,發現是 activity 啟動失敗,依據啟動失敗的錯誤訊息去搜索,發現是需要為activity加上android:process屬性,於是在 Settings app AndroidManifest.xml 新增的Activity tag上加上android:process=”com.android.phone”,就可以順利啟動並解鎖了。