Merge "Improve work profile unification flow" into rvc-dev

This commit is contained in:
Rubin Xu
2020-04-15 11:18:00 +00:00
committed by Android (Google) Code Review
10 changed files with 279 additions and 93 deletions

View File

@@ -143,7 +143,7 @@ public class ChooseLockGeneric extends SettingsActivity {
static final int SKIP_FINGERPRINT_REQUEST = 104;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private DevicePolicyManager mDPM;
private DevicePolicyManager mDpm;
private boolean mHasChallenge = false;
private long mChallenge;
private boolean mPasswordConfirmed = false;
@@ -158,6 +158,8 @@ public class ChooseLockGeneric extends SettingsActivity {
private boolean mIsSetNewPassword = false;
private UserManager mUserManager;
private ChooseLockGenericController mController;
private int mUnificationProfileId = UserHandle.USER_NULL;
private LockscreenCredential mUnificationProfileCredential;
/**
* From intent extra {@link ChooseLockSettingsHelper#EXTRA_KEY_REQUESTED_MIN_COMPLEXITY}.
@@ -185,48 +187,57 @@ public class ChooseLockGeneric extends SettingsActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Activity activity = getActivity();
final Bundle arguments = getArguments();
if (!WizardManagerHelper.isDeviceProvisioned(activity)
&& !canRunBeforeDeviceProvisioned()) {
Log.i(TAG, "Refusing to start because device is not provisioned");
activity.finish();
return;
}
String chooseLockAction = getActivity().getIntent().getAction();
mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity());
mFaceManager = Utils.getFaceManagerOrNull(getActivity());
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
mLockPatternUtils = new LockPatternUtils(getActivity());
final Intent intent = activity.getIntent();
String chooseLockAction = intent.getAction();
mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
mFaceManager = Utils.getFaceManagerOrNull(activity);
mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(activity);
mLockPatternUtils = new LockPatternUtils(activity);
mIsSetNewPassword = ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
|| ACTION_SET_NEW_PASSWORD.equals(chooseLockAction);
// Defaults to needing to confirm credentials
final boolean confirmCredentials = getActivity().getIntent()
final boolean confirmCredentials = intent
.getBooleanExtra(CONFIRM_CREDENTIALS, true);
if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
if (activity instanceof ChooseLockGeneric.InternalActivity) {
mPasswordConfirmed = !confirmCredentials;
mUserPassword = getActivity().getIntent().getParcelableExtra(
mUserPassword = intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
mHasChallenge = getActivity().getIntent().getBooleanExtra(
mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
mChallenge = getActivity().getIntent().getLongExtra(
mChallenge = intent.getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
mForFingerprint = getActivity().getIntent().getBooleanExtra(
mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForFace = getActivity().getIntent().getBooleanExtra(
mForFace = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
mRequestedMinComplexity = getActivity().getIntent()
mRequestedMinComplexity = intent
.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
mCallerAppName =
getActivity().getIntent().getStringExtra(EXTRA_KEY_CALLER_APP_NAME);
mIsCallingAppAdmin = getActivity().getIntent()
intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME);
mIsCallingAppAdmin = intent
.getBooleanExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, /* defValue= */ false);
mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
mForChangeCredRequiredForBoot = arguments != null && arguments.getBoolean(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
mUserManager = UserManager.get(getActivity());
mUserManager = UserManager.get(activity);
if (arguments != null) {
mUnificationProfileCredential = (LockscreenCredential) arguments.getParcelable(
ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL);
mUnificationProfileId = arguments.getInt(
ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID,
UserHandle.USER_NULL);
}
if (savedInstanceState != null) {
mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
@@ -242,19 +253,19 @@ public class ChooseLockGeneric extends SettingsActivity {
// from Settings app itself.
// c) Otherwise, use UserHandle.myUserId().
mUserId = Utils.getSecureTargetUser(
getActivity().getActivityToken(),
UserManager.get(getActivity()),
getArguments(),
getActivity().getIntent().getExtras()).getIdentifier();
activity.getActivityToken(),
UserManager.get(activity),
arguments,
intent.getExtras()).getIdentifier();
mController = new ChooseLockGenericController(
getContext(), mUserId, mRequestedMinComplexity, mLockPatternUtils);
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
&& UserManager.get(getActivity()).isManagedProfile(mUserId)
&& UserManager.get(activity).isManagedProfile(mUserId)
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
getActivity().setTitle(R.string.lock_settings_picker_title_profile);
activity.setTitle(R.string.lock_settings_picker_title_profile);
}
mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId);
mManagedPasswordProvider = ManagedLockPasswordProvider.get(activity, mUserId);
if (mPasswordConfirmed) {
updatePreferencesOrFinish(savedInstanceState != null);
@@ -264,9 +275,9 @@ public class ChooseLockGeneric extends SettingsActivity {
}
} else if (!mWaitingForConfirmation) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
new ChooseLockSettingsHelper(activity, this);
boolean managedProfileWithUnifiedLock =
UserManager.get(getActivity()).isManagedProfile(mUserId)
UserManager.get(activity).isManagedProfile(mUserId)
&& !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
boolean skipConfirmation = managedProfileWithUnifiedLock && !mIsSetNewPassword;
if (skipConfirmation
@@ -632,9 +643,22 @@ public class ChooseLockGeneric extends SettingsActivity {
boolean hideDisabled) {
final PreferenceScreen entries = getPreferenceScreen();
int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
int adminEnforcedQuality = mDpm.getPasswordQuality(null, mUserId);
EnforcedAdmin enforcedAdmin = RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(
getActivity(), mUserId);
// If we are to unify a work challenge at the end of the credential enrollment, manually
// merge any password policy from that profile here, so we are enrolling a compliant
// password. This is because once unified, the profile's password policy will
// be enforced on the new credential.
if (mUnificationProfileId != UserHandle.USER_NULL) {
int profileEnforceQuality = mDpm.getPasswordQuality(null, mUnificationProfileId);
if (profileEnforceQuality > adminEnforcedQuality) {
adminEnforcedQuality = profileEnforceQuality;
enforcedAdmin = EnforcedAdmin.combine(enforcedAdmin,
RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(
getActivity(), mUnificationProfileId));
}
}
for (ScreenLockType lock : ScreenLockType.values()) {
String key = lock.preferenceKey;
@@ -704,6 +728,9 @@ public class ChooseLockGeneric extends SettingsActivity {
if (mUserPassword != null) {
builder.setPassword(mUserPassword);
}
if (mUnificationProfileId != UserHandle.USER_NULL) {
builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
}
return builder.build();
}
@@ -719,6 +746,9 @@ public class ChooseLockGeneric extends SettingsActivity {
if (mUserPassword != null) {
builder.setPattern(mUserPassword);
}
if (mUnificationProfileId != UserHandle.USER_NULL) {
builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
}
return builder.build();
}

View File

@@ -32,6 +32,8 @@ import static com.android.internal.widget.PasswordValidationError.RECENTLY_USED;
import static com.android.internal.widget.PasswordValidationError.TOO_LONG;
import static com.android.internal.widget.PasswordValidationError.TOO_SHORT;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
@@ -46,6 +48,7 @@ import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
@@ -153,6 +156,18 @@ public class ChooseLockPassword extends SettingsActivity {
return this;
}
/**
* Configures the launch such that at the end of the password enrollment, one of its
* managed profile (specified by {@code profileId}) will have its lockscreen unified
* to the parent user. The profile's current lockscreen credential needs to be specified by
* {@code credential}.
*/
public IntentBuilder setProfileToUnify(int profileId, LockscreenCredential credential) {
mIntent.putExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID, profileId);
mIntent.putExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL, credential);
return this;
}
public Intent build() {
return mIntent;
}
@@ -208,6 +223,7 @@ public class ChooseLockPassword extends SettingsActivity {
@PasswordComplexity private int mMinComplexity = PASSWORD_COMPLEXITY_NONE;
protected int mUserId;
private byte[] mPasswordHistoryHashFactor;
private int mUnificationProfileId = UserHandle.USER_NULL;
private LockPatternUtils mLockPatternUtils;
private SaveAndFinishWorker mSaveAndFinishWorker;
@@ -367,8 +383,19 @@ public class ChooseLockPassword extends SettingsActivity {
mRequestedQuality = intent.getIntExtra(
LockPatternUtils.PASSWORD_TYPE_KEY, PASSWORD_QUALITY_NUMERIC);
mUnificationProfileId = intent.getIntExtra(
EXTRA_KEY_UNIFICATION_PROFILE_ID, UserHandle.USER_NULL);
mMinMetrics = mLockPatternUtils.getRequestedPasswordMetrics(mUserId);
// If we are to unify a work challenge at the end of the credential enrollment, manually
// merge any password policy from that profile here, so we are enrolling a compliant
// password. This is because once unified, the profile's password policy will
// be enforced on the new credential.
if (mUnificationProfileId != UserHandle.USER_NULL) {
mMinMetrics.maxWith(
mLockPatternUtils.getRequestedPasswordMetrics(mUnificationProfileId));
}
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
if (intent.getBooleanExtra(
@@ -833,8 +860,16 @@ public class ChooseLockPassword extends SettingsActivity {
FRAGMENT_TAG_SAVE_AND_FINISH).commit();
getFragmentManager().executePendingTransactions();
final boolean required = getActivity().getIntent().getBooleanExtra(
final Intent intent = getActivity().getIntent();
final boolean required = intent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
if (mUnificationProfileId != UserHandle.USER_NULL) {
try (LockscreenCredential profileCredential = (LockscreenCredential)
intent.getParcelableExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) {
mSaveAndFinishWorker.setProfileToUnify(mUnificationProfileId,
profileCredential);
}
}
mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge,
mChosenPassword, mCurrentCredential, mUserId);
}
@@ -912,6 +947,9 @@ public class ChooseLockPassword extends SettingsActivity {
protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final boolean success = mUtils.setLockCredential(
mChosenPassword, mCurrentCredential, mUserId);
if (success) {
unifyProfileCredentialIfRequested();
}
Intent result = null;
if (success && mHasChallenge) {
byte[] token;

View File

@@ -16,6 +16,9 @@
package com.android.settings.password;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -23,6 +26,7 @@ import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Resources.Theme;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
@@ -50,6 +54,7 @@ import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.notification.RedactionInterstitial;
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
import com.google.android.collect.Lists;
import com.google.android.setupcompat.template.FooterBarMixin;
@@ -130,6 +135,19 @@ public class ChooseLockPattern extends SettingsActivity {
return this;
}
/**
* Configures the launch such that at the end of the pattern enrollment, one of its
* managed profile (specified by {@code profileId}) will have its lockscreen unified
* to the parent user. The profile's current lockscreen credential needs to be specified by
* {@code credential}.
*/
public IntentBuilder setProfileToUnify(int profileId, LockscreenCredential credential) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, profileId);
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL,
credential);
return this;
}
public Intent build() {
return mIntent;
}
@@ -810,8 +828,18 @@ public class ChooseLockPattern extends SettingsActivity {
FRAGMENT_TAG_SAVE_AND_FINISH).commit();
getFragmentManager().executePendingTransactions();
final boolean required = getActivity().getIntent().getBooleanExtra(
final Intent intent = getActivity().getIntent();
final boolean required = intent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
if (intent.hasExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID)) {
try (LockscreenCredential profileCredential = (LockscreenCredential)
intent.getParcelableExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) {
mSaveAndFinishWorker.setProfileToUnify(
intent.getIntExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID,
UserHandle.USER_NULL),
profileCredential);
}
}
mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required,
mHasChallenge, mChallenge, mChosenPattern, mCurrentCredential, mUserId);
}
@@ -863,6 +891,9 @@ public class ChooseLockPattern extends SettingsActivity {
final int userId = mUserId;
final boolean success = mUtils.setLockCredential(mChosenPattern, mCurrentCredential,
userId);
if (success) {
unifyProfileCredentialIfRequested();
}
Intent result = null;
if (success && mHasChallenge) {
byte[] token;

View File

@@ -33,6 +33,7 @@ import androidx.fragment.app.Fragment;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -49,6 +50,17 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
/**
* When EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL and EXTRA_KEY_UNIFICATION_PROFILE_ID are
* provided to ChooseLockGeneric as fragment arguments {@link SubSettingLauncher#setArguments},
* at the end of the password change flow, the supplied profile user
* (EXTRA_KEY_UNIFICATION_PROFILE_ID) will be unified to its parent. The current profile
* password is supplied by EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL.
*/
public static final String EXTRA_KEY_UNIFICATION_PROFILE_ID = "unification_profile_id";
public static final String EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL =
"unification_profile_credential";
/**
* Intent extra for passing the requested min password complexity to later steps in the set new
* screen lock flow.

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Pair;
import android.widget.Toast;
@@ -27,6 +28,7 @@ import android.widget.Toast;
import androidx.fragment.app.Fragment;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R;
/**
@@ -44,6 +46,8 @@ abstract class SaveChosenLockWorkerBase extends Fragment {
protected long mChallenge;
protected boolean mWasSecureBefore;
protected int mUserId;
protected int mUnificationProfileId = UserHandle.USER_NULL;
protected LockscreenCredential mUnificationProfileCredential;
private boolean mBlocking;
@@ -106,12 +110,27 @@ abstract class SaveChosenLockWorkerBase extends Fragment {
if (mListener != null) {
mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
}
if (mUnificationProfileCredential != null) {
mUnificationProfileCredential.zeroize();
}
}
public void setBlocking(boolean blocking) {
mBlocking = blocking;
}
public void setProfileToUnify(int profileId, LockscreenCredential credential) {
mUnificationProfileId = profileId;
mUnificationProfileCredential = credential.duplicate();
}
protected void unifyProfileCredentialIfRequested() {
if (mUnificationProfileId != UserHandle.USER_NULL) {
mUtils.setSeparateProfileChallengeEnabled(mUnificationProfileId, false,
mUnificationProfileCredential);
}
}
private class Task extends AsyncTask<Void, Void, Pair<Boolean, Intent>> {
@Override