Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2018 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.car.settings.security;
     18 
     19 import android.content.Context;
     20 import android.os.Bundle;
     21 import android.os.UserHandle;
     22 import android.view.View;
     23 import android.widget.TextView;
     24 
     25 import com.android.car.settings.R;
     26 import com.android.car.settings.common.BaseFragment;
     27 import com.android.internal.widget.LockPatternUtils;
     28 import com.android.internal.widget.LockPatternView;
     29 
     30 import java.util.List;
     31 
     32 /**
     33  * Fragment for confirming existing lock pattern
     34  */
     35 public class ConfirmLockPatternFragment extends BaseFragment {
     36 
     37     private static final String FRAGMENT_TAG_CHECK_LOCK_WORKER = "check_lock_worker";
     38     // Time we wait before clearing a wrong pattern and the error message.
     39     private static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 2500L;
     40 
     41     private LockPatternView mLockPatternView;
     42     private TextView mMsgView;
     43 
     44     private LockPatternUtils mLockPatternUtils;
     45     private CheckLockWorker mCheckLockWorker;
     46     private CheckLockListener mCheckLockListener;
     47 
     48     private int mUserId;
     49     private List<LockPatternView.Cell> mPattern;
     50 
     51     /**
     52      * Factory method for creating ConfirmLockPatternFragment
     53      */
     54     public static ConfirmLockPatternFragment newInstance() {
     55         ConfirmLockPatternFragment patternFragment = new ConfirmLockPatternFragment();
     56         Bundle bundle = BaseFragment.getBundle();
     57         bundle.putInt(EXTRA_TITLE_ID, R.string.security_settings_title);
     58         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
     59         bundle.putInt(EXTRA_LAYOUT, R.layout.confirm_lock_pattern_fragment);
     60         patternFragment.setArguments(bundle);
     61         return patternFragment;
     62     }
     63 
     64     @Override
     65     public void onAttach(Context context) {
     66         super.onAttach(context);
     67         if ((getActivity() instanceof CheckLockListener)) {
     68             mCheckLockListener = (CheckLockListener) getActivity();
     69         } else {
     70             throw new RuntimeException("The activity must implement CheckLockListener");
     71         }
     72     }
     73 
     74     @Override
     75     public void onCreate(Bundle savedInstanceState) {
     76         super.onCreate(savedInstanceState);
     77         mLockPatternUtils = new LockPatternUtils(getContext());
     78         mUserId = UserHandle.myUserId();
     79     }
     80 
     81     @Override
     82     public void onViewCreated(View view, Bundle savedInstanceState) {
     83         super.onViewCreated(view, savedInstanceState);
     84 
     85         mMsgView = (TextView) view.findViewById(R.id.message);
     86         mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
     87         mLockPatternView.setFadePattern(false);
     88         mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(mUserId));
     89         mLockPatternView.setOnPatternListener(mLockPatternListener);
     90 
     91         if (savedInstanceState != null) {
     92             mCheckLockWorker = (CheckLockWorker) getFragmentManager().findFragmentByTag(
     93                     FRAGMENT_TAG_CHECK_LOCK_WORKER);
     94         }
     95     }
     96 
     97     @Override
     98     public void onStart() {
     99         super.onStart();
    100         if (mCheckLockWorker != null) {
    101             mCheckLockWorker.setListener(this::onCheckCompleted);
    102         }
    103     }
    104 
    105     @Override
    106     public void onStop() {
    107         super.onStop();
    108         if (mCheckLockWorker != null) {
    109             mCheckLockWorker.setListener(null);
    110         }
    111     }
    112 
    113     private Runnable mClearErrorRunnable = () ->  {
    114         mLockPatternView.clearPattern();
    115         mMsgView.setText("");
    116     };
    117 
    118     private LockPatternView.OnPatternListener mLockPatternListener =
    119             new LockPatternView.OnPatternListener() {
    120 
    121         public void onPatternStart() {
    122             mLockPatternView.removeCallbacks(mClearErrorRunnable);
    123             mMsgView.setText("");
    124         }
    125 
    126         public void onPatternCleared() {
    127             mLockPatternView.removeCallbacks(mClearErrorRunnable);
    128         }
    129 
    130         public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {}
    131 
    132         public void onPatternDetected(List<LockPatternView.Cell> pattern) {
    133             mLockPatternView.setEnabled(false);
    134 
    135             if (mCheckLockWorker == null) {
    136                 mCheckLockWorker = new CheckLockWorker();
    137                 mCheckLockWorker.setListener(ConfirmLockPatternFragment.this::onCheckCompleted);
    138 
    139                 getFragmentManager()
    140                         .beginTransaction()
    141                         .add(mCheckLockWorker, FRAGMENT_TAG_CHECK_LOCK_WORKER)
    142                         .commitNow();
    143             }
    144 
    145             mPattern = pattern;
    146             mCheckLockWorker.checkPattern(mUserId, pattern);
    147         }
    148     };
    149 
    150     private void onCheckCompleted(boolean lockMatched) {
    151         if (lockMatched) {
    152             mCheckLockListener.onLockVerified(LockPatternUtils.patternToString(mPattern));
    153         } else {
    154             mLockPatternView.setEnabled(true);
    155             mMsgView.setText(R.string.lockpattern_pattern_wrong);
    156 
    157             // Set timer to clear wrong pattern
    158             mLockPatternView.removeCallbacks(mClearErrorRunnable);
    159             mLockPatternView.postDelayed(mClearErrorRunnable, CLEAR_WRONG_ATTEMPT_TIMEOUT_MS);
    160         }
    161     }
    162 }
    163