Home | History | Annotate | Download | only in keyguard
      1 /*
      2  * Copyright (C) 2014 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.keyguard;
     18 
     19 import android.content.Context;
     20 import android.graphics.Rect;
     21 import android.util.AttributeSet;
     22 import android.view.KeyEvent;
     23 import android.view.MotionEvent;
     24 import android.view.View;
     25 
     26 /**
     27  * A Pin based Keyguard input view
     28  */
     29 public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
     30         implements View.OnKeyListener, View.OnTouchListener {
     31 
     32     protected PasswordTextView mPasswordEntry;
     33     private View mOkButton;
     34     private View mDeleteButton;
     35     private View mButton0;
     36     private View mButton1;
     37     private View mButton2;
     38     private View mButton3;
     39     private View mButton4;
     40     private View mButton5;
     41     private View mButton6;
     42     private View mButton7;
     43     private View mButton8;
     44     private View mButton9;
     45 
     46     public KeyguardPinBasedInputView(Context context) {
     47         this(context, null);
     48     }
     49 
     50     public KeyguardPinBasedInputView(Context context, AttributeSet attrs) {
     51         super(context, attrs);
     52     }
     53 
     54     @Override
     55     public void reset() {
     56         mPasswordEntry.requestFocus();
     57         super.reset();
     58     }
     59 
     60     @Override
     61     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
     62         // send focus to the password field
     63         return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
     64     }
     65 
     66     @Override
     67     protected void resetState() {
     68         setPasswordEntryEnabled(true);
     69     }
     70 
     71     @Override
     72     protected void setPasswordEntryEnabled(boolean enabled) {
     73         mPasswordEntry.setEnabled(enabled);
     74         mOkButton.setEnabled(enabled);
     75     }
     76 
     77     @Override
     78     protected void setPasswordEntryInputEnabled(boolean enabled) {
     79         mPasswordEntry.setEnabled(enabled);
     80         mOkButton.setEnabled(enabled);
     81     }
     82 
     83     @Override
     84     public boolean onKeyDown(int keyCode, KeyEvent event) {
     85         if (KeyEvent.isConfirmKey(keyCode)) {
     86             performClick(mOkButton);
     87             return true;
     88         } else if (keyCode == KeyEvent.KEYCODE_DEL) {
     89             performClick(mDeleteButton);
     90             return true;
     91         }
     92         if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
     93             int number = keyCode - KeyEvent.KEYCODE_0;
     94             performNumberClick(number);
     95             return true;
     96         }
     97         if (keyCode >= KeyEvent.KEYCODE_NUMPAD_0 && keyCode <= KeyEvent.KEYCODE_NUMPAD_9) {
     98             int number = keyCode - KeyEvent.KEYCODE_NUMPAD_0;
     99             performNumberClick(number);
    100             return true;
    101         }
    102         return super.onKeyDown(keyCode, event);
    103     }
    104 
    105     @Override
    106     protected int getPromtReasonStringRes(int reason) {
    107         switch (reason) {
    108             case PROMPT_REASON_RESTART:
    109                 return R.string.kg_prompt_reason_restart_pin;
    110             case PROMPT_REASON_TIMEOUT:
    111                 return R.string.kg_prompt_reason_timeout_pin;
    112             case PROMPT_REASON_DEVICE_ADMIN:
    113                 return R.string.kg_prompt_reason_device_admin;
    114             case PROMPT_REASON_USER_REQUEST:
    115                 return R.string.kg_prompt_reason_user_request;
    116             case PROMPT_REASON_NONE:
    117                 return 0;
    118             default:
    119                 return R.string.kg_prompt_reason_timeout_pin;
    120         }
    121     }
    122 
    123     private void performClick(View view) {
    124         view.performClick();
    125     }
    126 
    127     private void performNumberClick(int number) {
    128         switch (number) {
    129             case 0:
    130                 performClick(mButton0);
    131                 break;
    132             case 1:
    133                 performClick(mButton1);
    134                 break;
    135             case 2:
    136                 performClick(mButton2);
    137                 break;
    138             case 3:
    139                 performClick(mButton3);
    140                 break;
    141             case 4:
    142                 performClick(mButton4);
    143                 break;
    144             case 5:
    145                 performClick(mButton5);
    146                 break;
    147             case 6:
    148                 performClick(mButton6);
    149                 break;
    150             case 7:
    151                 performClick(mButton7);
    152                 break;
    153             case 8:
    154                 performClick(mButton8);
    155                 break;
    156             case 9:
    157                 performClick(mButton9);
    158                 break;
    159         }
    160     }
    161 
    162     @Override
    163     protected void resetPasswordText(boolean animate, boolean announce) {
    164         mPasswordEntry.reset(animate, announce);
    165     }
    166 
    167     @Override
    168     protected String getPasswordText() {
    169         return mPasswordEntry.getText();
    170     }
    171 
    172     @Override
    173     protected void onFinishInflate() {
    174         mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
    175         mPasswordEntry.setOnKeyListener(this);
    176 
    177         // Set selected property on so the view can send accessibility events.
    178         mPasswordEntry.setSelected(true);
    179 
    180         mPasswordEntry.setUserActivityListener(new PasswordTextView.UserActivityListener() {
    181             @Override
    182             public void onUserActivity() {
    183                 onUserInput();
    184             }
    185         });
    186 
    187         mOkButton = findViewById(R.id.key_enter);
    188         if (mOkButton != null) {
    189             mOkButton.setOnTouchListener(this);
    190             mOkButton.setOnClickListener(new View.OnClickListener() {
    191                 @Override
    192                 public void onClick(View v) {
    193                     if (mPasswordEntry.isEnabled()) {
    194                         verifyPasswordAndUnlock();
    195                     }
    196                 }
    197             });
    198             mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
    199         }
    200 
    201         mDeleteButton = findViewById(R.id.delete_button);
    202         mDeleteButton.setVisibility(View.VISIBLE);
    203         mDeleteButton.setOnTouchListener(this);
    204         mDeleteButton.setOnClickListener(new OnClickListener() {
    205             @Override
    206             public void onClick(View v) {
    207                 // check for time-based lockouts
    208                 if (mPasswordEntry.isEnabled()) {
    209                     mPasswordEntry.deleteLastChar();
    210                 }
    211             }
    212         });
    213         mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
    214             @Override
    215             public boolean onLongClick(View v) {
    216                 // check for time-based lockouts
    217                 if (mPasswordEntry.isEnabled()) {
    218                     resetPasswordText(true /* animate */, true /* announce */);
    219                 }
    220                 doHapticKeyClick();
    221                 return true;
    222             }
    223         });
    224 
    225         mButton0 = findViewById(R.id.key0);
    226         mButton1 = findViewById(R.id.key1);
    227         mButton2 = findViewById(R.id.key2);
    228         mButton3 = findViewById(R.id.key3);
    229         mButton4 = findViewById(R.id.key4);
    230         mButton5 = findViewById(R.id.key5);
    231         mButton6 = findViewById(R.id.key6);
    232         mButton7 = findViewById(R.id.key7);
    233         mButton8 = findViewById(R.id.key8);
    234         mButton9 = findViewById(R.id.key9);
    235 
    236         mPasswordEntry.requestFocus();
    237         super.onFinishInflate();
    238     }
    239 
    240     @Override
    241     public boolean onTouch(View v, MotionEvent event) {
    242         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
    243             doHapticKeyClick();
    244         }
    245         return false;
    246     }
    247 
    248     @Override
    249     public boolean onKey(View v, int keyCode, KeyEvent event) {
    250         if (event.getAction() == KeyEvent.ACTION_DOWN) {
    251             return onKeyDown(keyCode, event);
    252         }
    253         return false;
    254     }
    255 }
    256