Merge changes from topic "simplify_pw" into udc-qpr-dev am: e414d40e60 am: 3f4b3fdce8

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/23840849

Change-Id: I3e2974a91c86aecf459ce51f9afdbf6175b8faed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Chun-Wei Wang
2023-07-18 02:36:44 +00:00
committed by Automerger Merge Worker
10 changed files with 384 additions and 255 deletions

View File

@@ -33,6 +33,7 @@ import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_C
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
@@ -795,6 +796,9 @@ public class ChooseLockGeneric extends SettingsActivity {
if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) { if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped); intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
} }
if (getIntent().getBooleanExtra(EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false)) {
intent.putExtra(EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, true);
}
intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras()); intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
// If the caller requested Gatekeeper Password Handle to be returned, we assume it // If the caller requested Gatekeeper Password Handle to be returned, we assume it
// came from biometric enrollment. onActivityResult will put the LockSettingsService // came from biometric enrollment. onActivityResult will put the LockSettingsService

View File

@@ -65,7 +65,6 @@ import android.text.Spannable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -89,7 +88,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential; import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.PasswordValidationError; import com.android.internal.widget.PasswordValidationError;
import com.android.internal.widget.TextViewInputDisabler; import com.android.internal.widget.TextViewInputDisabler;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.SetupWizardUtils; import com.android.settings.SetupWizardUtils;
@@ -236,6 +234,7 @@ public class ChooseLockPassword extends SettingsActivity {
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
private LockscreenCredential mChosenPassword; private LockscreenCredential mChosenPassword;
private boolean mRequestGatekeeperPassword; private boolean mRequestGatekeeperPassword;
private boolean mRequestWriteRepairModePassword;
private ImeAwareEditText mPasswordEntry; private ImeAwareEditText mPasswordEntry;
private TextViewInputDisabler mPasswordEntryInputDisabler; private TextViewInputDisabler mPasswordEntryInputDisabler;
@@ -565,6 +564,8 @@ public class ChooseLockPassword extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mRequestGatekeeperPassword = intent.getBooleanExtra( mRequestGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
mRequestWriteRepairModePassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false);
if (savedInstanceState == null) { if (savedInstanceState == null) {
updateStage(Stage.Introduction); updateStage(Stage.Introduction);
if (confirmCredentials) { if (confirmCredentials) {
@@ -574,6 +575,7 @@ public class ChooseLockPassword extends SettingsActivity {
.setTitle(getString(R.string.unlock_set_unlock_launch_picker_title)) .setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
.setReturnCredentials(true) .setReturnCredentials(true)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword) .setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword)
.setRequestWriteRepairModePassword(mRequestWriteRepairModePassword)
.setUserId(mUserId) .setUserId(mUserId)
.show(); .show();
} }
@@ -1034,7 +1036,10 @@ public class ChooseLockPassword extends SettingsActivity {
setNextEnabled(false); setNextEnabled(false);
mSaveAndFinishWorker = new SaveAndFinishWorker(); mSaveAndFinishWorker = new SaveAndFinishWorker();
mSaveAndFinishWorker.setListener(this); mSaveAndFinishWorker
.setListener(this)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword)
.setRequestWriteRepairModePassword(mRequestWriteRepairModePassword);
getFragmentManager().beginTransaction().add(mSaveAndFinishWorker, getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
FRAGMENT_TAG_SAVE_AND_FINISH).commit(); FRAGMENT_TAG_SAVE_AND_FINISH).commit();
@@ -1054,7 +1059,7 @@ public class ChooseLockPassword extends SettingsActivity {
(mAutoPinConfirmOption != null && mAutoPinConfirmOption.isChecked()), (mAutoPinConfirmOption != null && mAutoPinConfirmOption.isChecked()),
mUserId); mUserId);
mSaveAndFinishWorker.start(mLockPatternUtils, mRequestGatekeeperPassword, mSaveAndFinishWorker.start(mLockPatternUtils,
mChosenPassword, mCurrentCredential, mUserId); mChosenPassword, mCurrentCredential, mUserId);
} }
@@ -1107,50 +1112,4 @@ public class ChooseLockPassword extends SettingsActivity {
} }
} }
} }
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private LockscreenCredential mChosenPassword;
private LockscreenCredential mCurrentCredential;
public void start(LockPatternUtils utils, boolean requestGatekeeperPassword,
LockscreenCredential chosenPassword, LockscreenCredential currentCredential,
int userId) {
prepare(utils, requestGatekeeperPassword, userId);
mChosenPassword = chosenPassword;
mCurrentCredential = currentCredential != null ? currentCredential
: LockscreenCredential.createNone();
mUserId = userId;
start();
}
@Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final boolean success = mUtils.setLockCredential(
mChosenPassword, mCurrentCredential, mUserId);
if (success) {
unifyProfileCredentialIfRequested();
}
Intent result = null;
if (success && mRequestGatekeeperPassword) {
// If a Gatekeeper Password was requested, invoke the LockSettingsService code
// path to return a Gatekeeper Password based on the credential that the user
// chose. This should only be run if the credential was successfully set.
final VerifyCredentialResponse response = mUtils.verifyCredential(mChosenPassword,
mUserId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE);
if (!response.isMatched() || !response.containsGatekeeperPasswordHandle()) {
Log.e(TAG, "critical: bad response or missing GK PW handle for known good"
+ " password: " + response.toString());
}
result = new Intent();
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
response.getGatekeeperPasswordHandle());
}
return Pair.create(success, result);
}
}
} }

