Merge "Enable auth check for profiles with shared credentials" into main

This commit is contained in:
Jigar Thakkar
2023-11-15 12:41:14 +00:00
committed by Android (Google) Code Review

View File

@@ -31,6 +31,7 @@ import android.app.trust.TrustManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserProperties;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Color; import android.graphics.Color;
import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricConstants;
@@ -61,11 +62,6 @@ import java.util.concurrent.Executor;
public class ConfirmDeviceCredentialActivity extends FragmentActivity { public class ConfirmDeviceCredentialActivity extends FragmentActivity {
public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName(); public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
// The normal flow that apps go through
private static final int CREDENTIAL_NORMAL = 1;
// Unlocks the managed profile when the primary profile is unlocked
private static final int CREDENTIAL_MANAGED = 2;
private static final String TAG_BIOMETRIC_FRAGMENT = "fragment"; private static final String TAG_BIOMETRIC_FRAGMENT = "fragment";
public static class InternalActivity extends ConfirmDeviceCredentialActivity { public static class InternalActivity extends ConfirmDeviceCredentialActivity {
@@ -84,7 +80,9 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private String mTitle; private String mTitle;
private CharSequence mDetails; private CharSequence mDetails;
private int mUserId; private int mUserId;
private int mCredentialMode; // Used to force the verification path required to unlock profile that shares credentials with
// with parent
private boolean mForceVerifyPath = false;
private boolean mGoingToBackground; private boolean mGoingToBackground;
private boolean mWaitingForBiometricCallback; private boolean mWaitingForBiometricCallback;
@@ -189,7 +187,9 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
} }
final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId); final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
final boolean isEffectiveUserManagedProfile = final boolean isEffectiveUserManagedProfile =
UserManager.get(this).isManagedProfile(effectiveUserId); mUserManager.isManagedProfile(effectiveUserId);
final UserProperties userProperties =
mUserManager.getUserProperties(UserHandle.of(mUserId));
// if the client app did not hand in a title and we are about to show the work challenge, // if the client app did not hand in a title and we are about to show the work challenge,
// check whether there is a policy setting the organization name and use that as title // check whether there is a policy setting the organization name and use that as title
if ((mTitle == null) && isEffectiveUserManagedProfile) { if ((mTitle == null) && isEffectiveUserManagedProfile) {
@@ -278,7 +278,19 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
.setForceVerifyPath(true) .setForceVerifyPath(true)
.show(); .show();
} else if (isEffectiveUserManagedProfile && isInternalActivity()) { } else if (isEffectiveUserManagedProfile && isInternalActivity()) {
mCredentialMode = CREDENTIAL_MANAGED; // When the mForceVerifyPath is set to true, we launch the real confirm credential
// activity with an explicit but fake challenge value (0L). This will result in
// ConfirmLockPassword calling verifyTiedProfileChallenge() (if it's a profile with
// unified challenge), due to the difference between
// ConfirmLockPassword.startVerifyPassword() and
// ConfirmLockPassword.startCheckPassword(). Calling verifyTiedProfileChallenge() here
// is necessary when this is part of the turning on work profile flow, because it forces
// unlocking the work profile even before the profile is running.
// TODO: Remove the duplication of checkPassword and verifyPassword in
// ConfirmLockPassword,
// LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to
// use, which optionally accepts a challenge.
mForceVerifyPath = true;
if (isBiometricAllowed(effectiveUserId, mUserId)) { if (isBiometricAllowed(effectiveUserId, mUserId)) {
showBiometricPrompt(promptInfo); showBiometricPrompt(promptInfo);
launchedBiometric = true; launchedBiometric = true;
@@ -286,8 +298,19 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
showConfirmCredentials(); showConfirmCredentials();
launchedCDC = true; launchedCDC = true;
} }
} else if (android.os.Flags.allowPrivateProfile()
&& userProperties != null
&& userProperties.isAuthAlwaysRequiredToDisableQuietMode()
&& isInternalActivity()) {
// Force verification path is required to be invoked as we might need to verify the tied
// profile challenge if the profile is using the unified challenge mode. This would
// result in ConfirmLockPassword.startVerifyPassword/
// ConfirmLockPattern.startVerifyPattern being called instead of the
// startCheckPassword/startCheckPattern
mForceVerifyPath = userProperties.isCredentialShareableWithParent();
showConfirmCredentials();
launchedCDC = true;
} else { } else {
mCredentialMode = CREDENTIAL_NORMAL;
if (isBiometricAllowed(effectiveUserId, mUserId)) { if (isBiometricAllowed(effectiveUserId, mUserId)) {
// Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
// onAuthenticationError and do the right thing automatically. // onAuthenticationError and do the right thing automatically.
@@ -313,11 +336,8 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private String getTitleFromCredentialType(@LockPatternUtils.CredentialType int credentialType, private String getTitleFromCredentialType(@LockPatternUtils.CredentialType int credentialType,
boolean isEffectiveUserManagedProfile) { boolean isEffectiveUserManagedProfile) {
int overrideStringId;
int defaultStringId;
switch (credentialType) { switch (credentialType) {
case LockPatternUtils.CREDENTIAL_TYPE_PIN: case LockPatternUtils.CREDENTIAL_TYPE_PIN:
if (isEffectiveUserManagedProfile) { if (isEffectiveUserManagedProfile) {
return mDevicePolicyManager.getResources().getString( return mDevicePolicyManager.getResources().getString(
CONFIRM_WORK_PROFILE_PIN_HEADER, CONFIRM_WORK_PROFILE_PIN_HEADER,
@@ -410,29 +430,15 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
* Shows ConfirmDeviceCredentials for normal apps. * Shows ConfirmDeviceCredentials for normal apps.
*/ */
private void showConfirmCredentials() { private void showConfirmCredentials() {
boolean launched = false; boolean launched = new ChooseLockSettingsHelper.Builder(this)
ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(this)
.setHeader(mTitle) .setHeader(mTitle)
.setDescription(mDetails) .setDescription(mDetails)
.setExternal(true) .setExternal(true)
.setUserId(mUserId) .setUserId(mUserId)
.setTaskOverlay(mTaskOverlay); .setTaskOverlay(mTaskOverlay)
// The only difference between CREDENTIAL_MANAGED and CREDENTIAL_NORMAL is that for .setForceVerifyPath(mForceVerifyPath)
// CREDENTIAL_MANAGED, we launch the real confirm credential activity with an explicit .show();
// but fake challenge value (0L). This will result in ConfirmLockPassword calling
// verifyTiedProfileChallenge() (if it's a profile with unified challenge), due to the
// difference between ConfirmLockPassword.startVerifyPassword() and
// ConfirmLockPassword.startCheckPassword(). Calling verifyTiedProfileChallenge() here is
// necessary when this is part of the turning on work profile flow, because it forces
// unlocking the work profile even before the profile is running.
// TODO: Remove the duplication of checkPassword and verifyPassword in ConfirmLockPassword,
// LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to use,
// which optionally accepts a challenge.
if (mCredentialMode == CREDENTIAL_MANAGED) {
launched = builder.setForceVerifyPath(true).show();
} else if (mCredentialMode == CREDENTIAL_NORMAL) {
launched = builder.show();
}
if (!launched) { if (!launched) {
Log.d(TAG, "No pin/pattern/pass set"); Log.d(TAG, "No pin/pattern/pass set");
setResult(Activity.RESULT_OK); setResult(Activity.RESULT_OK);