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.os.Bundle;
20 
21 import androidx.fragment.app.Fragment;
22 
23 import com.android.car.settings.common.Logger;
24 import com.android.internal.widget.LockPatternChecker;
25 import com.android.internal.widget.LockPatternUtils;
26 import com.android.internal.widget.LockPatternView;
27 import com.android.internal.widget.LockscreenCredential;
28 
29 import java.util.List;
30 
31 /**
32  * An invisible retained worker fragment to track the AsyncTask that checks the entered lock
33  * credential (pattern/pin/password).
34  */
35 public class CheckLockWorker extends Fragment implements LockPatternChecker.OnCheckCallback {
36 
37     private static final Logger LOG = new Logger(CheckLockWorker.class);
38 
39     private boolean mHasPendingResult;
40     private boolean mLockMatched;
41     private int mThrottleTimeoutMs;
42     private boolean mCheckInProgress;
43     private Listener mListener;
44     private LockPatternUtils mLockPatternUtils;
45 
46     @Override
onCreate(Bundle savedInstanceState)47     public void onCreate(Bundle savedInstanceState) {
48         super.onCreate(savedInstanceState);
49         setRetainInstance(true);
50         mLockPatternUtils = new LockPatternUtils(getContext());
51     }
52 
53     @Override
onChecked(boolean matched, int throttleTimeoutMs)54     public void onChecked(boolean matched, int throttleTimeoutMs) {
55         mCheckInProgress = false;
56 
57         if (mListener == null) {
58             mHasPendingResult = true;
59             mLockMatched = matched;
60             mThrottleTimeoutMs = throttleTimeoutMs;
61         } else {
62             mListener.onCheckCompleted(matched, throttleTimeoutMs);
63         }
64     }
65 
66     /**
67      * Sets the listener for callback when lock check is completed.
68      */
setListener(Listener listener)69     public void setListener(Listener listener) {
70         mListener = listener;
71         if (mListener != null && mHasPendingResult) {
72             mHasPendingResult = false;
73             mListener.onCheckCompleted(mLockMatched, mThrottleTimeoutMs);
74         }
75     }
76 
77     /** Returns whether a lock check is in progress. */
isCheckInProgress()78     public final boolean isCheckInProgress() {
79         return mCheckInProgress;
80     }
81 
82     /**
83      * Checks lock pattern asynchronously. To receive callback when check is completed,
84      * implement {@link Listener} and call {@link #setListener(Listener)}.
85      */
checkPattern(int userId, List<LockPatternView.Cell> pattern)86     public final void checkPattern(int userId, List<LockPatternView.Cell> pattern) {
87         if (mCheckInProgress) {
88             LOG.w("Check pattern request issued while one is still running");
89             return;
90         }
91 
92         mCheckInProgress = true;
93         try (LockscreenCredential toCheck = LockscreenCredential.createPattern(pattern)) {
94             LockPatternChecker.checkCredential(mLockPatternUtils, toCheck, userId, this);
95         }
96     }
97 
98     /**
99      * Checks lock PIN/password asynchronously.  To receive callback when check is completed,
100      * implement {@link Listener} and call {@link #setListener(Listener)}.
101      */
checkPinPassword(int userId, LockscreenCredential password)102     public final void checkPinPassword(int userId, LockscreenCredential password) {
103         if (mCheckInProgress) {
104             LOG.w("Check pin/password request issued while one is still running");
105             return;
106         }
107         if (password == null || password.isNone()) {
108             LOG.w("Empty pin/password LockscreenCredential");
109             return;
110         }
111         mCheckInProgress = true;
112         LockPatternChecker.checkCredential(mLockPatternUtils, password, userId, this);
113     }
114 
115     /**
116      * Callback when lock check is completed.
117      */
118     interface Listener {
119         /**
120          * @param matched Whether the entered password matches the stored record.
121          * @param timeoutMs The remaining amount of time that the user is locked out from
122          *                  retrying the password challenge.
123          */
onCheckCompleted(boolean matched, int timeoutMs)124         void onCheckCompleted(boolean matched, int timeoutMs);
125     }
126 }
127 
128