1 /* 2 * Copyright (C) 2013 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.app; 18 19 import android.content.Context; 20 import android.os.Bundle; 21 import android.os.UserManager; 22 import android.text.Editable; 23 import android.text.TextWatcher; 24 import android.view.KeyEvent; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.View.OnClickListener; 28 import android.widget.Button; 29 import android.widget.EditText; 30 import android.widget.TextView; 31 import android.widget.TextView.OnEditorActionListener; 32 33 import com.android.internal.R; 34 35 /** 36 * This activity is launched by Settings and other apps to either create a new PIN or 37 * challenge for an existing PIN. The PIN is maintained by UserManager. 38 */ 39 public class RestrictionsPinActivity extends AlertActivity 40 implements OnClickListener, TextWatcher, OnEditorActionListener { 41 42 protected UserManager mUserManager; 43 protected boolean mHasRestrictionsPin; 44 45 protected EditText mPinText; 46 protected TextView mPinErrorMessage; 47 private Button mOkButton; 48 private Button mCancelButton; 49 50 @Override 51 public void onCreate(Bundle icicle) { 52 super.onCreate(icicle); 53 54 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); 55 mHasRestrictionsPin = mUserManager.hasRestrictionsChallenge(); 56 initUi(); 57 setupAlert(); 58 } 59 60 protected void initUi() { 61 AlertController.AlertParams ap = mAlertParams; 62 ap.mTitle = getString(R.string.restr_pin_enter_admin_pin); 63 LayoutInflater inflater = 64 (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 65 ap.mView = inflater.inflate(R.layout.restrictions_pin_challenge, null); 66 67 mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message); 68 mPinText = (EditText) ap.mView.findViewById(R.id.pin_text); 69 mOkButton = (Button) ap.mView.findViewById(R.id.pin_ok_button); 70 mCancelButton = (Button) ap.mView.findViewById(R.id.pin_cancel_button); 71 72 mPinText.addTextChangedListener(this); 73 74 mOkButton.setOnClickListener(this); 75 mCancelButton.setOnClickListener(this); 76 } 77 78 protected boolean verifyingPin() { 79 return true; 80 } 81 82 public void onResume() { 83 super.onResume(); 84 85 setPositiveButtonState(false); 86 boolean hasPin = mUserManager.hasRestrictionsChallenge(); 87 if (hasPin) { 88 mPinErrorMessage.setVisibility(View.INVISIBLE); 89 mPinText.setOnEditorActionListener(this); 90 updatePinTimer(-1); 91 } else if (verifyingPin()) { 92 setResult(RESULT_OK); 93 finish(); 94 } 95 } 96 97 protected void setPositiveButtonState(boolean enabled) { 98 mOkButton.setEnabled(enabled); 99 } 100 101 private boolean updatePinTimer(int pinTimerMs) { 102 if (pinTimerMs < 0) { 103 pinTimerMs = mUserManager.checkRestrictionsChallenge(null); 104 } 105 boolean enableInput; 106 if (pinTimerMs >= 200) { 107 // Do the count down timer for less than a minute, otherwise just say try again later. 108 if (pinTimerMs <= 60000) { 109 final int seconds = (pinTimerMs + 200) / 1000; 110 final String formatString = getResources().getQuantityString( 111 R.plurals.restr_pin_countdown, 112 seconds); 113 mPinErrorMessage.setText(String.format(formatString, seconds)); 114 } else { 115 mPinErrorMessage.setText(R.string.restr_pin_try_later); 116 } 117 enableInput = false; 118 mPinErrorMessage.setVisibility(View.VISIBLE); 119 mPinText.setText(""); 120 mPinText.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs)); 121 } else { 122 enableInput = true; 123 mPinErrorMessage.setText(R.string.restr_pin_incorrect); 124 } 125 mPinText.setEnabled(enableInput); 126 setPositiveButtonState(enableInput); 127 return enableInput; 128 } 129 130 protected void performPositiveButtonAction() { 131 int result = mUserManager.checkRestrictionsChallenge(mPinText.getText().toString()); 132 if (result == UserManager.PIN_VERIFICATION_SUCCESS) { 133 setResult(RESULT_OK); 134 finish(); 135 } else if (result >= 0) { 136 mPinErrorMessage.setText(R.string.restr_pin_incorrect); 137 mPinErrorMessage.setVisibility(View.VISIBLE); 138 updatePinTimer(result); 139 mPinText.setText(""); 140 } 141 } 142 143 @Override 144 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 145 } 146 147 @Override 148 public void onTextChanged(CharSequence s, int start, int before, int count) { 149 CharSequence pin = mPinText.getText(); 150 setPositiveButtonState(pin != null && pin.length() >= 4); 151 } 152 153 @Override 154 public void afterTextChanged(Editable s) { 155 } 156 157 @Override 158 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 159 performPositiveButtonAction(); 160 return true; 161 } 162 163 private Runnable mCountdownRunnable = new Runnable() { 164 public void run() { 165 if (updatePinTimer(-1)) { 166 // If we are no longer counting down, clear the message. 167 mPinErrorMessage.setVisibility(View.INVISIBLE); 168 } 169 } 170 }; 171 172 @Override 173 public void onClick(View v) { 174 if (v == mOkButton) { 175 performPositiveButtonAction(); 176 } else if (v == mCancelButton) { 177 setResult(RESULT_CANCELED); 178 finish(); 179 } 180 } 181 } 182