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