Make ConfirmCredentials take user into account when creating intent

The existing implementation returned null if the device was not locked,
but when using ConfirmCredentials for the Work Profile we need to take into
account the user we want to confirm credentials for, given that the device
user might not have a lock but the work profile will.

Change-Id: Ifb5882846b0a62c73ac7cc04d90d1a4d9b103e63
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 23e4d97..3910657 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -21,11 +21,14 @@
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
+import android.os.IUserManager;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.view.IWindowManager;
 import android.view.IOnKeyguardExitResult;
 import android.view.WindowManagerGlobal;
@@ -40,6 +43,7 @@
 public class KeyguardManager {
     private IWindowManager mWM;
     private ITrustManager mTrustManager;
+    private IUserManager mUserManager;
 
     /**
      * Intent used to prompt user for device credentials.
@@ -49,6 +53,13 @@
             "android.app.action.CONFIRM_DEVICE_CREDENTIAL";
 
     /**
+     * Intent used to prompt user for device credentials.
+     * @hide
+     */
+    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER =
+            "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER";
+
+    /**
      * A CharSequence dialog title to show to the user when used with a
      * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
      * @hide
@@ -71,7 +82,7 @@
      * @return the intent for launching the activity or null if no password is required.
      **/
     public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
-        if (!isKeyguardSecure()) return null;
+        if (!isDeviceSecure()) return null;
         Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
         intent.putExtra(EXTRA_TITLE, title);
         intent.putExtra(EXTRA_DESCRIPTION, description);
@@ -81,6 +92,28 @@
     }
 
     /**
+     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
+     * for the given user. The caller is expected to launch this activity using
+     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
+     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
+     *
+     * @return the intent for launching the activity or null if no password is required.
+     *
+     * @hide
+     */
+    public Intent createConfirmDeviceCredentialIntent(
+            CharSequence title, CharSequence description, int userId) {
+        if (!isDeviceSecure(userId)) return null;
+        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
+        intent.putExtra(EXTRA_TITLE, title);
+        intent.putExtra(EXTRA_DESCRIPTION, description);
+        intent.putExtra(Intent.EXTRA_USER_ID, userId);
+        // For security reasons, only allow this to come from system settings.
+        intent.setPackage("com.android.settings");
+        return intent;
+    }
+
+    /**
      * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
      * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
      * instead; this allows you to seamlessly hide the keyguard as your application
@@ -162,6 +195,8 @@
         mWM = WindowManagerGlobal.getWindowManagerService();
         mTrustManager = ITrustManager.Stub.asInterface(
                 ServiceManager.getService(Context.TRUST_SERVICE));
+        mUserManager = IUserManager.Stub.asInterface(
+                ServiceManager.getService(Context.USER_SERVICE));
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6c00e73..50575e8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1624,21 +1624,23 @@
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
                             | PendingIntent.FLAG_IMMUTABLE, null);
             int flags = intent.getFlags();
-            intent = km.createConfirmDeviceCredentialIntent(null, null);
-            intent.addFlags(FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
-            intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
-            intent.putExtra(Intent.EXTRA_USER_ID, userId);
-            intent.setFlags(flags);
+            Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, user.id);
+            if (newIntent != null) {
+                intent = newIntent;
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
+                intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
+                intent.setFlags(flags);
 
-            resolvedType = null;
-            callingUid = realCallingUid;
-            callingPid = realCallingPid;
+                resolvedType = null;
+                callingUid = realCallingUid;
+                callingPid = realCallingPid;
 
-            UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
-            aInfo = resolveActivity(intent, null, PackageManager.MATCH_DEFAULT_ONLY
-                    | ActivityManagerService.STOCK_PM_FLAGS, null, parent.id);
+                UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
+                aInfo = resolveActivity(intent, null, PackageManager.MATCH_DEFAULT_ONLY
+                        | ActivityManagerService.STOCK_PM_FLAGS, null, parent.id);
+            }
         }
 
         if (abort) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4b6db99..d888c56 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -53,7 +53,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.service.trust.TrustAgentService;
 import android.util.ArraySet;
@@ -681,7 +680,9 @@
         public boolean isDeviceSecure(int userId) throws RemoteException {
             userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
                     false /* allowAll */, true /* requireFull */, "isDeviceSecure", null);
-            userId = resolveProfileParent(userId);
+            if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+                userId = resolveProfileParent(userId);
+            }
 
             long token = Binder.clearCallingIdentity();
             try {