View File

@@ -34,7 +34,6 @@ import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -53,7 +52,6 @@ import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell; import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockPatternView.DisplayMode; import com.android.internal.widget.LockPatternView.DisplayMode;
import com.android.internal.widget.LockscreenCredential; import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.SetupWizardUtils; import com.android.settings.SetupWizardUtils;
@@ -206,6 +204,7 @@ public class ChooseLockPattern extends SettingsActivity {
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
private boolean mRequestGatekeeperPassword; private boolean mRequestGatekeeperPassword;
private boolean mRequestWriteRepairModePassword;
protected TextView mHeaderText; protected TextView mHeaderText;
protected LockPatternView mLockPatternView; protected LockPatternView mLockPatternView;
protected TextView mFooterText; protected TextView mFooterText;
@@ -563,6 +562,8 @@ public class ChooseLockPattern extends SettingsActivity {
intent.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); intent.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mRequestGatekeeperPassword = intent.getBooleanExtra( mRequestGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
mRequestWriteRepairModePassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false);
if (savedInstanceState == null) { if (savedInstanceState == null) {
if (confirmCredentials) { if (confirmCredentials) {
@@ -576,6 +577,7 @@ public class ChooseLockPattern extends SettingsActivity {
.setTitle(getString(R.string.unlock_set_unlock_launch_picker_title)) .setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
.setReturnCredentials(true) .setReturnCredentials(true)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword) .setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword)
.setRequestWriteRepairModePassword(mRequestWriteRepairModePassword)
.setUserId(mUserId) .setUserId(mUserId)
.show(); .show();
@@ -827,7 +829,10 @@ public class ChooseLockPattern extends SettingsActivity {
setRightButtonEnabled(false); setRightButtonEnabled(false);
mSaveAndFinishWorker = new SaveAndFinishWorker(); mSaveAndFinishWorker = new SaveAndFinishWorker();
mSaveAndFinishWorker.setListener(this); mSaveAndFinishWorker
.setListener(this)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPassword)
.setRequestWriteRepairModePassword(mRequestWriteRepairModePassword);
getFragmentManager().beginTransaction().add(mSaveAndFinishWorker, getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
FRAGMENT_TAG_SAVE_AND_FINISH).commit(); FRAGMENT_TAG_SAVE_AND_FINISH).commit();
@@ -843,7 +848,7 @@ public class ChooseLockPattern extends SettingsActivity {
profileCredential); profileCredential);
} }
} }
mSaveAndFinishWorker.start(mLockPatternUtils, mRequestGatekeeperPassword, mSaveAndFinishWorker.start(mLockPatternUtils,
mChosenPattern, mCurrentCredential, mUserId); mChosenPattern, mCurrentCredential, mUserId);
} }
@@ -867,51 +872,4 @@ public class ChooseLockPattern extends SettingsActivity {
getActivity().finish(); getActivity().finish();
} }
} }
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private LockscreenCredential mChosenPattern;
private LockscreenCredential mCurrentCredential;
public void start(LockPatternUtils utils, boolean requestGatekeeperPassword,
LockscreenCredential chosenPattern, LockscreenCredential currentCredential,
int userId) {
prepare(utils, requestGatekeeperPassword, userId);
mCurrentCredential = currentCredential != null ? currentCredential
: LockscreenCredential.createNone();
mChosenPattern = chosenPattern;
mUserId = userId;
start();
}
@Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final int userId = mUserId;
final boolean success = mUtils.setLockCredential(mChosenPattern, mCurrentCredential,
userId);
if (success) {
unifyProfileCredentialIfRequested();
}
Intent result = null;
if (success && mRequestGatekeeperPassword) {
// If a Gatekeeper Password was requested, invoke the LockSettingsService code
// path to return a Gatekeeper Password based on the credential that the user
// chose. This should only be run if the credential was successfully set.
final VerifyCredentialResponse response = mUtils.verifyCredential(mChosenPattern,
userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE);
if (!response.isMatched() || !response.containsGatekeeperPasswordHandle()) {
Log.e(TAG, "critical: bad response or missing GK PW handle for known good"
+ " pattern: " + response.toString());
}
result = new Intent();
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
response.getGatekeeperPasswordHandle());
}
return Pair.create(success, result);
}
}
} }

