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.systemui.statusbar.phone;
18 
19 import android.content.Context;
20 
21 import com.android.internal.widget.LockPatternUtils;
22 import com.android.keyguard.KeyguardUpdateMonitor;
23 import com.android.keyguard.KeyguardUpdateMonitorCallback;
24 
25 import java.util.ArrayList;
26 
27 /**
28  * Caches whether the current unlock method is insecure, taking trust into account. This information
29  * might be a little bit out of date and should not be used for actual security decisions; it should
30  * be only used for visual indications.
31  */
32 public class UnlockMethodCache {
33 
34     private static UnlockMethodCache sInstance;
35 
36     private final LockPatternUtils mLockPatternUtils;
37     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
38     private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
39     /** Whether the user configured a secure unlock method (PIN, password, etc.) */
40     private boolean mSecure;
41     /** Whether the unlock method is currently insecure (insecure method or trusted environment) */
42     private boolean mCurrentlyInsecure;
43     private boolean mTrustManaged;
44     private boolean mFaceUnlockRunning;
45 
UnlockMethodCache(Context ctx)46     private UnlockMethodCache(Context ctx) {
47         mLockPatternUtils = new LockPatternUtils(ctx);
48         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx);
49         KeyguardUpdateMonitor.getInstance(ctx).registerCallback(mCallback);
50         update(true /* updateAlways */);
51     }
52 
getInstance(Context context)53     public static UnlockMethodCache getInstance(Context context) {
54         if (sInstance == null) {
55             sInstance = new UnlockMethodCache(context);
56         }
57         return sInstance;
58     }
59 
60     /**
61      * @return whether the user configured a secure unlock method like PIN, password, etc.
62      */
isMethodSecure()63     public boolean isMethodSecure() {
64         return mSecure;
65     }
66 
67     /**
68      * @return whether the lockscreen is currently insecure, i. e. the bouncer won't be shown
69      */
isCurrentlyInsecure()70     public boolean isCurrentlyInsecure() {
71         return mCurrentlyInsecure;
72     }
73 
addListener(OnUnlockMethodChangedListener listener)74     public void addListener(OnUnlockMethodChangedListener listener) {
75         mListeners.add(listener);
76     }
77 
removeListener(OnUnlockMethodChangedListener listener)78     public void removeListener(OnUnlockMethodChangedListener listener) {
79         mListeners.remove(listener);
80     }
81 
update(boolean updateAlways)82     private void update(boolean updateAlways) {
83         int user = mLockPatternUtils.getCurrentUser();
84         boolean secure = mLockPatternUtils.isSecure();
85         boolean currentlyInsecure = !secure ||  mKeyguardUpdateMonitor.getUserHasTrust(user);
86         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
87         boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
88                 && trustManaged;
89         boolean changed = secure != mSecure || currentlyInsecure != mCurrentlyInsecure ||
90                 trustManaged != mTrustManaged  || faceUnlockRunning != mFaceUnlockRunning;
91         if (changed || updateAlways) {
92             mSecure = secure;
93             mCurrentlyInsecure = currentlyInsecure;
94             mTrustManaged = trustManaged;
95             mFaceUnlockRunning = faceUnlockRunning;
96             notifyListeners();
97         }
98     }
99 
notifyListeners()100     private void notifyListeners() {
101         for (OnUnlockMethodChangedListener listener : mListeners) {
102             listener.onUnlockMethodStateChanged();
103         }
104     }
105 
106     private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
107         @Override
108         public void onUserSwitchComplete(int userId) {
109             update(false /* updateAlways */);
110         }
111 
112         @Override
113         public void onTrustChanged(int userId) {
114             update(false /* updateAlways */);
115         }
116 
117         @Override
118         public void onTrustManagedChanged(int userId) {
119             update(false /* updateAlways */);
120         }
121 
122         @Override
123         public void onScreenTurnedOn() {
124             update(false /* updateAlways */);
125         }
126 
127         @Override
128         public void onFingerprintRecognized(int userId) {
129             update(false /* updateAlways */);
130         }
131 
132         @Override
133         public void onFaceUnlockStateChanged(boolean running, int userId) {
134             update(false /* updateAlways */);
135         }
136     };
137 
isTrustManaged()138     public boolean isTrustManaged() {
139         return mTrustManaged;
140     }
141 
isFaceUnlockRunning()142     public boolean isFaceUnlockRunning() {
143         return mFaceUnlockRunning;
144     }
145 
146     public static interface OnUnlockMethodChangedListener {
onUnlockMethodStateChanged()147         void onUnlockMethodStateChanged();
148     }
149 }
150