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