View File

@@ -73,6 +73,8 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_GK_PW_HANDLE = "gk_pw_handle"; public static final String EXTRA_KEY_GK_PW_HANDLE = "gk_pw_handle";
public static final String EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW = public static final String EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW =
"request_write_repair_mode_pw"; "request_write_repair_mode_pw";
public static final String EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL =
"wrote_repair_mode_credential";
/** /**
* When EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL and EXTRA_KEY_UNIFICATION_PROFILE_ID are * When EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL and EXTRA_KEY_UNIFICATION_PROFILE_ID are

View File

@@ -125,7 +125,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment
implements OnClickListener, OnEditorActionListener, implements OnClickListener, OnEditorActionListener,
CredentialCheckResultTracker.Listener, SaveChosenLockWorkerBase.Listener, CredentialCheckResultTracker.Listener, SaveAndFinishWorker.Listener,
RemoteLockscreenValidationFragment.Listener { RemoteLockscreenValidationFragment.Listener {
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result"; private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
private ImeAwareEditText mPasswordEntry; private ImeAwareEditText mPasswordEntry;
@@ -633,15 +633,15 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
if (mCheckBox.isChecked() && mRemoteLockscreenValidationFragment if (mCheckBox.isChecked() && mRemoteLockscreenValidationFragment
.getLockscreenCredential() != null) { .getLockscreenCredential() != null) {
Log.i(TAG, "Setting device screen lock to the other device's screen lock."); Log.i(TAG, "Setting device screen lock to the other device's screen lock.");
ChooseLockPassword.SaveAndFinishWorker saveAndFinishWorker = SaveAndFinishWorker saveAndFinishWorker = new SaveAndFinishWorker();
new ChooseLockPassword.SaveAndFinishWorker();
getFragmentManager().beginTransaction().add(saveAndFinishWorker, null) getFragmentManager().beginTransaction().add(saveAndFinishWorker, null)
.commit(); .commit();
getFragmentManager().executePendingTransactions(); getFragmentManager().executePendingTransactions();
saveAndFinishWorker.setListener(this); saveAndFinishWorker
.setListener(this)
.setRequestGatekeeperPasswordHandle(true);
saveAndFinishWorker.start( saveAndFinishWorker.start(
mLockPatternUtils, mLockPatternUtils,
/* requestGatekeeperPassword= */ true,
mRemoteLockscreenValidationFragment.getLockscreenCredential(), mRemoteLockscreenValidationFragment.getLockscreenCredential(),
/* currentCredential= */ null, /* currentCredential= */ null,
mEffectiveUserId); mEffectiveUserId);

View File

