summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/settings/password/ChooseLockGeneric.java90
-rw-r--r--src/com/android/settings/password/ChooseLockPassword.java40
-rw-r--r--src/com/android/settings/password/ChooseLockPattern.java33
-rw-r--r--src/com/android/settings/password/ChooseLockSettingsHelper.java12
-rw-r--r--src/com/android/settings/password/SaveChosenLockWorkerBase.java19
-rw-r--r--src/com/android/settings/security/LockUnificationPreferenceController.java95
-rw-r--r--src/com/android/settings/security/SecuritySettings.java1
-rw-r--r--tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java52
-rw-r--r--tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java15
-rw-r--r--tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java15
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() {