Trust Agents: Add facility to request credential entry

Bug: 15871777
Change-Id: I43c80151f6403ff62961aeb3dc7aafe049e18a62
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index ad4ccbb..6fbf87d 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -26,6 +26,7 @@
 interface ITrustManager {
     void reportUnlockAttempt(boolean successful, int userId);
     void reportEnabledTrustAgentsChanged(int userId);
+    void reportRequireCredentialEntry(int userId);
     void registerTrustListener(in ITrustListener trustListener);
     void unregisterTrustListener(in ITrustListener trustListener);
 }
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index e31c624..6e90590 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -71,6 +71,21 @@
     }
 
     /**
+     * Reports that trust is disabled until credentials have been entered for user {@param userId}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     *
+     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
+     */
+    public void reportRequireCredentialEntry(int userId) {
+        try {
+            mService.reportRequireCredentialEntry(userId);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
      * Registers a listener for trust events.
      *
      * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d31c5cc..5bd6f52 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1460,4 +1460,11 @@
         }
         return activeTrustAgents;
     }
+
+    /**
+     * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
+     */
+    public void requireCredentialEntry(int userId) {
+        getTrustManager().reportRequireCredentialEntry(userId);
+    }
 }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 32546df..1aec569 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -88,6 +88,7 @@
     private static final int MSG_UNREGISTER_LISTENER = 2;
     private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
     private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
+    private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
 
     private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
     private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
@@ -314,6 +315,17 @@
         }
     }
 
+
+    private void requireCredentialEntry(int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mUserHasAuthenticatedSinceBoot.clear();
+            updateTrustAll();
+        } else {
+            mUserHasAuthenticatedSinceBoot.put(userId, false);
+            updateTrust(userId);
+        }
+    }
+
     // Listeners
 
     private void addListener(ITrustListener listener) {
@@ -367,6 +379,17 @@
         }
 
         @Override
+        public void reportRequireCredentialEntry(int userId) throws RemoteException {
+            enforceReportPermission();
+            if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
+                mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
+            } else {
+                throw new IllegalArgumentException(
+                        "userId must be an explicit user id or USER_ALL");
+            }
+        }
+
+        @Override
         public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
             enforceListenerPermission();
             mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
@@ -379,8 +402,8 @@
         }
 
         private void enforceReportPermission() {
-            mContext.enforceCallingPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
-                    "reporting trust events");
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
         }
 
         private void enforceListenerPermission() {
@@ -460,6 +483,9 @@
                 case MSG_ENABLED_AGENTS_CHANGED:
                     refreshAgentList();
                     break;
+                case MSG_REQUIRE_CREDENTIAL_ENTRY:
+                    requireCredentialEntry(msg.arg1);
+                    break;
             }
         }
     };