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.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.hardware.biometrics.BiometricSourceType;
24 import android.os.Build;
25 import android.os.Trace;
26 
27 import com.android.internal.widget.LockPatternUtils;
28 import com.android.keyguard.KeyguardUpdateMonitor;
29 import com.android.keyguard.KeyguardUpdateMonitorCallback;
30 
31 import java.io.PrintWriter;
32 import java.util.ArrayList;
33 
34 /**
35  * Caches whether the current unlock method is insecure, taking trust into account. This information
36  * might be a little bit out of date and should not be used for actual security decisions; it should
37  * be only used for visual indications.
38  */
39 public class UnlockMethodCache {
40 
41     private static UnlockMethodCache sInstance;
42     private static final boolean DEBUG_AUTH_WITH_ADB = false;
43     private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth";
44 
45     private final LockPatternUtils mLockPatternUtils;
46     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
47     private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
48     /** Whether the user configured a secure unlock method (PIN, password, etc.) */
49     private boolean mSecure;
50     /** Whether the unlock method is currently insecure (insecure method or trusted environment) */
51     private boolean mCanSkipBouncer;
52     private boolean mTrustManaged;
53     private boolean mTrusted;
54     private boolean mDebugUnlocked = false;
55     private boolean mFaceAuthEnabled;
56 
UnlockMethodCache(Context ctx)57     private UnlockMethodCache(Context ctx) {
58         mLockPatternUtils = new LockPatternUtils(ctx);
59         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx);
60         KeyguardUpdateMonitor.getInstance(ctx).registerCallback(mCallback);
61         update(true /* updateAlways */);
62         if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) {
63             // Watch for interesting updates
64             final IntentFilter filter = new IntentFilter();
65             filter.addAction(AUTH_BROADCAST_KEY);
66             ctx.registerReceiver(new BroadcastReceiver() {
67                 @Override
68                 public void onReceive(Context context, Intent intent) {
69                     if (DEBUG_AUTH_WITH_ADB && AUTH_BROADCAST_KEY.equals(intent.getAction())) {
70                         mDebugUnlocked = !mDebugUnlocked;
71                         update(true /* updateAlways */);
72                     }
73                 }
74             }, filter, null, null);
75         }
76     }
77 
getInstance(Context context)78     public static UnlockMethodCache getInstance(Context context) {
79         if (sInstance == null) {
80             sInstance = new UnlockMethodCache(context);
81         }
82         return sInstance;
83     }
84 
85     /**
86      * @return whether the user configured a secure unlock method like PIN, password, etc.
87      */
isMethodSecure()88     public boolean isMethodSecure() {
89         return mSecure;
90     }
91 
isTrusted()92     public boolean isTrusted() {
93         return mTrusted;
94     }
95 
96     /**
97      * @return whether the lockscreen is currently insecure, and the bouncer won't be shown
98      */
canSkipBouncer()99     public boolean canSkipBouncer() {
100         return mCanSkipBouncer;
101     }
102 
addListener(OnUnlockMethodChangedListener listener)103     public void addListener(OnUnlockMethodChangedListener listener) {
104         mListeners.add(listener);
105     }
106 
removeListener(OnUnlockMethodChangedListener listener)107     public void removeListener(OnUnlockMethodChangedListener listener) {
108         mListeners.remove(listener);
109     }
110 
111     /**
112      * If there are faces enrolled and user enabled face auth on keyguard.
113      */
isFaceAuthEnabled()114     public boolean isFaceAuthEnabled() {
115         return mFaceAuthEnabled;
116     }
117 
update(boolean updateAlways)118     private void update(boolean updateAlways) {
119         Trace.beginSection("UnlockMethodCache#update");
120         int user = KeyguardUpdateMonitor.getCurrentUser();
121         boolean secure = mLockPatternUtils.isSecure(user);
122         boolean canSkipBouncer = !secure || mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)
123                 || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
124         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
125         boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
126         boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
127         boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer
128                 || trustManaged != mTrustManaged
129                 || mFaceAuthEnabled != faceAuthEnabled;
130         if (changed || updateAlways) {
131             mSecure = secure;
132             mCanSkipBouncer = canSkipBouncer;
133             mTrusted = trusted;
134             mTrustManaged = trustManaged;
135             mFaceAuthEnabled = faceAuthEnabled;
136             notifyListeners();
137         }
138         Trace.endSection();
139     }
140 
notifyListeners()141     private void notifyListeners() {
142         for (OnUnlockMethodChangedListener listener : mListeners) {
143             listener.onUnlockMethodStateChanged();
144         }
145     }
146 
dump(PrintWriter pw)147     public void dump(PrintWriter pw) {
148         pw.println("UnlockMethodCache");
149         pw.println("  mSecure: " + mSecure);
150         pw.println("  mCanSkipBouncer: " + mCanSkipBouncer);
151         pw.println("  mTrustManaged: " + mTrustManaged);
152         pw.println("  mTrusted: " + mTrusted);
153         pw.println("  mDebugUnlocked: " + mDebugUnlocked);
154         pw.println("  mFaceAuthEnabled: " + mFaceAuthEnabled);
155     }
156 
157     private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
158         @Override
159         public void onUserSwitchComplete(int userId) {
160             update(false /* updateAlways */);
161         }
162 
163         @Override
164         public void onTrustChanged(int userId) {
165             update(false /* updateAlways */);
166         }
167 
168         @Override
169         public void onTrustManagedChanged(int userId) {
170             update(false /* updateAlways */);
171         }
172 
173         @Override
174         public void onStartedWakingUp() {
175             update(false /* updateAlways */);
176         }
177 
178         @Override
179         public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
180             Trace.beginSection("KeyguardUpdateMonitorCallback#onBiometricAuthenticated");
181             if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
182                 Trace.endSection();
183                 return;
184             }
185             update(false /* updateAlways */);
186             Trace.endSection();
187         }
188 
189         @Override
190         public void onFaceUnlockStateChanged(boolean running, int userId) {
191             update(false /* updateAlways */);
192         }
193 
194         @Override
195         public void onStrongAuthStateChanged(int userId) {
196             update(false /* updateAlways */);
197         }
198 
199         @Override
200         public void onScreenTurnedOff() {
201             update(false /* updateAlways */);
202         }
203 
204         @Override
205         public void onKeyguardVisibilityChanged(boolean showing) {
206             update(false /* updateAlways */);
207         }
208 
209         @Override
210         public void onBiometricsCleared() {
211             update(false /* alwaysUpdate */);
212         }
213     };
214 
isTrustManaged()215     public boolean isTrustManaged() {
216         return mTrustManaged;
217     }
218 
219     public static interface OnUnlockMethodChangedListener {
onUnlockMethodStateChanged()220         void onUnlockMethodStateChanged();
221     }
222 }
223