Merge "update trust state immediately when user auths via FP on keyguard"
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index a10de45..6d65e3e 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -34,4 +34,6 @@
     boolean isDeviceLocked(int userId);
     boolean isDeviceSecure(int userId);
     boolean isTrustUsuallyManaged(int userId);
+    void unlockedByFingerprintForUser(int userId);
+    void clearAllFingerprints();
 }
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 06b0aac..3c681f2 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -25,8 +25,6 @@
 import android.os.RemoteException;
 import android.util.ArrayMap;
 
-import com.android.internal.widget.LockPatternUtils;
-
 /**
  * See {@link com.android.server.trust.TrustManagerService}
  * @hide
@@ -184,6 +182,32 @@
         }
     }
 
+    /**
+     * Updates the trust state for the user due to the user unlocking via fingerprint.
+     * Should only be called if user authenticated via fingerprint and bouncer can be skipped.
+     * @param userId
+     */
+    @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+    public void unlockedByFingerprintForUser(int userId) {
+        try {
+            mService.unlockedByFingerprintForUser(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Clears authenticated fingerprints for all users.
+     */
+    @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+    public void clearAllFingerprints() {
+        try {
+            mService.clearAllFingerprints();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1ce34d4..47290ec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -415,6 +415,10 @@
     private void onFingerprintAuthenticated(int userId) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
         mUserFingerprintAuthenticated.put(userId, true);
+        // Update/refresh trust state only if user can skip bouncer
+        if (getUserCanSkipBouncer(userId)) {
+            mTrustManager.unlockedByFingerprintForUser(userId);
+        }
         // Don't send cancel if authentication succeeds
         mFingerprintCancelSignal = null;
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1649,6 +1653,7 @@
 
     public void clearFingerprintRecognized() {
         mUserFingerprintAuthenticated.clear();
+        mTrustManager.clearAllFingerprints();
     }
 
     public boolean isSimPinVoiceSecure() {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c6393e7..5bd485c 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -106,6 +106,7 @@
     private static final int MSG_UNLOCK_USER = 11;
     private static final int MSG_STOP_USER = 12;
     private static final int MSG_DISPATCH_UNLOCK_LOCKOUT = 13;
+    private static final int MSG_REFRESH_DEVICE_LOCKED_FOR_USER = 14;
 
     private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;
 
@@ -125,9 +126,13 @@
     @GuardedBy("mDeviceLockedForUser")
     private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
 
-    @GuardedBy("mDeviceLockedForUser")
+    @GuardedBy("mTrustUsuallyManagedForUser")
     private final SparseBooleanArray mTrustUsuallyManagedForUser = new SparseBooleanArray();
 
+    // set to true only if user can skip bouncer
+    @GuardedBy("mUsersUnlockedByFingerprint")
+    private SparseBooleanArray mUsersUnlockedByFingerprint = new SparseBooleanArray();
+
     private final StrongAuthTracker mStrongAuthTracker;
 
     private boolean mTrustAgentsCanRun = false;
@@ -409,7 +414,6 @@
                     + " must be USER_ALL or a specific user.", new Throwable("here"));
             userId = UserHandle.USER_ALL;
         }
-
         List<UserInfo> userInfos;
         if (userId == UserHandle.USER_ALL) {
             userInfos = mUserManager.getUsers(true /* excludeDying */);
@@ -432,13 +436,19 @@
             boolean secure = mLockPatternUtils.isSecure(id);
             boolean trusted = aggregateIsTrusted(id);
             boolean showingKeyguard = true;
+            boolean fingerprintAuthenticated = false;
+
             if (mCurrentUser == id) {
+                synchronized(mUsersUnlockedByFingerprint) {
+                    fingerprintAuthenticated = mUsersUnlockedByFingerprint.get(id, false);
+                }
                 try {
                     showingKeyguard = wm.isKeyguardLocked();
                 } catch (RemoteException e) {
                 }
             }
-            boolean deviceLocked = secure && showingKeyguard && !trusted;
+            boolean deviceLocked = secure && showingKeyguard && !trusted &&
+                    !fingerprintAuthenticated;
             setDeviceLockedForUser(id, deviceLocked);
         }
     }
@@ -986,6 +996,26 @@
                     "query trust state");
             return isTrustUsuallyManagedInternal(userId);
         }
+
+        @Override
+        public void unlockedByFingerprintForUser(int userId) {
+            enforceReportPermission();
+            synchronized(mUsersUnlockedByFingerprint) {
+                mUsersUnlockedByFingerprint.put(userId, true);
+            }
+            mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, userId,
+                    0 /* arg2 */).sendToTarget();
+        }
+
+        @Override
+        public void clearAllFingerprints() {
+            enforceReportPermission();
+            synchronized(mUsersUnlockedByFingerprint) {
+                mUsersUnlockedByFingerprint.clear();
+            }
+            mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, UserHandle.USER_ALL,
+                    0 /* arg2 */).sendToTarget();
+        }
     };
 
     private boolean isTrustUsuallyManagedInternal(int userId) {
@@ -1073,6 +1103,9 @@
                         }
                     }
                     break;
+                case MSG_REFRESH_DEVICE_LOCKED_FOR_USER:
+                    refreshDeviceLockedForUser(msg.arg1);
+                    break;
             }
         }
     };
@@ -1132,6 +1165,9 @@
                     synchronized (mTrustUsuallyManagedForUser) {
                         mTrustUsuallyManagedForUser.delete(userId);
                     }
+                    synchronized (mUsersUnlockedByFingerprint) {
+                        mUsersUnlockedByFingerprint.delete(userId);
+                    }
                     refreshAgentList(userId);
                     refreshDeviceLockedForUser(userId);
                 }