@@ -93,7 +93,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment
implements AppearAnimationCreator<Object>, CredentialCheckResultTracker.Listener, implements AppearAnimationCreator<Object>, CredentialCheckResultTracker.Listener,
SaveChosenLockWorkerBase.Listener, RemoteLockscreenValidationFragment.Listener { SaveAndFinishWorker.Listener, RemoteLockscreenValidationFragment.Listener {
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result"; private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
@@ -630,15 +630,15 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
if (mCheckBox.isChecked() && mRemoteLockscreenValidationFragment if (mCheckBox.isChecked() && mRemoteLockscreenValidationFragment
.getLockscreenCredential() != null) { .getLockscreenCredential() != null) {
Log.i(TAG, "Setting device screen lock to the other device's screen lock."); Log.i(TAG, "Setting device screen lock to the other device's screen lock.");
ChooseLockPattern.SaveAndFinishWorker saveAndFinishWorker = SaveAndFinishWorker saveAndFinishWorker = new SaveAndFinishWorker();
new ChooseLockPattern.SaveAndFinishWorker();
getFragmentManager().beginTransaction().add(saveAndFinishWorker, null) getFragmentManager().beginTransaction().add(saveAndFinishWorker, null)
.commit(); .commit();
getFragmentManager().executePendingTransactions(); getFragmentManager().executePendingTransactions();
saveAndFinishWorker.setListener(this); saveAndFinishWorker
.setListener(this)
.setRequestGatekeeperPasswordHandle(true);
saveAndFinishWorker.start( saveAndFinishWorker.start(
mLockPatternUtils, mLockPatternUtils,
/* requestGatekeeperPassword= */ true,
mRemoteLockscreenValidationFragment.getLockscreenCredential(), mRemoteLockscreenValidationFragment.getLockscreenCredential(),
/* currentCredential= */ null, /* currentCredential= */ null,
mEffectiveUserId); mEffectiveUserId);

View File

@@ -0,0 +1,213 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.password;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.settings.R;
import com.android.settings.safetycenter.LockScreenSafetySource;
/**
* An invisible retained worker fragment to track the AsyncWork that saves (and optionally
* verifies if a challenge is given) the chosen lock credential (pattern/pin/password).
*/
public class SaveAndFinishWorker extends Fragment {
private static final String TAG = "SaveAndFinishWorker";
private Listener mListener;
private boolean mFinished;
private Intent mResultData;
private LockPatternUtils mUtils;
private boolean mRequestGatekeeperPassword;
private boolean mRequestWriteRepairModePassword;
private boolean mWasSecureBefore;
private int mUserId;
private int mUnificationProfileId = UserHandle.USER_NULL;
private LockscreenCredential mUnificationProfileCredential;
private LockscreenCredential mChosenCredential;
private LockscreenCredential mCurrentCredential;
private boolean mBlocking;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public SaveAndFinishWorker setListener(Listener listener) {
if (mListener == listener) {
return this;
}
mListener = listener;
if (mFinished && mListener != null) {
mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
}
return this;
}
@VisibleForTesting
void prepare(LockPatternUtils utils, LockscreenCredential chosenCredential,
LockscreenCredential currentCredential, int userId) {
mUtils = utils;
mUserId = userId;
// This will be a no-op for non managed profiles.
mWasSecureBefore = mUtils.isSecure(mUserId);
mFinished = false;
mResultData = null;
mChosenCredential = chosenCredential;
mCurrentCredential = currentCredential != null ? currentCredential
: LockscreenCredential.createNone();
}
public void start(LockPatternUtils utils, LockscreenCredential chosenCredential,
LockscreenCredential currentCredential, int userId) {
prepare(utils, chosenCredential, currentCredential, userId);
if (mBlocking) {
finish(saveAndVerifyInBackground().second);
} else {
new Task().execute();
}
}
/**
* Executes the save and verify work in background.
* @return pair where the first is a boolean confirming whether the change was successful or not
* and second is the Intent which has the challenge token or is null.
*/
@VisibleForTesting
Pair<Boolean, Intent> saveAndVerifyInBackground() {
final int userId = mUserId;
if (!mUtils.setLockCredential(mChosenCredential, mCurrentCredential, userId)) {
return Pair.create(false, null);
}
unifyProfileCredentialIfRequested();
@LockPatternUtils.VerifyFlag int flags = 0;
if (mRequestGatekeeperPassword) {
// If a Gatekeeper Password was requested, invoke the LockSettingsService code
// path to return a Gatekeeper Password based on the credential that the user
// chose. This should only be run if the credential was successfully set.
flags |= LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE;
}
if (mRequestWriteRepairModePassword) {
flags |= LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
}
if (flags == 0) {
return Pair.create(true, null);
}
Intent result = new Intent();
final VerifyCredentialResponse response = mUtils.verifyCredential(mChosenCredential,
userId, flags);
if (response.isMatched()) {
if (mRequestGatekeeperPassword && response.containsGatekeeperPasswordHandle()) {
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
response.getGatekeeperPasswordHandle());
} else if (mRequestGatekeeperPassword) {
Log.e(TAG, "critical: missing GK PW handle for known good credential: " + response);
}
} else {
Log.e(TAG, "critical: bad response for known good credential: " + response);
}
if (mRequestWriteRepairModePassword) {
// Notify the caller if repair mode credential is saved successfully
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL,
response.isMatched());
}
return Pair.create(true, result);
}
private void finish(Intent resultData) {
mFinished = true;
mResultData = resultData;
if (mListener != null) {
mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
}
if (mUnificationProfileCredential != null) {
mUnificationProfileCredential.zeroize();
}
LockScreenSafetySource.onLockScreenChange(getContext());
}
public SaveAndFinishWorker setRequestGatekeeperPasswordHandle(boolean value) {
mRequestGatekeeperPassword = value;
return this;
}
public SaveAndFinishWorker setRequestWriteRepairModePassword(boolean value) {
mRequestWriteRepairModePassword = value;
return this;
}
public SaveAndFinishWorker setBlocking(boolean blocking) {
mBlocking = blocking;
return this;
}
public SaveAndFinishWorker setProfileToUnify(
int profileId, LockscreenCredential credential) {
mUnificationProfileId = profileId;
mUnificationProfileCredential = credential.duplicate();
return this;
}
private void unifyProfileCredentialIfRequested() {
if (mUnificationProfileId != UserHandle.USER_NULL) {
mUtils.setSeparateProfileChallengeEnabled(mUnificationProfileId, false,
mUnificationProfileCredential);
}
}
private class Task extends AsyncTask<Void, Void, Pair<Boolean, Intent>> {
@Override
protected Pair<Boolean, Intent> doInBackground(Void... params){
return saveAndVerifyInBackground();
}
@Override
protected void onPostExecute(Pair<Boolean, Intent> resultData) {
if (!resultData.first) {
Toast.makeText(getContext(), R.string.lockpassword_credential_changed,
Toast.LENGTH_LONG).show();
}
finish(resultData.second);
}
}
interface Listener {
void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData);
}
}

View File

@@ -1,142 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.password;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Pair;
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;
import com.android.settings.safetycenter.LockScreenSafetySource;
/**
* An invisible retained worker fragment to track the AsyncWork that saves (and optionally
* verifies if a challenge is given) the chosen lock credential (pattern/pin/password).
*/
abstract class SaveChosenLockWorkerBase extends Fragment {
private Listener mListener;
private boolean mFinished;
private Intent mResultData;
protected LockPatternUtils mUtils;
protected boolean mRequestGatekeeperPassword;
protected boolean mWasSecureBefore;
protected int mUserId;
protected int mUnificationProfileId = UserHandle.USER_NULL;
protected LockscreenCredential mUnificationProfileCredential;
private boolean mBlocking;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void setListener(Listener listener) {
if (mListener == listener) {
return;
}
mListener = listener;
if (mFinished && mListener != null) {
mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
}
}
protected void prepare(LockPatternUtils utils, boolean requestGatekeeperPassword, int userId) {
mUtils = utils;
mUserId = userId;
mRequestGatekeeperPassword = requestGatekeeperPassword;
// This will be a no-op for non managed profiles.
mWasSecureBefore = mUtils.isSecure(mUserId);
mFinished = false;
mResultData = null;
}
protected void start() {
if (mBlocking) {
finish(saveAndVerifyInBackground().second);
} else {
new Task().execute();
}
}
/**
* Executes the save and verify work in background.
* @return pair where the first is a boolean confirming whether the change was successful or not
* and second is the Intent which has the challenge token or is null.
*/
protected abstract Pair<Boolean, Intent> saveAndVerifyInBackground();
protected void finish(Intent resultData) {
mFinished = true;
mResultData = resultData;
if (mListener != null) {
mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
}
if (mUnificationProfileCredential != null) {
mUnificationProfileCredential.zeroize();
}
LockScreenSafetySource.onLockScreenChange(getContext());
}
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
protected Pair<Boolean, Intent> doInBackground(Void... params){
return saveAndVerifyInBackground();
}
@Override
protected void onPostExecute(Pair<Boolean, Intent> resultData) {
if (!resultData.first) {
Toast.makeText(getContext(), R.string.lockpassword_credential_changed,
Toast.LENGTH_LONG).show();
}
finish(resultData.second);
}
}
interface Listener {
void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData);
}
}

