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