KeyguardSimPukView.java revision 3af630c8d18bcf4b23a5a308917319dd04cc8ed2
1/* 2 * Copyright (C) 2012 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 */ 16package com.android.internal.policy.impl.keyguard; 17 18import android.app.Activity; 19import android.app.Dialog; 20import android.app.ProgressDialog; 21import android.content.Context; 22import android.content.res.Configuration; 23import android.graphics.Rect; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.text.Editable; 27import android.util.AttributeSet; 28import android.util.Log; 29import android.view.KeyEvent; 30import android.view.MotionEvent; 31import android.view.View; 32import android.view.WindowManager; 33import android.view.inputmethod.EditorInfo; 34import android.widget.LinearLayout; 35import android.widget.TextView; 36import android.widget.TextView.OnEditorActionListener; 37 38import com.android.internal.telephony.ITelephony; 39import com.android.internal.widget.LockPatternUtils; 40import com.android.internal.widget.PasswordEntryKeyboardHelper; 41import com.android.internal.widget.PasswordEntryKeyboardView; 42import com.android.internal.R; 43 44public class KeyguardSimPukView extends LinearLayout implements View.OnClickListener, 45 View.OnFocusChangeListener, KeyguardSecurityView, OnEditorActionListener { 46 47 private static final int DIGIT_PRESS_WAKE_MILLIS = 5000; 48 49 private TextView mPukText; 50 private TextView mPinText; 51 private TextView mFocusedEntry; 52 53 private View mDelPukButton; 54 private View mDelPinButton; 55 56 private ProgressDialog mSimUnlockProgressDialog = null; 57 private KeyguardSecurityCallback mCallback; 58 59 private KeyguardNavigationManager mNavigationManager; 60 61 private PasswordEntryKeyboardView mKeyboardView; 62 63 private PasswordEntryKeyboardHelper mKeyboardHelper; 64 65 private LockPatternUtils mLockPatternUtils; 66 67 private volatile boolean mCheckInProgress; 68 69 public KeyguardSimPukView(Context context) { 70 this(context, null); 71 } 72 73 public KeyguardSimPukView(Context context, AttributeSet attrs) { 74 super(context, attrs); 75 mLockPatternUtils = new LockPatternUtils(getContext()); 76 } 77 78 public void setKeyguardCallback(KeyguardSecurityCallback callback) { 79 mCallback = callback; 80 mLockPatternUtils = new LockPatternUtils(getContext()); 81 } 82 83 @Override 84 protected void onFinishInflate() { 85 super.onFinishInflate(); 86 87 mNavigationManager = new KeyguardNavigationManager(this); 88 89 mPukText = (TextView) findViewById(R.id.sim_puk_entry); 90 mPukText.setOnEditorActionListener(this); 91 mPinText = (TextView) findViewById(R.id.sim_pin_entry); 92 mPinText.setOnEditorActionListener(this); 93 mDelPukButton = findViewById(R.id.puk_delete_button); 94 mDelPukButton.setOnClickListener(this); 95 mDelPinButton = findViewById(R.id.pin_delete_button); 96 mDelPinButton.setOnClickListener(this); 97 98 mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); 99 mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false, 100 new int[] { 101 R.xml.kg_password_kbd_numeric, 102 com.android.internal.R.xml.password_kbd_qwerty, 103 com.android.internal.R.xml.password_kbd_qwerty_shifted, 104 com.android.internal.R.xml.password_kbd_symbols, 105 com.android.internal.R.xml.password_kbd_symbols_shift 106 }); 107 mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); 108 mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled()); 109 110 mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint); 111 112 mPinText.setFocusableInTouchMode(true); 113 mPinText.setOnFocusChangeListener(this); 114 mPukText.setFocusableInTouchMode(true); 115 mPukText.setOnFocusChangeListener(this); 116 117 setFocusableInTouchMode(true); 118 119 reset(); 120 } 121 122 @Override 123 protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 124 return mPukText.requestFocus(direction, previouslyFocusedRect); 125 } 126 127 public boolean needsInput() { 128 return false; // This view provides its own keypad 129 } 130 131 public void onPause() { 132 133 } 134 135 public void onResume() { 136 reset(); 137 } 138 139 /** {@inheritDoc} */ 140 public void cleanUp() { 141 // dismiss the dialog. 142 if (mSimUnlockProgressDialog != null) { 143 mSimUnlockProgressDialog.dismiss(); 144 mSimUnlockProgressDialog = null; 145 } 146 } 147 148 /** 149 * Since the IPC can block, we want to run the request in a separate thread 150 * with a callback. 151 */ 152 private abstract class CheckSimPuk extends Thread { 153 154 private final String mPin, mPuk; 155 156 protected CheckSimPuk(String puk, String pin) { 157 mPuk = puk; 158 mPin = pin; 159 } 160 161 abstract void onSimLockChangedResponse(boolean success); 162 163 @Override 164 public void run() { 165 try { 166 final boolean result = ITelephony.Stub.asInterface(ServiceManager 167 .checkService("phone")).supplyPuk(mPuk, mPin); 168 169 post(new Runnable() { 170 public void run() { 171 onSimLockChangedResponse(result); 172 } 173 }); 174 } catch (RemoteException e) { 175 post(new Runnable() { 176 public void run() { 177 onSimLockChangedResponse(false); 178 } 179 }); 180 } 181 } 182 } 183 184 public void onClick(View v) { 185 if (v == mDelPukButton) { 186 if (mFocusedEntry != mPukText) 187 mPukText.requestFocus(); 188 final Editable digits = mPukText.getEditableText(); 189 final int len = digits.length(); 190 if (len > 0) { 191 digits.delete(len-1, len); 192 } 193 } else if (v == mDelPinButton) { 194 if (mFocusedEntry != mPinText) 195 mPinText.requestFocus(); 196 final Editable digits = mPinText.getEditableText(); 197 final int len = digits.length(); 198 if (len > 0) { 199 digits.delete(len-1, len); 200 } 201 } 202 mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS); 203 } 204 205 @Override 206 public void onFocusChange(View view, boolean hasFocus) { 207 if (hasFocus) 208 mFocusedEntry = (TextView) view; 209 } 210 211 private Dialog getSimUnlockProgressDialog() { 212 if (mSimUnlockProgressDialog == null) { 213 mSimUnlockProgressDialog = new ProgressDialog(mContext); 214 mSimUnlockProgressDialog.setMessage(mContext.getString( 215 R.string.kg_sim_unlock_progress_dialog_message)); 216 mSimUnlockProgressDialog.setIndeterminate(true); 217 mSimUnlockProgressDialog.setCancelable(false); 218 if (!(mContext instanceof Activity)) { 219 mSimUnlockProgressDialog.getWindow().setType( 220 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 221 } 222 } 223 return mSimUnlockProgressDialog; 224 } 225 226 private void checkPuk() { 227 // make sure the puk is at least 8 digits long. 228 if (mPukText.getText().length() < 8) { 229 // otherwise, display a message to the user, and don't submit. 230 mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint); 231 mPukText.setText(""); 232 return; 233 } 234 235 // make sure the PIN is between 4 and 8 digits 236 if (mPinText.getText().length() < 4 237 || mPinText.getText().length() > 8) { 238 // otherwise, display a message to the user, and don't submit. 239 mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint); 240 mPinText.setText(""); 241 return; 242 } 243 244 getSimUnlockProgressDialog().show(); 245 246 if (!mCheckInProgress) { 247 mCheckInProgress = true; 248 new CheckSimPuk(mPukText.getText().toString(), 249 mPinText.getText().toString()) { 250 void onSimLockChangedResponse(final boolean success) { 251 mPinText.post(new Runnable() { 252 public void run() { 253 if (mSimUnlockProgressDialog != null) { 254 mSimUnlockProgressDialog.hide(); 255 } 256 if (success) { 257 mCallback.dismiss(true); 258 } else { 259 mNavigationManager.setMessage(R.string.kg_invalid_puk); 260 mPukText.setText(""); 261 mPinText.setText(""); 262 } 263 mCheckInProgress = false; 264 } 265 }); 266 } 267 }.start(); 268 } 269 } 270 271 @Override 272 public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { 273 // Check if this was the result of hitting the enter key 274 mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS); 275 if (event.getAction() == MotionEvent.ACTION_DOWN) { 276 if (actionId == EditorInfo.IME_NULL 277 || actionId == EditorInfo.IME_ACTION_DONE 278 || actionId == EditorInfo.IME_ACTION_NEXT) { 279 if (view == mPukText && mPukText.getText().length() < 8) { 280 mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint); 281 mPukText.setText(""); 282 mPukText.requestFocus(); 283 return true; 284 } else if (view == mPinText) { 285 if (mPinText.getText().length() < 4 || mPinText.getText().length() > 8) { 286 mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint); 287 mPinText.setText(""); 288 mPinText.requestFocus(); 289 } else { 290 checkPuk(); 291 } 292 return true; 293 } 294 } 295 } 296 return false; 297 } 298 299 @Override 300 public void setLockPatternUtils(LockPatternUtils utils) { 301 mLockPatternUtils = utils; 302 } 303 304 @Override 305 public void reset() { 306 mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint); 307 mPinText.setText(""); 308 mPukText.setText(""); 309 mPukText.requestFocus(); 310 } 311 312 @Override 313 public KeyguardSecurityCallback getCallback() { 314 return mCallback; 315 } 316 317} 318