View File

@@ -1,8 +1,7 @@
com.android.settings.deletionhelper.ActivationWarningFragment com.android.settings.deletionhelper.ActivationWarningFragment
com.android.settings.applications.appops.AppOpsCategory com.android.settings.applications.appops.AppOpsCategory
com.android.settings.CustomListPreference$CustomListPreferenceDialogFragment com.android.settings.CustomListPreference$CustomListPreferenceDialogFragment
com.android.settings.password.ChooseLockPassword$SaveAndFinishWorker com.android.settings.password.SaveAndFinishWorker
com.android.settings.password.ChooseLockPattern$SaveAndFinishWorker
com.android.settings.RestrictedListPreference$RestrictedListPreferenceDialogFragment com.android.settings.RestrictedListPreference$RestrictedListPreferenceDialogFragment
com.android.settings.password.ConfirmDeviceCredentialBaseFragment$LastTryDialog com.android.settings.password.ConfirmDeviceCredentialBaseFragment$LastTryDialog
com.android.settings.password.CredentialCheckResultTracker com.android.settings.password.CredentialCheckResultTracker

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.password;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class SaveAndFinishWorkerTest {
@Test
public void testSetRequestWriteRepairModePassword_setLockCredentialFail() {
int userId = 0;
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
var chosenCredential = LockscreenCredential.createPassword("1234");
var currentCredential = LockscreenCredential.createNone();
var worker = new SaveAndFinishWorker();
var lpu = mock(LockPatternUtils.class);
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(false);
worker.setRequestWriteRepairModePassword(true);
worker.prepare(lpu, chosenCredential, currentCredential, userId);
var result = worker.saveAndVerifyInBackground();
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
verify(lpu, never()).verifyCredential(chosenCredential, userId, flags);
assertThat(result.first).isFalse();
}
@Test
public void testSetRequestWriteRepairModePassword_verifyCredentialFail() {
int userId = 0;
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
var chosenCredential = LockscreenCredential.createPassword("1234");
var currentCredential = LockscreenCredential.createNone();
var worker = new SaveAndFinishWorker();
var lpu = mock(LockPatternUtils.class);
var response = VerifyCredentialResponse.fromError();
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
worker.setRequestWriteRepairModePassword(true);
worker.prepare(lpu, chosenCredential, currentCredential, userId);
var result = worker.saveAndVerifyInBackground();
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
verify(lpu).verifyCredential(chosenCredential, userId, flags);
assertThat(result.first).isTrue();
assertThat(result.second.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, true))
.isFalse();
}
@Test
public void testSetRequestWriteRepairModePassword_verifyCredentialSucceed() {
int userId = 0;
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
var chosenCredential = LockscreenCredential.createPassword("1234");
var currentCredential = LockscreenCredential.createNone();
var worker = new SaveAndFinishWorker();
var lpu = mock(LockPatternUtils.class);
var response = new VerifyCredentialResponse.Builder().build();
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
worker.setRequestWriteRepairModePassword(true);
worker.prepare(lpu, chosenCredential, currentCredential, userId);
var result = worker.saveAndVerifyInBackground();
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
verify(lpu).verifyCredential(chosenCredential, userId, flags);
assertThat(result.first).isTrue();
assertThat(result.second.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, false))
.isTrue();
}
@Test
public void testSetRequestWriteRepairModePassword_verifyCredentialSucceed_noGkPwHandle() {
int userId = 0;
int flags = LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW
| LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE;
var chosenCredential = LockscreenCredential.createPassword("1234");
var currentCredential = LockscreenCredential.createNone();
var worker = new SaveAndFinishWorker();
var lpu = mock(LockPatternUtils.class);
var response = new VerifyCredentialResponse.Builder().build();
when(lpu.setLockCredential(chosenCredential, currentCredential, userId)).thenReturn(true);
when(lpu.verifyCredential(chosenCredential, userId, flags)).thenReturn(response);
worker.setRequestWriteRepairModePassword(true);
worker.setRequestGatekeeperPasswordHandle(true);
worker.prepare(lpu, chosenCredential, currentCredential, userId);
var result = worker.saveAndVerifyInBackground();
verify(lpu).setLockCredential(chosenCredential, currentCredential, userId);
verify(lpu).verifyCredential(chosenCredential, userId, flags);
assertThat(result.first).isTrue();
assertThat(result.second.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_WROTE_REPAIR_MODE_CREDENTIAL, false))
.isTrue();
assertThat(result.second.getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, -1))
.isEqualTo(-1);
}
}