Support remote device credentials validation in UI.
Test: m RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.password Test: Manual Bug: 258505917 Change-Id: Ifb9f15728eb8396b34c844d28f71a8e6e1aad837
This commit is contained in:
@@ -27,6 +27,8 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROF
|
||||
import static android.app.admin.DevicePolicyResources.UNDEFINED;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.RemoteLockscreenValidationResult;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
@@ -42,6 +44,7 @@ import android.os.UserManager;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -114,13 +117,13 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_content);
|
||||
if (fragment != null && fragment instanceof ConfirmLockPasswordFragment) {
|
||||
((ConfirmLockPasswordFragment)fragment).onWindowFocusChanged(hasFocus);
|
||||
((ConfirmLockPasswordFragment) fragment).onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment
|
||||
implements OnClickListener, OnEditorActionListener,
|
||||
CredentialCheckResultTracker.Listener {
|
||||
CredentialCheckResultTracker.Listener, SaveChosenLockWorkerBase.Listener {
|
||||
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
|
||||
private ImeAwareEditText mPasswordEntry;
|
||||
private TextViewInputDisabler mPasswordEntryInputDisabler;
|
||||
@@ -134,6 +137,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
private DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
private boolean mIsManagedProfile;
|
||||
private GlifLayout mGlifLayout;
|
||||
private CharSequence mCheckBoxLabel;
|
||||
|
||||
// required constructor for fragments
|
||||
public ConfirmLockPasswordFragment() {
|
||||
@@ -160,11 +164,19 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
mPasswordEntry.requestFocus();
|
||||
mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
|
||||
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
|
||||
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_MANAGED == storedQuality;
|
||||
|
||||
if (mRemoteValidation) {
|
||||
mIsAlpha = mStartLockscreenValidationRequest.getLockscreenUiType()
|
||||
== KeyguardManager.PASSWORD;
|
||||
// ProgressBar visibility is set to GONE until interacted with.
|
||||
// Set progress bar to INVISIBLE, so the EditText does not get bumped down later.
|
||||
mGlifLayout.setProgressBarShown(false);
|
||||
} else {
|
||||
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality
|
||||
|| DevicePolicyManager.PASSWORD_QUALITY_MANAGED == storedQuality;
|
||||
}
|
||||
mImm = (InputMethodManager) getActivity().getSystemService(
|
||||
Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
@@ -187,6 +199,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
mGlifLayout.setHeaderText(headerMessage);
|
||||
mGlifLayout.setDescriptionText(detailsMessage);
|
||||
mCheckBoxLabel = intent.getCharSequenceExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL);
|
||||
}
|
||||
int currentType = mPasswordEntry.getInputType();
|
||||
if (mIsAlpha) {
|
||||
@@ -227,6 +240,19 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
if (mRemoteValidation) {
|
||||
if (mCheckBox != null) {
|
||||
mCheckBox.setText(TextUtils.isEmpty(mCheckBoxLabel)
|
||||
? getDefaultCheckboxLabel()
|
||||
: mCheckBoxLabel);
|
||||
}
|
||||
if (mCancelButton != null && TextUtils.isEmpty(mAlternateButtonText)) {
|
||||
mCancelButton.setText(mIsAlpha
|
||||
? R.string.lockpassword_forgot_password
|
||||
: R.string.lockpassword_forgot_pin);
|
||||
}
|
||||
}
|
||||
|
||||
if (mForgotButton != null) {
|
||||
mForgotButton.setText(mIsAlpha
|
||||
? R.string.lockpassword_forgot_password
|
||||
@@ -237,7 +263,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mPasswordEntry.setText(null);
|
||||
if (mPasswordEntry != null) {
|
||||
mPasswordEntry.setText(null);
|
||||
}
|
||||
// Force a garbage collection to remove remnant of user password shards from memory.
|
||||
// Execute this with a slight delay to allow the activity lifecycle to complete and
|
||||
// the instance to become gc-able.
|
||||
@@ -253,6 +281,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
return mIsAlpha ? getString(R.string.lockpassword_confirm_your_password_header_frp)
|
||||
: getString(R.string.lockpassword_confirm_your_pin_header_frp);
|
||||
}
|
||||
if (mRemoteValidation) {
|
||||
return getString(R.string.lockpassword_remote_validation_header);
|
||||
}
|
||||
if (mIsManagedProfile) {
|
||||
if (mIsAlpha) {
|
||||
return mDevicePolicyManager.getResources().getString(
|
||||
@@ -273,6 +304,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
return mIsAlpha ? getString(R.string.lockpassword_confirm_your_password_details_frp)
|
||||
: getString(R.string.lockpassword_confirm_your_pin_details_frp);
|
||||
}
|
||||
if (mRemoteValidation) {
|
||||
return getContext().getString(mIsAlpha
|
||||
? R.string.lockpassword_remote_validation_password_details
|
||||
: R.string.lockpassword_remote_validation_pin_details);
|
||||
}
|
||||
boolean isStrongAuthRequired = isStrongAuthRequired();
|
||||
// Map boolean flags to an index by isStrongAuth << 2 + isManagedProfile << 1 + isAlpha.
|
||||
int index = ((isStrongAuthRequired ? 1 : 0) << 2) + ((mIsManagedProfile ? 1 : 0) << 1)
|
||||
@@ -281,6 +317,16 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
DETAIL_TEXT_OVERRIDES[index], () -> getString(DETAIL_TEXTS[index]));
|
||||
}
|
||||
|
||||
private String getDefaultCheckboxLabel() {
|
||||
if (mRemoteValidation) {
|
||||
return getString(mIsAlpha
|
||||
? R.string.lockpassword_remote_validation_set_password_as_screenlock
|
||||
: R.string.lockpassword_remote_validation_set_pin_as_screenlock);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Trying to get default checkbox label for illegal flow");
|
||||
}
|
||||
|
||||
private int getErrorMessage() {
|
||||
return mIsAlpha ? R.string.lockpassword_invalid_password
|
||||
: R.string.lockpassword_invalid_pin;
|
||||
@@ -392,6 +438,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
mImm.hideSoftInputFromWindow(mPasswordEntry.getWindowToken(), 0 /*flags*/);
|
||||
} else {
|
||||
mPasswordEntry.scheduleShowSoftInput();
|
||||
mPasswordEntry.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,12 +460,18 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
if (TextUtils.isEmpty(passwordText)) {
|
||||
return;
|
||||
}
|
||||
final LockscreenCredential credential =
|
||||
mIsAlpha ? LockscreenCredential.createPassword(passwordText)
|
||||
final LockscreenCredential credential = mIsAlpha
|
||||
? LockscreenCredential.createPassword(passwordText)
|
||||
: LockscreenCredential.createPin(passwordText);
|
||||
|
||||
mPasswordEntryInputDisabler.setInputEnabled(false);
|
||||
|
||||
if (mRemoteValidation) {
|
||||
validateGuess(credential);
|
||||
mGlifLayout.setProgressBarShown(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
// TODO(b/161956762): Sanitize this
|
||||
if (mReturnGatekeeperPassword) {
|
||||
@@ -546,6 +599,44 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemoteDeviceCredentialValidationResult(
|
||||
RemoteLockscreenValidationResult result) {
|
||||
switch (result.getResultCode()) {
|
||||
case RemoteLockscreenValidationResult.RESULT_GUESS_VALID:
|
||||
if (mCheckBox.isChecked()) {
|
||||
ChooseLockPassword.SaveAndFinishWorker saveAndFinishWorker =
|
||||
new ChooseLockPassword.SaveAndFinishWorker();
|
||||
Log.i(TAG, "Setting device screen lock to the other device's screen lock.");
|
||||
getFragmentManager().beginTransaction().add(saveAndFinishWorker, null)
|
||||
.commit();
|
||||
getFragmentManager().executePendingTransactions();
|
||||
saveAndFinishWorker.setListener(this);
|
||||
saveAndFinishWorker.start(
|
||||
mLockPatternUtils,
|
||||
/* requestGatekeeperPassword= */ false,
|
||||
mDeviceCredentialGuess,
|
||||
/* currentCredential= */ null,
|
||||
mEffectiveUserId);
|
||||
return;
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(/* matched= */ true, new Intent(),
|
||||
/* timeoutMs= */ 0, mEffectiveUserId);
|
||||
break;
|
||||
case RemoteLockscreenValidationResult.RESULT_GUESS_INVALID:
|
||||
mCredentialCheckResultTracker.setResult(/* matched= */ false, new Intent(),
|
||||
/* timeoutMs= */ 0, mEffectiveUserId);
|
||||
break;
|
||||
case RemoteLockscreenValidationResult.RESULT_LOCKOUT:
|
||||
mCredentialCheckResultTracker.setResult(/* matched= */ false, new Intent(),
|
||||
(int) result.getTimeoutMillis(), mEffectiveUserId);
|
||||
break;
|
||||
case RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS:
|
||||
getActivity().finish();
|
||||
}
|
||||
mGlifLayout.setProgressBarShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId, boolean newResult) {
|
||||
@@ -601,5 +692,19 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for when the device credential guess used for remote validation was set as the
|
||||
* current device's device credential.
|
||||
*/
|
||||
@Override
|
||||
public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
|
||||
if (mDeviceCredentialGuess != null) {
|
||||
mDeviceCredentialGuess.zeroize();
|
||||
}
|
||||
mGlifLayout.setProgressBarShown(false);
|
||||
mCredentialCheckResultTracker.setResult(/* matched= */ true, new Intent(),
|
||||
/* timeoutMs= */ 0, mEffectiveUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user