• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.policy.impl;
18 
19 import android.app.Dialog;
20 import android.app.ProgressDialog;
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 
26 import com.android.internal.telephony.ITelephony;
27 import com.android.internal.widget.LockPatternUtils;
28 
29 import android.text.Editable;
30 import android.util.Log;
31 import android.view.KeyEvent;
32 import android.view.LayoutInflater;
33 import android.view.View;
34 import android.view.WindowManager;
35 import android.widget.Button;
36 import android.widget.LinearLayout;
37 import android.widget.TextView;
38 import com.android.internal.R;
39 
40 /**
41  * Displays a dialer like interface to unlock the SIM PUK.
42  */
43 public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
44         View.OnClickListener, View.OnFocusChangeListener {
45 
46     private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
47 
48     private final KeyguardUpdateMonitor mUpdateMonitor;
49     private final KeyguardScreenCallback mCallback;
50     private KeyguardStatusViewManager mKeyguardStatusViewManager;
51 
52     private TextView mHeaderText;
53     private TextView mPukText;
54     private TextView mPinText;
55     private TextView mFocusedEntry;
56 
57     private View mOkButton;
58     private View mDelPukButton;
59     private View mDelPinButton;
60 
61     private ProgressDialog mSimUnlockProgressDialog = null;
62 
63     private LockPatternUtils mLockPatternUtils;
64 
65     private int mCreationOrientation;
66 
67     private int mKeyboardHidden;
68 
69     private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
70 
SimPukUnlockScreen(Context context, Configuration configuration, KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback, LockPatternUtils lockpatternutils)71     public SimPukUnlockScreen(Context context, Configuration configuration,
72             KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
73             LockPatternUtils lockpatternutils) {
74         super(context);
75         mUpdateMonitor = updateMonitor;
76         mCallback = callback;;
77 
78         mCreationOrientation = configuration.orientation;
79         mKeyboardHidden = configuration.hardKeyboardHidden;
80         mLockPatternUtils = lockpatternutils;
81 
82         LayoutInflater inflater = LayoutInflater.from(context);
83         if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
84             inflater.inflate(
85                     R.layout.keyguard_screen_sim_puk_landscape, this, true);
86         } else {
87             inflater.inflate(
88                     R.layout.keyguard_screen_sim_puk_portrait, this, true);
89             new TouchInput();
90         }
91 
92         mHeaderText = (TextView) findViewById(R.id.headerText);
93 
94         mPukText = (TextView) findViewById(R.id.pukDisplay);
95         mPinText = (TextView) findViewById(R.id.pinDisplay);
96         mDelPukButton = findViewById(R.id.pukDel);
97         mDelPinButton = findViewById(R.id.pinDel);
98         mOkButton = findViewById(R.id.ok);
99 
100         mDelPinButton.setOnClickListener(this);
101         mDelPukButton.setOnClickListener(this);
102         mOkButton.setOnClickListener(this);
103 
104         mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
105         // To make marquee work
106         mHeaderText.setSelected(true);
107 
108         mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
109                 lockpatternutils, callback, true);
110 
111         mPinText.setFocusableInTouchMode(true);
112         mPinText.setOnFocusChangeListener(this);
113         mPukText.setFocusableInTouchMode(true);
114         mPukText.setOnFocusChangeListener(this);
115     }
116 
117     /** {@inheritDoc} */
needsInput()118     public boolean needsInput() {
119         return false;
120     }
121 
122     /** {@inheritDoc} */
onPause()123     public void onPause() {
124         mKeyguardStatusViewManager.onPause();
125     }
126 
127     /** {@inheritDoc} */
onResume()128     public void onResume() {
129         // start fresh
130         mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
131         mKeyguardStatusViewManager.onResume();
132     }
133 
134     /** {@inheritDoc} */
cleanUp()135     public void cleanUp() {
136         // dismiss the dialog.
137         if (mSimUnlockProgressDialog != null) {
138             mSimUnlockProgressDialog.dismiss();
139             mSimUnlockProgressDialog = null;
140         }
141         mUpdateMonitor.removeCallback(this);
142     }
143 
144 
145     /**
146      * Since the IPC can block, we want to run the request in a separate thread
147      * with a callback.
148      */
149     private abstract class CheckSimPuk extends Thread {
150 
151         private final String mPin, mPuk;
152 
CheckSimPuk(String puk, String pin)153         protected CheckSimPuk(String puk, String pin) {
154             mPuk = puk;
155             mPin = pin;
156         }
157 
onSimLockChangedResponse(boolean success)158         abstract void onSimLockChangedResponse(boolean success);
159 
160         @Override
run()161         public void run() {
162             try {
163                 final boolean result = ITelephony.Stub.asInterface(ServiceManager
164                         .checkService("phone")).supplyPuk(mPuk, mPin);
165 
166                 post(new Runnable() {
167                     public void run() {
168                         onSimLockChangedResponse(result);
169                     }
170                 });
171             } catch (RemoteException e) {
172                 post(new Runnable() {
173                     public void run() {
174                         onSimLockChangedResponse(false);
175                     }
176                 });
177             }
178         }
179     }
180 
onClick(View v)181     public void onClick(View v) {
182         if (v == mDelPukButton) {
183             if (mFocusedEntry != mPukText)
184                 mPukText.requestFocus();
185             final Editable digits = mPukText.getEditableText();
186             final int len = digits.length();
187             if (len > 0) {
188                 digits.delete(len-1, len);
189             }
190         } else if (v == mDelPinButton) {
191             if (mFocusedEntry != mPinText)
192                 mPinText.requestFocus();
193             final Editable digits = mPinText.getEditableText();
194             final int len = digits.length();
195             if (len > 0) {
196                 digits.delete(len-1, len);
197             }
198         } else if (v == mOkButton) {
199             checkPuk();
200         }
201         mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
202 
203     }
204 
205     @Override
onFocusChange(View v, boolean hasFocus)206     public void onFocusChange(View v, boolean hasFocus) {
207         if (hasFocus)
208             mFocusedEntry = (TextView)v;
209     }
210 
getSimUnlockProgressDialog()211     private Dialog getSimUnlockProgressDialog() {
212         if (mSimUnlockProgressDialog == null) {
213             mSimUnlockProgressDialog = new ProgressDialog(mContext);
214             mSimUnlockProgressDialog.setMessage(
215                     mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
216             mSimUnlockProgressDialog.setIndeterminate(true);
217             mSimUnlockProgressDialog.setCancelable(false);
218             mSimUnlockProgressDialog.getWindow().setType(
219                     WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
220         }
221         return mSimUnlockProgressDialog;
222     }
223 
checkPuk()224     private void checkPuk() {
225         // make sure that the puk is at least 8 digits long.
226         if (mPukText.getText().length() < 8) {
227             // otherwise, display a message to the user, and don't submit.
228             mHeaderText.setText(R.string.invalidPuk);
229             mPukText.setText("");
230             return;
231         }
232 
233         if (mPinText.getText().length() < 4
234                 || mPinText.getText().length() > 8) {
235             // otherwise, display a message to the user, and don't submit.
236             mHeaderText.setText(R.string.invalidPin);
237             mPinText.setText("");
238             return;
239         }
240 
241         getSimUnlockProgressDialog().show();
242 
243         new CheckSimPuk(mPukText.getText().toString(),
244                 mPinText.getText().toString()) {
245             void onSimLockChangedResponse(final boolean success) {
246                 mPinText.post(new Runnable() {
247                     public void run() {
248                         if (mSimUnlockProgressDialog != null) {
249                             mSimUnlockProgressDialog.hide();
250                         }
251                         if (success) {
252                             // before closing the keyguard, report back that
253                             // the sim is unlocked so it knows right away
254                             mUpdateMonitor.reportSimUnlocked();
255                             mCallback.goToUnlockScreen();
256                         } else {
257                             mHeaderText.setText(R.string.badPuk);
258                             mPukText.setText("");
259                             mPinText.setText("");
260                         }
261                     }
262                 });
263             }
264         }.start();
265     }
266 
267 
onKeyDown(int keyCode, KeyEvent event)268     public boolean onKeyDown(int keyCode, KeyEvent event) {
269         if (keyCode == KeyEvent.KEYCODE_BACK) {
270             mCallback.goToLockScreen();
271             return true;
272         }
273         final char match = event.getMatch(DIGITS);
274         if (match != 0) {
275             reportDigit(match - '0');
276             return true;
277         }
278         if (keyCode == KeyEvent.KEYCODE_DEL) {
279             mFocusedEntry.onKeyDown(keyCode, event);
280             final Editable digits = mFocusedEntry.getEditableText();
281             final int len = digits.length();
282             if (len > 0) {
283                 digits.delete(len-1, len);
284             }
285             mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
286             return true;
287         }
288 
289         if (keyCode == KeyEvent.KEYCODE_ENTER) {
290             checkPuk();
291             return true;
292         }
293 
294         return false;
295     }
296 
reportDigit(int digit)297     private void reportDigit(int digit) {
298         mFocusedEntry.append(Integer.toString(digit));
299     }
300 
updateConfiguration()301     void updateConfiguration() {
302         Configuration newConfig = getResources().getConfiguration();
303         if (newConfig.orientation != mCreationOrientation) {
304             mCallback.recreateMe(newConfig);
305         } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
306             mKeyboardHidden = newConfig.hardKeyboardHidden;
307         }
308 
309     }
310 
311     @Override
onAttachedToWindow()312     protected void onAttachedToWindow() {
313         super.onAttachedToWindow();
314         updateConfiguration();
315     }
316 
317     /** {@inheritDoc} */
318     @Override
onConfigurationChanged(Configuration newConfig)319     protected void onConfigurationChanged(Configuration newConfig) {
320         super.onConfigurationChanged(newConfig);
321         updateConfiguration();
322     }
323 
324     /**
325      * Helper class to handle input from touch dialer.  Only relevant when
326      * the keyboard is shut.
327      */
328     private class TouchInput implements View.OnClickListener {
329         private TextView mZero;
330         private TextView mOne;
331         private TextView mTwo;
332         private TextView mThree;
333         private TextView mFour;
334         private TextView mFive;
335         private TextView mSix;
336         private TextView mSeven;
337         private TextView mEight;
338         private TextView mNine;
339         private TextView mCancelButton;
340 
TouchInput()341         private TouchInput() {
342             mZero = (TextView) findViewById(R.id.zero);
343             mOne = (TextView) findViewById(R.id.one);
344             mTwo = (TextView) findViewById(R.id.two);
345             mThree = (TextView) findViewById(R.id.three);
346             mFour = (TextView) findViewById(R.id.four);
347             mFive = (TextView) findViewById(R.id.five);
348             mSix = (TextView) findViewById(R.id.six);
349             mSeven = (TextView) findViewById(R.id.seven);
350             mEight = (TextView) findViewById(R.id.eight);
351             mNine = (TextView) findViewById(R.id.nine);
352             mCancelButton = (TextView) findViewById(R.id.cancel);
353 
354             mZero.setText("0");
355             mOne.setText("1");
356             mTwo.setText("2");
357             mThree.setText("3");
358             mFour.setText("4");
359             mFive.setText("5");
360             mSix.setText("6");
361             mSeven.setText("7");
362             mEight.setText("8");
363             mNine.setText("9");
364 
365             mZero.setOnClickListener(this);
366             mOne.setOnClickListener(this);
367             mTwo.setOnClickListener(this);
368             mThree.setOnClickListener(this);
369             mFour.setOnClickListener(this);
370             mFive.setOnClickListener(this);
371             mSix.setOnClickListener(this);
372             mSeven.setOnClickListener(this);
373             mEight.setOnClickListener(this);
374             mNine.setOnClickListener(this);
375             mCancelButton.setOnClickListener(this);
376         }
377 
378 
onClick(View v)379         public void onClick(View v) {
380             if (v == mCancelButton) {
381                 // clear the PIN/PUK entry fields if the user cancels
382                 mPinText.setText("");
383                 mPukText.setText("");
384                 mCallback.goToLockScreen();
385                 return;
386             }
387 
388             final int digit = checkDigit(v);
389             if (digit >= 0) {
390                 mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
391                 reportDigit(digit);
392             }
393         }
394 
checkDigit(View v)395         private int checkDigit(View v) {
396             int digit = -1;
397             if (v == mZero) {
398                 digit = 0;
399             } else if (v == mOne) {
400                 digit = 1;
401             } else if (v == mTwo) {
402                 digit = 2;
403             } else if (v == mThree) {
404                 digit = 3;
405             } else if (v == mFour) {
406                 digit = 4;
407             } else if (v == mFive) {
408                 digit = 5;
409             } else if (v == mSix) {
410                 digit = 6;
411             } else if (v == mSeven) {
412                 digit = 7;
413             } else if (v == mEight) {
414                 digit = 8;
415             } else if (v == mNine) {
416                 digit = 9;
417             }
418             return digit;
419         }
420     }
421 
422 }
423