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 mCanSkipBouncer;
43     private boolean mTrustManaged;
44     private boolean mFaceUnlockRunning;
45     private boolean mTrusted;
46 
UnlockMethodCache(Context ctx)47     private UnlockMethodCache(Context ctx) {
48         mLockPatternUtils = new LockPatternUtils(ctx);
49         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx);
50         KeyguardUpdateMonitor.getInstance(ctx).registerCallback(mCallback);
51         update(true /* updateAlways */);
52     }
53 
getInstance(Context context)54     public static UnlockMethodCache getInstance(Context context) {
55         if (sInstance == null) {
56             sInstance = new UnlockMethodCache(context);
57         }
58         return sInstance;
59     }
60 
61     /**
62      * @return whether the user configured a secure unlock method like PIN, password, etc.
63      */
isMethodSecure()64     public boolean isMethodSecure() {
65         return mSecure;
66     }
67 
isTrusted()68     public boolean isTrusted() {
69         return mTrusted;
70     }
71 
72     /**
73      * @return whether the lockscreen is currently insecure, and the bouncer won't be shown
74      */
canSkipBouncer()75     public boolean canSkipBouncer() {
76         return mCanSkipBouncer;
77     }
78 
addListener(OnUnlockMethodChangedListener listener)79     public void addListener(OnUnlockMethodChangedListener listener) {
80         mListeners.add(listener);
81     }
82 
removeListener(OnUnlockMethodChangedListener listener)83     public void removeListener(OnUnlockMethodChangedListener listener) {
84         mListeners.remove(listener);
85     }
86 
update(boolean updateAlways)87     private void update(boolean updateAlways) {
88         int user = KeyguardUpdateMonitor.getCurrentUser();
89         boolean secure = mLockPatternUtils.isSecure(user);
90         boolean canSkipBouncer = !secure ||  mKeyguardUpdateMonitor.getUserCanSkipBouncer(user);
91         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
92         boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
93         boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
94                 && trustManaged;
95         boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer ||
96                 trustManaged != mTrustManaged  || faceUnlockRunning != mFaceUnlockRunning;
97         if (changed || updateAlways) {
98             mSecure = secure;
99             mCanSkipBouncer = canSkipBouncer;
100             mTrusted = trusted;
101             mTrustManaged = trustManaged;
102             mFaceUnlockRunning = faceUnlockRunning;
103             notifyListeners();
104         }
105     }
106 
notifyListeners()107     private void notifyListeners() {
108         for (OnUnlockMethodChangedListener listener : mListeners) {
109             listener.onUnlockMethodStateChanged();
110         }
111     }
112 
113     private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
114         @Override
115         public void onUserSwitchComplete(int userId) {
116             update(false /* updateAlways */);
117         }
118 
119         @Override
120         public void onTrustChanged(int userId) {
121             update(false /* updateAlways */);
122         }
123 
124         @Override
125         public void onTrustManagedChanged(int userId) {
126             update(false /* updateAlways */);
127         }
128 
129         @Override
130         public void onStartedWakingUp() {
131             update(false /* updateAlways */);
132         }
133 
134         @Override
135         public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
136             if (!mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()) {
137                 return;
138             }
139             update(false /* updateAlways */);
140         }
141 
142         @Override
143         public void onFaceUnlockStateChanged(boolean running, int userId) {
144             update(false /* updateAlways */);
145         }
146     };
147 
isTrustManaged()148     public boolean isTrustManaged() {
149         return mTrustManaged;
150     }
151 
isFaceUnlockRunning()152     public boolean isFaceUnlockRunning() {
153         return mFaceUnlockRunning;
154     }
155 
156     public static interface OnUnlockMethodChangedListener {
onUnlockMethodStateChanged()157         void onUnlockMethodStateChanged();
158     }
159 }
160