diff options
10 files changed, 279 insertions, 93 deletions
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 5beacdd595..f55d65c165 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -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(); } diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index ff94d8b895..ebfc1afb43 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -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; diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java index b5670cacc4..ece3da8f24 100644 --- a/src/com/android/settings/password/ChooseLockPattern.java +++ b/src/com/android/settings/password/ChooseLockPattern.java @@ -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; diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java index 3353d62053..3989ee66f0 100644 --- a/src/com/android/settings/password/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java @@ -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; @@ -50,6 +51,17 @@ public final class ChooseLockSettingsHelper { 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. */ diff --git a/src/com/android/settings/password/SaveChosenLockWorkerBase.java b/src/com/android/settings/password/SaveChosenLockWorkerBase.java index 2798b3d7f4..26e4d5aa8a 100644 --- a/src/com/android/settings/password/SaveChosenLockWorkerBase.java +++ b/src/com/android/settings/password/SaveChosenLockWorkerBase.java @@ -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 diff --git a/src/com/android/settings/security/LockUnificationPreferenceController.java b/src/com/android/settings/security/LockUnificationPreferenceController.java index 4bac601cf2..9cacf8e2ec 100644 --- a/src/com/android/settings/security/LockUnificationPreferenceController.java +++ b/src/com/android/settings/security/LockUnificationPreferenceController.java @@ -16,7 +16,6 @@ package com.android.settings.security; -import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_DEVICE_REQUEST; import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_PROFILE_REQUEST; import static com.android.settings.security.SecuritySettings.UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST; @@ -48,12 +47,14 @@ import com.android.settingslib.core.AbstractPreferenceController; * Controller for password unification/un-unification flows. * * When password is being unified, there may be two cases: - * 1. If work password is not empty and satisfies device-wide policies (if any), it will be made - * into device-wide password. To do that we need both current device and profile passwords - * because both of them will be changed as a result. - * 2. Otherwise device-wide password is preserved. In this case we only need current profile - * password, but after unifying the passwords we proceed to ask the user for a new device - * password. + * 1. If device password will satisfy device-wide policies post-unification (when password policy + * set on the work challenge will be enforced on device password), the device password is + * preserved while work challenge is unified. Only the current work challenge is required + * in this flow. + * 2. Otherwise the user will need to enroll a new compliant device password before unification + * takes place. In this case we first confirm the current work challenge, then guide the user + * through an enrollment flow for the new device password, and finally unify the work challenge + * at the very end. */ public class LockUnificationPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { @@ -73,7 +74,7 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr private LockscreenCredential mCurrentDevicePassword; private LockscreenCredential mCurrentProfilePassword; - private boolean mKeepDeviceLock; + private boolean mRequireNewDevicePassword; @Override public void displayPreference(PreferenceScreen screen) { @@ -112,13 +113,9 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr } final boolean useOneLock = (Boolean) value; if (useOneLock) { - // Keep current device (personal) lock if the profile lock is empty or is not compliant - // with the policy on personal side. - mKeepDeviceLock = - mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId) - < DevicePolicyManager.PASSWORD_QUALITY_SOMETHING - || !mDpm.isProfileActivePasswordSufficientForParent(mProfileUserId); - UnificationConfirmationDialog.newInstance(!mKeepDeviceLock).show(mHost); + mRequireNewDevicePassword = !mDpm.isPasswordSufficientAfterProfileUnification( + UserHandle.myUserId(), mProfileUserId); + startUnification(); } else { final String title = mContext.getString(R.string.unlock_set_unlock_launch_picker_title); final ChooseLockSettingsHelper helper = @@ -149,13 +146,9 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST && resultCode == Activity.RESULT_OK) { - ununifyLocks(); - return true; - } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST - && resultCode == Activity.RESULT_OK) { mCurrentDevicePassword = data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); - launchConfirmProfileLock(); + ununifyLocks(); return true; } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST && resultCode == Activity.RESULT_OK) { @@ -170,67 +163,44 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr private void ununifyLocks() { final Bundle extras = new Bundle(); extras.putInt(Intent.EXTRA_USER_ID, mProfileUserId); + extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mCurrentDevicePassword); new SubSettingLauncher(mContext) .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName()) - .setTitleRes(R.string.lock_settings_picker_title_profile) + .setTitleRes(R.string.lock_settings_picker_title_profile) .setSourceMetricsCategory(mHost.getMetricsCategory()) .setArguments(extras) .launch(); } - /** Asks the user to confirm device lock (if there is one) and proceeds to ask profile lock. */ - private void launchConfirmDeviceAndProfileLock() { - final String title = mContext.getString( - R.string.unlock_set_unlock_launch_picker_title); - final ChooseLockSettingsHelper helper = - new ChooseLockSettingsHelper(mHost.getActivity(), mHost); - if (!helper.launchConfirmationActivity( - UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) { - launchConfirmProfileLock(); - } - } - - private void launchConfirmProfileLock() { + void startUnification() { + // Confirm profile lock final String title = mContext.getString( R.string.unlock_set_unlock_launch_picker_title_profile); final ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(mHost.getActivity(), mHost); if (!helper.launchConfirmationActivity( UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileUserId)) { + // If profile has no lock, go straight to unification. unifyLocks(); // TODO: update relevant prefs. // createPreferenceHierarchy(); } } - void startUnification() { - // If the device lock stays the same, only confirm profile lock. Otherwise confirm both. - if (mKeepDeviceLock) { - launchConfirmProfileLock(); - } else { - launchConfirmDeviceAndProfileLock(); - } - } - private void unifyLocks() { - if (mKeepDeviceLock) { - unifyKeepingDeviceLock(); - promptForNewDeviceLock(); + if (mRequireNewDevicePassword) { + promptForNewDeviceLockAndThenUnify(); } else { - unifyKeepingWorkLock(); + unifyKeepingDeviceLock(); + } + if (mCurrentDevicePassword != null) { + mCurrentDevicePassword.zeroize(); + mCurrentDevicePassword = null; + } + if (mCurrentProfilePassword != null) { + mCurrentProfilePassword.zeroize(); + mCurrentProfilePassword = null; } - mCurrentDevicePassword = null; - mCurrentProfilePassword = null; - } - - private void unifyKeepingWorkLock() { - mLockPatternUtils.setLockCredential( - mCurrentProfilePassword, mCurrentDevicePassword, MY_USER_ID); - mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileUserId, false, - mCurrentProfilePassword); - final boolean profilePatternVisibility = - mLockPatternUtils.isVisiblePatternEnabled(mProfileUserId); - mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID); } private void unifyKeepingDeviceLock() { @@ -238,11 +208,16 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr mCurrentProfilePassword); } - private void promptForNewDeviceLock() { + private void promptForNewDeviceLockAndThenUnify() { + final Bundle extras = new Bundle(); + extras.putInt(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, mProfileUserId); + extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL, + mCurrentProfilePassword); new SubSettingLauncher(mContext) .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName()) .setTitleRes(R.string.lock_settings_picker_title) .setSourceMetricsCategory(mHost.getMetricsCategory()) + .setArguments(extras) .launch(); } diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java index effbd70dc8..c8288c6c7f 100644 --- a/src/com/android/settings/security/SecuritySettings.java +++ b/src/com/android/settings/security/SecuritySettings.java @@ -47,7 +47,6 @@ public class SecuritySettings extends DashboardFragment { private static final String WORK_PROFILE_SECURITY_CATEGORY = "security_category_profile"; public static final int CHANGE_TRUST_AGENT_SETTINGS = 126; - public static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128; public static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129; public static final int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130; diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java index 8340243cf4..b535bc142d 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java @@ -35,12 +35,14 @@ import static org.robolectric.Shadows.shadowOf; import android.app.Activity; import android.app.admin.DevicePolicyManager; import android.content.Intent; +import android.os.Bundle; import android.provider.Settings.Global; import androidx.annotation.Nullable; import androidx.preference.Preference; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockscreenCredential; import com.android.settings.R; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment; @@ -312,6 +314,56 @@ public class ChooseLockGenericTest { .isEqualTo("app name"); } + @Test + public void testUnifyProfile_IntentPassedToChooseLockPassword() { + final Bundle arguments = new Bundle(); + arguments.putInt(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 11); + arguments.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL, + LockscreenCredential.createNone()); + mFragment.setArguments(arguments); + + Intent intent = new Intent().putExtra( + LockPatternUtils.PASSWORD_TYPE_KEY, + DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); + initActivity(intent); + + mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */); + + Intent nextIntent = shadowOf(mActivity).getNextStartedActivity(); + assertThat(nextIntent).isNotNull(); + assertThat(nextIntent.getComponent().getClassName()).isEqualTo( + ChooseLockPassword.class.getName()); + assertThat(nextIntent.getIntExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 0)).isEqualTo(11); + assertThat((LockscreenCredential) nextIntent.getParcelableExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)).isNotNull(); + } + + @Test + public void testUnifyProfile_IntentPassedToChooseLockPattern() { + final Bundle arguments = new Bundle(); + arguments.putInt(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 13); + arguments.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL, + LockscreenCredential.createNone()); + mFragment.setArguments(arguments); + + Intent intent = new Intent().putExtra( + LockPatternUtils.PASSWORD_TYPE_KEY, + DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); + initActivity(intent); + + mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */); + + Intent nextIntent = shadowOf(mActivity).getNextStartedActivity(); + assertThat(nextIntent).isNotNull(); + assertThat(nextIntent.getComponent().getClassName()).isEqualTo( + ChooseLockPattern.class.getName()); + assertThat(nextIntent.getIntExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 0)).isEqualTo(13); + assertThat((LockscreenCredential) nextIntent.getParcelableExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)).isNotNull(); + } + private void initActivity(@Nullable Intent intent) { if (intent == null) { intent = new Intent(); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java index 4bbf51d981..5ec6f41abb 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java @@ -148,6 +148,21 @@ public class ChooseLockPasswordTest { } @Test + public void intentBuilder_setProfileToUnify_shouldAddExtras() { + Intent intent = new IntentBuilder(application) + .setProfileToUnify(23, LockscreenCredential.createNone()) + .build(); + + assertThat(intent.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 0)) + .named("EXTRA_KEY_UNIFICATION_PROFILE_ID") + .isEqualTo(23); + assertThat((LockscreenCredential) intent.getParcelableExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) + .named("EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL") + .isNotNull(); + } + + @Test public void processAndValidatePasswordRequirements_noMinPasswordComplexity() { mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_ALPHABETIC); mShadowDpm.setPasswordMinimumLength(10); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java index 01007449fd..557e7c169c 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java @@ -92,6 +92,21 @@ public class ChooseLockPatternTest { .isEqualTo(123); } + @Test + public void intentBuilder_setProfileToUnify_shouldAddExtras() { + Intent intent = new IntentBuilder(application) + .setProfileToUnify(23, LockscreenCredential.createNone()) + .build(); + + assertThat(intent.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID, 0)) + .named("EXTRA_KEY_UNIFICATION_PROFILE_ID") + .isEqualTo(23); + assertThat((LockscreenCredential) intent.getParcelableExtra( + ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) + .named("EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL") + .isNotNull(); + } + @Config(qualifiers = "sw400dp") @Test public void fingerprintExtraSet_shouldDisplayFingerprintIcon() { |