Merge changes from topics "async-challenge", "lss-sp"

* changes:
  Remove remainder of generateChallengeBlocking
  BiometricEnrollIntro should use non-blocking generateChallenge
  4/n: Remove challenge from choose/confirm, use new path
  3/n: verifyCredential no longer returns RequestThrottledException
  2/n: Add setRequestGatekeeperPassword to ChooseLockSettingsHelper
This commit is contained in:
Kevin Chyn
2020-08-08 00:05:53 +00:00
committed by Android (Google) Code Review
26 changed files with 403 additions and 308 deletions

View File

@@ -104,9 +104,14 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); .getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
final int userId = getIntent() final int userId = getIntent()
.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL); .getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
final byte[] gkPw = getIntent().getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_GK_PW);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.putExtra(Intent.EXTRA_USER_ID, userId);
if (gkPw != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW, gkPw);
}
} }
startActivity(intent); startActivity(intent);

View File

@@ -88,7 +88,13 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mToken = getIntent().getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); // Don't need to retrieve the HAT if it already exists. In some cases, the extras do not
// contain EXTRA_KEY_CHALLENGE_TOKEN but contain EXTRA_KEY_GK_PW, in which case enrollment
// classes may request a HAT to be created (as opposed to being passed in)
if (mToken == null) {
mToken = getIntent().getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
}
mFromSettingsSummary = getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false); mFromSettingsSummary = getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false);
if (savedInstanceState != null && mToken == null) { if (savedInstanceState != null && mToken == null) {
mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM); mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
@@ -180,11 +186,11 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
return intent; return intent;
} }
protected void launchConfirmLock(int titleResId, long challenge) { protected void launchConfirmLock(int titleResId) {
final ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(this); final ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(this);
builder.setRequestCode(CONFIRM_REQUEST) builder.setRequestCode(CONFIRM_REQUEST)
.setTitle(getString(titleResId)) .setTitle(getString(titleResId))
.setChallenge(challenge) .setRequestGatekeeperPassword(true)
.setForegroundOnly(true) .setForegroundOnly(true)
.setReturnCredentials(true); .setReturnCredentials(true);

View File

@@ -101,7 +101,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
/** /**
* @return the challenge generated by the biometric hardware * @return the challenge generated by the biometric hardware
*/ */
protected abstract long getChallenge(); protected abstract void getChallenge(GenerateChallengeCallback callback);
/** /**
* @return one of the ChooseLockSettingsHelper#EXTRA_KEY_FOR_* constants * @return one of the ChooseLockSettingsHelper#EXTRA_KEY_FOR_* constants
@@ -125,6 +125,10 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
*/ */
public abstract void onClick(LinkSpan span); public abstract void onClick(LinkSpan span);
protected interface GenerateChallengeCallback {
void onChallengeGenerated(long challenge);
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -160,11 +164,11 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
// No password registered, launch into enrollment wizard. // No password registered, launch into enrollment wizard.
mConfirmingCredentials = true; mConfirmingCredentials = true;
launchChooseLock(); launchChooseLock();
} else if (mToken == null) { } else if (!BiometricUtils.containsGatekeeperPassword(getIntent()) && mToken == null) {
// It's possible to have a token but mLaunchedConfirmLock == false, since // It's possible to have a token but mLaunchedConfirmLock == false, since
// ChooseLockGeneric can pass us a token. // ChooseLockGeneric can pass us a token.
mConfirmingCredentials = true; mConfirmingCredentials = true;
launchConfirmLock(getConfirmLockTitleResId(), getChallenge()); launchConfirmLock(getConfirmLockTitleResId());
} }
} }
} }
@@ -217,12 +221,10 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
private void launchChooseLock() { private void launchChooseLock() {
Intent intent = getChooseLockIntent(); Intent intent = getChooseLockIntent();
long challenge = getChallenge();
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(getExtraKeyForBiometric(), true); intent.putExtra(getExtraKeyForBiometric(), true);
if (mUserId != UserHandle.USER_NULL) { if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
@@ -269,13 +271,15 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
return; return;
} }
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) { } else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
mConfirmingCredentials = false;
if (resultCode == RESULT_FINISHED) { if (resultCode == RESULT_FINISHED) {
updatePasswordQuality(); updatePasswordQuality();
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
mConfirmingCredentials = false; getNextButton().setEnabled(false);
return; getChallenge((challenge -> {
mToken = BiometricUtils.requestGatekeeperHat(this, data, mUserId, challenge);
getNextButton().setEnabled(true);
}));
} else { } else {
setResult(resultCode, data); setResult(resultCode, data);
finish(); finish();
@@ -283,8 +287,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
} else if (requestCode == CONFIRM_REQUEST) { } else if (requestCode == CONFIRM_REQUEST) {
mConfirmingCredentials = false; mConfirmingCredentials = false;
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
getNextButton().setEnabled(false);
getChallenge((challenge -> {
mToken = BiometricUtils.requestGatekeeperHat(this, data, mUserId, challenge);
getNextButton().setEnabled(true);
}));
} else { } else {
setResult(resultCode, data); setResult(resultCode, data);
finish(); finish();

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2020 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.biometrics;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
/**
* Common biometric utilities.
*/
public class BiometricUtils {
/**
* Given the result from confirming or choosing a credential, request Gatekeeper to generate
* a HardwareAuthToken with the Gatekeeper Password together with a biometric challenge.
*
* @param context Caller's context
* @param result The onActivityResult intent from ChooseLock* or ConfirmLock*
* @param userId User ID that the credential/biometric operation applies to
* @param challenge Unique biometric challenge from FingerprintManager/FaceManager
* @return
*/
public static byte[] requestGatekeeperHat(Context context, Intent result, int userId,
long challenge) {
final byte[] gkPassword = result.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_GK_PW);
if (gkPassword == null) {
throw new IllegalStateException("Gatekeeper Password is null!!");
}
final LockPatternUtils utils = new LockPatternUtils(context);
return utils.verifyGatekeeperPassword(gkPassword, challenge, userId).getGatekeeperHAT();
}
public static boolean containsGatekeeperPassword(Intent data) {
if (data == null) {
return false;
}
return data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW) != null;
}
}

View File

@@ -26,6 +26,7 @@ import android.widget.TextView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollIntroduction; import com.android.settings.biometrics.BiometricEnrollIntroduction;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -38,7 +39,7 @@ import com.google.android.setupdesign.template.RequireScrollMixin;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction { public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceIntro"; private static final String TAG = "FaceEnrollIntroduction";
private FaceManager mFaceManager; private FaceManager mFaceManager;
private FaceFeatureProvider mFaceFeatureProvider; private FaceFeatureProvider mFaceFeatureProvider;
@@ -86,9 +87,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
RequireScrollMixin.class); RequireScrollMixin.class);
requireScrollMixin.requireScrollWithButton(this, agreeButton, requireScrollMixin.requireScrollWithButton(this, agreeButton,
R.string.security_settings_face_enroll_introduction_more, R.string.security_settings_face_enroll_introduction_more,
button -> { this::onNextButtonClick);
onNextButtonClick(button);
});
} }
final TextView footer2 = findViewById(R.id.face_enroll_introduction_footer_part_2); final TextView footer2 = findViewById(R.id.face_enroll_introduction_footer_part_2);
@@ -97,6 +96,18 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
? R.string.security_settings_face_enroll_introduction_footer_part_2 ? R.string.security_settings_face_enroll_introduction_footer_part_2
: R.string.security_settings_face_settings_footer_attention_not_supported; : R.string.security_settings_face_settings_footer_attention_not_supported;
footer2.setText(footer2TextResource); footer2.setText(footer2TextResource);
// This path is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
if (mToken == null && BiometricUtils.containsGatekeeperPassword(getIntent())) {
mFooterBarMixin.getPrimaryButton().setEnabled(false);
// We either block on generateChallenge, or need to gray out the "next" button until
// the challenge is ready. Let's just do this for now.
mFaceManager.generateChallenge(challenge -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
mFooterBarMixin.getPrimaryButton().setEnabled(true);
});
}
} }
@Override @Override
@@ -171,12 +182,13 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
} }
@Override @Override
protected long getChallenge() { protected void getChallenge(GenerateChallengeCallback callback) {
mFaceManager = Utils.getFaceManagerOrNull(this); mFaceManager = Utils.getFaceManagerOrNull(this);
if (mFaceManager == null) { if (mFaceManager == null) {
return 0; callback.onChallengeGenerated(0L);
return;
} }
return mFaceManager.generateChallengeBlocking(); mFaceManager.generateChallenge(callback::onChallengeGenerated);
} }
@Override @Override

View File

@@ -37,6 +37,7 @@ import androidx.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
@@ -202,15 +203,11 @@ public class FaceSettings extends DashboardFragment {
super.onResume(); super.onResume();
if (mToken == null && !mConfirmingPassword) { if (mToken == null && !mConfirmingPassword) {
// Generate challenge in onResume instead of onCreate, since FaceSettings can be
// created while Keyguard is showing, in which case the resetLockout revokeChallenge
// will invalidate the too-early created challenge here.
final long challenge = mFaceManager.generateChallengeBlocking();
final ChooseLockSettingsHelper.Builder builder = final ChooseLockSettingsHelper.Builder builder =
new ChooseLockSettingsHelper.Builder(getActivity(), this); new ChooseLockSettingsHelper.Builder(getActivity(), this);
final boolean launched = builder.setRequestCode(CONFIRM_REQUEST) final boolean launched = builder.setRequestCode(CONFIRM_REQUEST)
.setTitle(getString(R.string.security_settings_face_preference_title)) .setTitle(getString(R.string.security_settings_face_preference_title))
.setChallenge(challenge) .setRequestGatekeeperPassword(true)
.setUserId(mUserId) .setUserId(mUserId)
.setForegroundOnly(true) .setForegroundOnly(true)
.setReturnCredentials(true) .setReturnCredentials(true)
@@ -238,18 +235,22 @@ public class FaceSettings extends DashboardFragment {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (mToken == null && !BiometricUtils.containsGatekeeperPassword(data)) {
Log.e(TAG, "No credential");
finish();
}
if (requestCode == CONFIRM_REQUEST) { if (requestCode == CONFIRM_REQUEST) {
mConfirmingPassword = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) { if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
// The pin/pattern/password was set. // The pin/pattern/password was set.
if (data != null) { mFaceManager.generateChallenge(challenge -> {
mToken = data.getByteArrayExtra( mToken = BiometricUtils.requestGatekeeperHat(getPrefContext(), data, mUserId,
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); challenge);
if (mToken != null) {
mAttentionController.setToken(mToken); mAttentionController.setToken(mToken);
mEnrollController.setToken(mToken); mEnrollController.setToken(mToken);
} mConfirmingPassword = false;
} });
} }
} else if (requestCode == ENROLL_REQUEST) { } else if (requestCode == ENROLL_REQUEST) {
if (resultCode == RESULT_TIMEOUT) { if (resultCode == RESULT_TIMEOUT) {
@@ -257,11 +258,6 @@ public class FaceSettings extends DashboardFragment {
finish(); finish();
} }
} }
if (mToken == null) {
// Didn't get an authentication, finishing
finish();
}
} }
@Override @Override

View File

@@ -28,6 +28,7 @@ import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar.Listener; import com.android.settings.biometrics.BiometricEnrollSidecar.Listener;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterBarMixin;
@@ -60,8 +61,24 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title); setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
// This is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
if (mToken == null && BiometricUtils.containsGatekeeperPassword(getIntent())) {
final FingerprintManager fpm = getSystemService(FingerprintManager.class);
fpm.generateChallenge(challenge -> {
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
startLookingForFingerprint(); // already confirmed, so start looking for fingerprint // Put this into the intent. This is really just to work around the fact that the
// enrollment sidecar gets the HAT from the activity's intent, rather than having
// it passed in.
getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
startLookingForFingerprint();
});
} else if (mToken != null) {
// HAT passed in from somewhere else, such as FingerprintEnrollIntroduction
startLookingForFingerprint();
}
View animationView = findViewById(R.id.fingerprint_sensor_location_animation); View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
if (animationView instanceof FingerprintFindSensorAnimation) { if (animationView instanceof FingerprintFindSensorAnimation) {
@@ -160,10 +177,13 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CONFIRM_REQUEST) { if (requestCode == CONFIRM_REQUEST) {
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
throw new IllegalStateException("Pretty sure this is dead code");
/*
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
startLookingForFingerprint(); startLookingForFingerprint();
*/
} else { } else {
finish(); finish();
} }

View File

@@ -131,12 +131,13 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
} }
@Override @Override
protected long getChallenge() { protected void getChallenge(GenerateChallengeCallback callback) {
mFingerprintManager = Utils.getFingerprintManagerOrNull(this); mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
if (mFingerprintManager == null) { if (mFingerprintManager == null) {
return 0; callback.onChallengeGenerated(0L);
return;
} }
return mFingerprintManager.generateChallengeBlocking(); mFingerprintManager.generateChallenge(callback::onChallengeGenerated);
} }
@Override @Override

View File

@@ -54,6 +54,7 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.password.ChooseLockGeneric; import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
@@ -410,6 +411,8 @@ public class FingerprintSettings extends SubSettings {
private void updateAddPreference() { private void updateAddPreference() {
if (getActivity() == null) return; // Activity went away if (getActivity() == null) return; // Activity went away
final Preference addPreference = findPreference(KEY_FINGERPRINT_ADD);
/* Disable preference if too many fingerprints added */ /* Disable preference if too many fingerprints added */
final int max = getContext().getResources().getInteger( final int max = getContext().getResources().getInteger(
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
@@ -419,9 +422,8 @@ public class FingerprintSettings extends SubSettings {
final boolean removalInProgress = mRemovalSidecar.inProgress(); final boolean removalInProgress = mRemovalSidecar.inProgress();
CharSequence maxSummary = tooMany ? CharSequence maxSummary = tooMany ?
getContext().getString(R.string.fingerprint_add_max, max) : ""; getContext().getString(R.string.fingerprint_add_max, max) : "";
Preference addPreference = findPreference(KEY_FINGERPRINT_ADD);
addPreference.setSummary(maxSummary); addPreference.setSummary(maxSummary);
addPreference.setEnabled(!tooMany && !removalInProgress); addPreference.setEnabled(!tooMany && !removalInProgress && mToken != null);
} }
private void createFooterPreference(PreferenceGroup root) { private void createFooterPreference(PreferenceGroup root) {
@@ -565,15 +567,22 @@ public class FingerprintSettings extends SubSettings {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST if (requestCode == CONFIRM_REQUEST || requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
|| requestCode == CONFIRM_REQUEST) {
mLaunchedConfirm = false; mLaunchedConfirm = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) { if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
// The lock pin/pattern/password was set. Start enrolling! if (data != null && BiometricUtils.containsGatekeeperPassword(data)) {
if (data != null) { mFingerprintManager.generateChallenge(challenge -> {
mToken = data.getByteArrayExtra( mToken = BiometricUtils.requestGatekeeperHat(getActivity(), data,
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); mUserId, challenge);
updateAddPreference();
});
} else {
Log.d(TAG, "Data null or GK PW missing");
finish();
} }
} else {
Log.d(TAG, "Password not confirmed");
finish();
} }
} else if (requestCode == ADD_FINGERPRINT_REQUEST) { } else if (requestCode == ADD_FINGERPRINT_REQUEST) {
mEnrollClicked = false; mEnrollClicked = false;
@@ -583,11 +592,6 @@ public class FingerprintSettings extends SubSettings {
activity.finish(); activity.finish();
} }
} }
if (mToken == null) {
// Didn't get an authentication, finishing
getActivity().finish();
}
} }
@Override @Override
@@ -635,26 +639,26 @@ public class FingerprintSettings extends SubSettings {
private void launchChooseOrConfirmLock() { private void launchChooseOrConfirmLock() {
final Intent intent = new Intent(); final Intent intent = new Intent();
final long challenge = mFingerprintManager.generateChallengeBlocking();
final ChooseLockSettingsHelper.Builder builder = final ChooseLockSettingsHelper.Builder builder =
new ChooseLockSettingsHelper.Builder(getActivity(), this); new ChooseLockSettingsHelper.Builder(getActivity(), this);
final boolean launched = builder.setRequestCode(CONFIRM_REQUEST) final boolean launched = builder.setRequestCode(CONFIRM_REQUEST)
.setTitle(getString(R.string.security_settings_fingerprint_preference_title)) .setTitle(getString(R.string.security_settings_fingerprint_preference_title))
.setChallenge(challenge) .setRequestGatekeeperPassword(true)
.setUserId(mUserId) .setUserId(mUserId)
.setForegroundOnly(true) .setForegroundOnly(true)
.setReturnCredentials(true) .setReturnCredentials(true)
.show(); .show();
if (!launched) { if (!launched) {
// TODO: This should be cleaned up. ChooseLockGeneric should provide a way of
// specifying arguments/requests, instead of relying on callers setting extras.
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName()); intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS,
true); true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, true);
intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST); startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
} }

View File

@@ -109,7 +109,7 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase {
.setDescription(description) .setDescription(description)
.setUserId(user.id) .setUserId(user.id)
.setAllowAnyUserId(true) .setAllowAnyUserId(true)
.setChallenge(0L) .setForceVerifyPath(true)
.show(); .show();
return; return;
} }

View File

@@ -90,7 +90,7 @@ public class StorageWizardMoveConfirm extends StorageWizardBase {
builder.setRequestCode(REQUEST_CREDENTIAL) builder.setRequestCode(REQUEST_CREDENTIAL)
.setDescription(description) .setDescription(description)
.setUserId(user.id) .setUserId(user.id)
.setChallenge(0L) .setForceVerifyPath(true)
.setAllowAnyUserId(true) .setAllowAnyUserId(true)
.show(); .show();
return; return;

View File

@@ -144,8 +144,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private DevicePolicyManager mDpm; private DevicePolicyManager mDpm;
private boolean mHasChallenge = false; private boolean mRequestGatekeeperPassword = false;
private long mChallenge;
private boolean mPasswordConfirmed = false; private boolean mPasswordConfirmed = false;
private boolean mWaitingForConfirmation = false; private boolean mWaitingForConfirmation = false;
private boolean mForChangeCredRequiredForBoot = false; private boolean mForChangeCredRequiredForBoot = false;
@@ -211,10 +210,8 @@ public class ChooseLockGeneric extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
} }
mHasChallenge = intent.getBooleanExtra( mRequestGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
mChallenge = intent.getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
mForFingerprint = intent.getBooleanExtra( mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForFace = intent.getBooleanExtra( mForFace = intent.getBooleanExtra(
@@ -386,9 +383,12 @@ public class ChooseLockGeneric extends SettingsActivity {
mForFingerprint); mForFingerprint);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE,
mForFace); mForFace);
// If the caller requested Gatekeeper Password to be returned, we assume it came
// from biometric enrollment. This should be cleaned up, since requesting
// Gatekeeper Password should not imply it came from biometric setup/settings.
startActivityForResult( startActivityForResult(
intent, intent,
mIsSetNewPassword && mHasChallenge mIsSetNewPassword && mRequestGatekeeperPassword
? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
: ENABLE_ENCRYPTION_REQUEST); : ENABLE_ENCRYPTION_REQUEST);
} else { } else {
@@ -438,6 +438,10 @@ public class ChooseLockGeneric extends SettingsActivity {
&& resultCode == BiometricEnrollBase.RESULT_FINISHED) { && resultCode == BiometricEnrollBase.RESULT_FINISHED) {
Intent intent = getBiometricEnrollIntent(getActivity()); Intent intent = getBiometricEnrollIntent(getActivity());
if (data != null) { if (data != null) {
// ChooseLockGeneric should have requested that the Gatekeeper Password be
// returned, so that biometric enrollment(s) can subsequently request Gatekeeper
// to create HardwareAuthToken(s) wrapping biometric-specific challenges. Send
// the extras (including the GK Password) to the enrollment activity.
intent.putExtras(data.getExtras()); intent.putExtras(data.getExtras());
} }
// Forward the target user id to fingerprint setup page. // Forward the target user id to fingerprint setup page.
@@ -722,10 +726,8 @@ public class ChooseLockGeneric extends SettingsActivity {
.setRequestedMinComplexity(mRequestedMinComplexity) .setRequestedMinComplexity(mRequestedMinComplexity)
.setForFingerprint(mForFingerprint) .setForFingerprint(mForFingerprint)
.setForFace(mForFace) .setForFace(mForFace)
.setUserId(mUserId); .setUserId(mUserId)
if (mHasChallenge) { .setRequestGatekeeperPassword(mRequestGatekeeperPassword);
builder.setChallenge(mChallenge);
}
if (mUserPassword != null) { if (mUserPassword != null) {
builder.setPassword(mUserPassword); builder.setPassword(mUserPassword);
} }
@@ -740,10 +742,8 @@ public class ChooseLockGeneric extends SettingsActivity {
new ChooseLockPattern.IntentBuilder(getContext()) new ChooseLockPattern.IntentBuilder(getContext())
.setForFingerprint(mForFingerprint) .setForFingerprint(mForFingerprint)
.setForFace(mForFace) .setForFace(mForFace)
.setUserId(mUserId); .setUserId(mUserId)
if (mHasChallenge) { .setRequestGatekeeperPassword(mRequestGatekeeperPassword);
builder.setChallenge(mChallenge);
}
if (mUserPassword != null) { if (mUserPassword != null) {
builder.setPattern(mUserPassword); builder.setPattern(mUserPassword);
} }
@@ -784,8 +784,13 @@ public class ChooseLockGeneric extends SettingsActivity {
intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped); intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
} }
intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras()); intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
// If the caller requested Gatekeeper Password to be returned, we assume it came
// from biometric enrollment. onActivityResult will put the LockSettingsService
// into the extras and launch biometric enrollment. This should be cleaned up,
// since requesting Gatekeeper Password should not imply it came from biometric
// setup/settings.
startActivityForResult(intent, startActivityForResult(intent,
mIsSetNewPassword && mHasChallenge mIsSetNewPassword && mRequestGatekeeperPassword
? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
: CHOOSE_LOCK_REQUEST); : CHOOSE_LOCK_REQUEST);
return; return;

View File

@@ -77,6 +77,7 @@ import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
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.EncryptionInterstitial; import com.android.settings.EncryptionInterstitial;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
@@ -117,7 +118,6 @@ public class ChooseLockPassword extends SettingsActivity {
mIntent = new Intent(context, ChooseLockPassword.class); mIntent = new Intent(context, ChooseLockPassword.class);
mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false); mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false);
mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false); mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false);
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
} }
public IntentBuilder setPasswordQuality(int quality) { public IntentBuilder setPasswordQuality(int quality) {
@@ -130,9 +130,9 @@ public class ChooseLockPassword extends SettingsActivity {
return this; return this;
} }
public IntentBuilder setChallenge(long challenge) { public IntentBuilder setRequestGatekeeperPassword(boolean requestGatekeeperPassword) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW,
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); requestGatekeeperPassword);
return this; return this;
} }
@@ -211,8 +211,7 @@ public class ChooseLockPassword extends SettingsActivity {
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
private LockscreenCredential mChosenPassword; private LockscreenCredential mChosenPassword;
private boolean mHasChallenge; private boolean mRequestGatekeeperPassword;
private long mChallenge;
private ImeAwareEditText mPasswordEntry; private ImeAwareEditText mPasswordEntry;
private TextViewInputDisabler mPasswordEntryInputDisabler; private TextViewInputDisabler mPasswordEntryInputDisabler;
@@ -407,7 +406,8 @@ public class ChooseLockPassword extends SettingsActivity {
w.setBlocking(true); w.setBlocking(true);
w.setListener(this); w.setListener(this);
w.start(utils, required, false, 0, currentCredential, currentCredential, mUserId); w.start(utils, required, false /* requestGatekeeperPassword */, currentCredential,
currentCredential, mUserId);
} }
mTextChangedHandler = new TextChangedHandler(); mTextChangedHandler = new TextChangedHandler();
} }
@@ -491,9 +491,8 @@ public class ChooseLockPassword extends SettingsActivity {
ChooseLockGeneric.CONFIRM_CREDENTIALS, true); ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
mCurrentCredential = intent.getParcelableExtra( mCurrentCredential = intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra( mRequestGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
if (savedInstanceState == null) { if (savedInstanceState == null) {
updateStage(Stage.Introduction); updateStage(Stage.Introduction);
if (confirmCredentials) { if (confirmCredentials) {
@@ -502,6 +501,7 @@ public class ChooseLockPassword extends SettingsActivity {
builder.setRequestCode(CONFIRM_EXISTING_REQUEST) builder.setRequestCode(CONFIRM_EXISTING_REQUEST)
.setTitle(getString(R.string.unlock_set_unlock_launch_picker_title)) .setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
.setReturnCredentials(true) .setReturnCredentials(true)
.setRequestGatekeeperPassword(mRequestGatekeeperPassword)
.setUserId(mUserId) .setUserId(mUserId)
.show(); .show();
} }
@@ -885,7 +885,7 @@ public class ChooseLockPassword extends SettingsActivity {
profileCredential); profileCredential);
} }
} }
mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge, mSaveAndFinishWorker.start(mLockPatternUtils, required, mRequestGatekeeperPassword,
mChosenPassword, mCurrentCredential, mUserId); mChosenPassword, mCurrentCredential, mUserId);
} }
@@ -945,10 +945,9 @@ public class ChooseLockPassword extends SettingsActivity {
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
public void start(LockPatternUtils utils, boolean required, public void start(LockPatternUtils utils, boolean required,
boolean hasChallenge, long challenge, boolean requestGatekeeperPassword, LockscreenCredential chosenPassword,
LockscreenCredential chosenPassword, LockscreenCredential currentCredential, LockscreenCredential currentCredential, int userId) {
int userId) { prepare(utils, required, requestGatekeeperPassword, userId);
prepare(utils, required, hasChallenge, challenge, userId);
mChosenPassword = chosenPassword; mChosenPassword = chosenPassword;
mCurrentCredential = currentCredential != null ? currentCredential mCurrentCredential = currentCredential != null ? currentCredential
@@ -966,20 +965,21 @@ public class ChooseLockPassword extends SettingsActivity {
unifyProfileCredentialIfRequested(); unifyProfileCredentialIfRequested();
} }
Intent result = null; Intent result = null;
if (success && mHasChallenge) { if (success && mRequestGatekeeperPassword) {
byte[] token; // If a Gatekeeper Password was requested, invoke the LockSettingsService code
try { // path to return a Gatekeeper Password based on the credential that the user
token = mUtils.verifyCredential(mChosenPassword, mChallenge, mUserId); // chose. This should only be run if the credential was successfully set.
} catch (RequestThrottledException e) { final VerifyCredentialResponse response = mUtils.verifyCredential(mChosenPassword,
token = null; mUserId, LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
}
if (token == null) { if (!response.isMatched() || response.getGatekeeperPw() == null) {
Log.e(TAG, "critical: no token returned for known good password."); Log.e(TAG, "critical: bad response or missing GK PW for known good password: "
+ response.toString());
} }
result = new Intent(); result = new Intent();
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
response.getGatekeeperPw());
} }
return Pair.create(success, result); return Pair.create(success, result);
} }

View File

@@ -42,11 +42,11 @@ import androidx.fragment.app.Fragment;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient; import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
import com.android.internal.widget.LockPatternView; 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.EncryptionInterstitial; import com.android.settings.EncryptionInterstitial;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
@@ -54,7 +54,6 @@ import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.InstrumentedFragment; import com.android.settings.core.InstrumentedFragment;
import com.android.settings.notification.RedactionInterstitial; import com.android.settings.notification.RedactionInterstitial;
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterBarMixin;
@@ -106,7 +105,6 @@ public class ChooseLockPattern extends SettingsActivity {
mIntent = new Intent(context, ChooseLockPattern.class); mIntent = new Intent(context, ChooseLockPattern.class);
mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false); mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false);
mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false); mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false);
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
} }
public IntentBuilder setUserId(int userId) { public IntentBuilder setUserId(int userId) {
@@ -114,9 +112,9 @@ public class ChooseLockPattern extends SettingsActivity {
return this; return this;
} }
public IntentBuilder setChallenge(long challenge) { public IntentBuilder setRequestGatekeeperPassword(boolean requestGatekeeperPassword) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW,
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); requestGatekeeperPassword);
return this; return this;
} }
@@ -206,8 +204,7 @@ public class ChooseLockPattern extends SettingsActivity {
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
private boolean mHasChallenge; private boolean mRequestGatekeeperPassword;
private long mChallenge;
protected TextView mTitleText; protected TextView mTitleText;
protected TextView mHeaderText; protected TextView mHeaderText;
protected TextView mMessageText; protected TextView mMessageText;
@@ -483,7 +480,8 @@ public class ChooseLockPattern extends SettingsActivity {
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
w.setBlocking(true); w.setBlocking(true);
w.setListener(this); w.setListener(this);
w.start(mLockPatternUtils, required, false, 0, current, current, mUserId); w.start(mLockPatternUtils, required, false /* requestGatekeeperPassword */, current,
current, mUserId);
} }
mForFingerprint = intent.getBooleanExtra( mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
@@ -563,9 +561,8 @@ public class ChooseLockPattern extends SettingsActivity {
Intent intent = getActivity().getIntent(); Intent intent = getActivity().getIntent();
mCurrentCredential = mCurrentCredential =
intent.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); intent.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra( mRequestGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
if (savedInstanceState == null) { if (savedInstanceState == null) {
if (confirmCredentials) { if (confirmCredentials) {
@@ -578,6 +575,7 @@ public class ChooseLockPattern extends SettingsActivity {
final boolean launched = builder.setRequestCode(CONFIRM_EXISTING_REQUEST) final boolean launched = builder.setRequestCode(CONFIRM_EXISTING_REQUEST)
.setTitle(getString(R.string.unlock_set_unlock_launch_picker_title)) .setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
.setReturnCredentials(true) .setReturnCredentials(true)
.setRequestGatekeeperPassword(mRequestGatekeeperPassword)
.setUserId(mUserId) .setUserId(mUserId)
.show(); .show();
@@ -858,7 +856,7 @@ public class ChooseLockPattern extends SettingsActivity {
} }
} }
mSaveAndFinishWorker.start(mLockPatternUtils, required, mSaveAndFinishWorker.start(mLockPatternUtils, required,
mHasChallenge, mChallenge, mChosenPattern, mCurrentCredential, mUserId); mRequestGatekeeperPassword, mChosenPattern, mCurrentCredential, mUserId);
} }
@Override @Override
@@ -888,10 +886,10 @@ public class ChooseLockPattern extends SettingsActivity {
private LockscreenCredential mCurrentCredential; private LockscreenCredential mCurrentCredential;
private boolean mLockVirgin; private boolean mLockVirgin;
public void start(LockPatternUtils utils, boolean credentialRequired, boolean hasChallenge, public void start(LockPatternUtils utils, boolean credentialRequired,
long challenge, LockscreenCredential chosenPattern, boolean requestGatekeeperPassword, LockscreenCredential chosenPattern,
LockscreenCredential currentCredential, int userId) { LockscreenCredential currentCredential, int userId) {
prepare(utils, credentialRequired, hasChallenge, challenge, userId); prepare(utils, credentialRequired, requestGatekeeperPassword, userId);
mCurrentCredential = currentCredential != null ? currentCredential mCurrentCredential = currentCredential != null ? currentCredential
: LockscreenCredential.createNone(); : LockscreenCredential.createNone();
@@ -912,20 +910,21 @@ public class ChooseLockPattern extends SettingsActivity {
unifyProfileCredentialIfRequested(); unifyProfileCredentialIfRequested();
} }
Intent result = null; Intent result = null;
if (success && mHasChallenge) { if (success && mRequestGatekeeperPassword) {
byte[] token; // If a Gatekeeper Password was requested, invoke the LockSettingsService code
try { // path to return a Gatekeeper Password based on the credential that the user
token = mUtils.verifyCredential(mChosenPattern, mChallenge, userId); // chose. This should only be run if the credential was successfully set.
} catch (RequestThrottledException e) { final VerifyCredentialResponse response = mUtils.verifyCredential(mChosenPattern,
token = null; userId, LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
}
if (token == null) { if (!response.isMatched() || response.getGatekeeperPw() == null) {
Log.e(TAG, "critical: no token returned for known good pattern"); Log.e(TAG, "critical: bad response or missing GK HAT for known good pattern: "
+ response.toString());
} }
result = new Intent(); result = new Intent();
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
response.getGatekeeperPw());
} }
return Pair.create(success, result); return Pair.create(success, result);
} }

View File

@@ -31,7 +31,9 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.SetupWizardUtils; import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
@@ -45,13 +47,19 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_TYPE = "type"; public static final String EXTRA_KEY_TYPE = "type";
public static final String EXTRA_KEY_PASSWORD = "password"; public static final String EXTRA_KEY_PASSWORD = "password";
public static final String EXTRA_KEY_RETURN_CREDENTIALS = "return_credentials"; public static final String EXTRA_KEY_RETURN_CREDENTIALS = "return_credentials";
public static final String EXTRA_KEY_HAS_CHALLENGE = "has_challenge"; // Force the verifyCredential path instead of checkCredential path. This will be removed
public static final String EXTRA_KEY_CHALLENGE = "challenge"; // after b/161956762 is resolved.
public static final String EXTRA_KEY_FORCE_VERIFY = "force_verify";
// Gatekeeper HardwareAuthToken
public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token"; public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint"; public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
public static final String EXTRA_KEY_FOR_FACE = "for_face"; public static final String EXTRA_KEY_FOR_FACE = "for_face";
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot"; public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only"; public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
public static final String EXTRA_KEY_REQUEST_GK_PW = "request_gk_pw";
// Gatekeeper password, which can subsequently be used to generate Gatekeeper
// HardwareAuthToken(s) via LockSettingsService#verifyGatekeeperPassword
public static final String EXTRA_KEY_GK_PW = "gk_pw";
/** /**
* 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
@@ -117,8 +125,8 @@ public final class ChooseLockSettingsHelper {
// ChooseLockSettingsHelper will determine the caller's userId if none provided. // ChooseLockSettingsHelper will determine the caller's userId if none provided.
private int mUserId; private int mUserId;
private boolean mAllowAnyUserId; private boolean mAllowAnyUserId;
// The challenge can be 0, which is different than "no challenge" private boolean mForceVerifyPath;
@Nullable Long mChallenge; boolean mRequestGatekeeperPassword;
public Builder(@NonNull Activity activity) { public Builder(@NonNull Activity activity) {
mActivity = activity; mActivity = activity;
@@ -174,8 +182,12 @@ public final class ChooseLockSettingsHelper {
* @param returnCredentials if true, puts the following credentials into intent for * @param returnCredentials if true, puts the following credentials into intent for
* onActivityResult with the following keys: * onActivityResult with the following keys:
* {@link #EXTRA_KEY_TYPE}, {@link #EXTRA_KEY_PASSWORD}, * {@link #EXTRA_KEY_TYPE}, {@link #EXTRA_KEY_PASSWORD},
* {@link #EXTRA_KEY_CHALLENGE_TOKEN}. * {@link #EXTRA_KEY_CHALLENGE_TOKEN}, {@link #EXTRA_KEY_GK_PW}
* Note that if this is true, this can only be called internally. * Note that if this is true, this can only be called internally.
*
* This should also generally be set if
* {@link #setRequestGatekeeperPassword(boolean)} (boolean)} is
* set.
*/ */
@NonNull public Builder setReturnCredentials(boolean returnCredentials) { @NonNull public Builder setReturnCredentials(boolean returnCredentials) {
mReturnCredentials = returnCredentials; mReturnCredentials = returnCredentials;
@@ -220,14 +232,26 @@ public final class ChooseLockSettingsHelper {
} }
/** /**
* @param challenge an opaque payload that will be wrapped in the Gatekeeper's payload * @param forceVerifyPath Forces the VerifyCredential path instead of the CheckCredential
* if authentication is successful. Common use case is for the caller's * path. This will be removed after b/161956762 is resolved.
* secure layer (e.g. Trusted Execution Environment) to 1) verify that
* the Gatekeeper HAT's HMAC is valid, and 2) if so, perform an operation
* based on the challenge.
*/ */
@NonNull public Builder setChallenge(long challenge) { @NonNull public Builder setForceVerifyPath(boolean forceVerifyPath) {
mChallenge = challenge; mForceVerifyPath = forceVerifyPath;
return this;
}
/**
* Requests that LockSettingsService return the Gatekeeper Password (instead of the
* Gatekeeper HAT). This allows us to use a single entry of the user's credential
* to create multiple Gatekeeper HATs containing distinct challenges via
* {@link LockPatternUtils#verifyGatekeeperPassword(byte[], long, int)}.
*
* Upon confirmation of the user's password, the Gatekeeper Password will be returned via
* onActivityResult with the key being {@link #EXTRA_KEY_GK_PW}.
* @param requestGatekeeperPassword
*/
@NonNull public Builder setRequestGatekeeperPassword(boolean requestGatekeeperPassword) {
mRequestGatekeeperPassword = requestGatekeeperPassword;
return this; return this;
} }
@@ -242,10 +266,10 @@ public final class ChooseLockSettingsHelper {
+ " onActivityResult"); + " onActivityResult");
} }
if (mChallenge != null && !mReturnCredentials) { if (mRequestGatekeeperPassword && !mReturnCredentials) {
// HAT containing the signed challenge will not be available to the caller. // HAT containing the signed challenge will not be available to the caller.
Log.w(TAG, "Challenge set but not requesting ReturnCredentials. Are you sure this" Log.w(TAG, "Requested gatekeeper password but not requesting ReturnCredentials. Are"
+ " is what you want?"); + " you sure this is what you want?");
} }
return new ChooseLockSettingsHelper(this, mActivity, mFragment); return new ChooseLockSettingsHelper(this, mActivity, mFragment);
@@ -261,29 +285,29 @@ public final class ChooseLockSettingsHelper {
* @return true if the confirmation activity is shown (e.g. user has a credential set up) * @return true if the confirmation activity is shown (e.g. user has a credential set up)
*/ */
public boolean launch() { public boolean launch() {
final long challenge = mBuilder.mChallenge != null ? mBuilder.mChallenge : 0L;
return launchConfirmationActivity(mBuilder.mRequestCode, mBuilder.mTitle, mBuilder.mHeader, return launchConfirmationActivity(mBuilder.mRequestCode, mBuilder.mTitle, mBuilder.mHeader,
mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal, mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal,
mBuilder.mChallenge != null, challenge, mBuilder.mUserId, mBuilder.mForceVerifyPath, mBuilder.mUserId, mBuilder.mAlternateButton,
mBuilder.mAlternateButton, mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly); mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly,
mBuilder.mRequestGatekeeperPassword);
} }
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title, private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description, @Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge, boolean returnCredentials, boolean external, boolean forceVerifyPath,
long challenge, int userId, @Nullable CharSequence alternateButton, int userId, @Nullable CharSequence alternateButton, boolean allowAnyUser,
boolean allowAnyUser, boolean foregroundOnly) { boolean foregroundOnly, boolean requestGatekeeperPassword) {
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId); final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
boolean launched = false; boolean launched = false;
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) { switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
launched = launchConfirmationActivity(request, title, header, description, launched = launchConfirmationActivity(request, title, header, description,
returnCredentials || hasChallenge returnCredentials
? ConfirmLockPattern.InternalActivity.class ? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, returnCredentials, external, : ConfirmLockPattern.class, returnCredentials, external,
hasChallenge, challenge, userId, alternateButton, allowAnyUser, forceVerifyPath, userId, alternateButton, allowAnyUser,
foregroundOnly); foregroundOnly, requestGatekeeperPassword);
break; break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
@@ -292,11 +316,11 @@ public final class ChooseLockSettingsHelper {
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
launched = launchConfirmationActivity(request, title, header, description, launched = launchConfirmationActivity(request, title, header, description,
returnCredentials || hasChallenge returnCredentials
? ConfirmLockPassword.InternalActivity.class ? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, returnCredentials, external, : ConfirmLockPassword.class, returnCredentials, external,
hasChallenge, challenge, userId, alternateButton, allowAnyUser, forceVerifyPath, userId, alternateButton, allowAnyUser,
foregroundOnly); foregroundOnly, requestGatekeeperPassword);
break; break;
} }
return launched; return launched;
@@ -304,9 +328,9 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header, private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean returnCredentials, CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge, boolean external, boolean forceVerifyPath, int userId,
int userId, @Nullable CharSequence alternateButton, boolean allowAnyUser, @Nullable CharSequence alternateButton, boolean allowAnyUser,
boolean foregroundOnly) { boolean foregroundOnly, boolean requestGatekeeperPassword) {
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title); intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header); intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -317,12 +341,13 @@ public final class ChooseLockSettingsHelper {
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external); intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.USE_FADE_ANIMATION, external); intent.putExtra(ConfirmDeviceCredentialBaseFragment.USE_FADE_ANIMATION, external);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, forceVerifyPath);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton); intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW,
requestGatekeeperPassword);
intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName()); intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName());
if (external) { if (external) {

View File

@@ -74,7 +74,7 @@ public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
// Copy the original extras into the new intent // Copy the original extras into the new intent
copyBooleanExtra(activityIntent, intent, copyBooleanExtra(activityIntent, intent,
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
copyBooleanExtra(activityIntent, intent, copyBooleanExtra(activityIntent, intent,
ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false); ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
if (activityIntent.hasExtra( if (activityIntent.hasExtra(
@@ -83,8 +83,6 @@ public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS)); ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS));
} }
intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, selectedLockType.defaultQuality); intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, selectedLockType.defaultQuality);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE,
activityIntent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0));
WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent); WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
activity.startActivity(intent); activity.startActivity(intent);
activity.finish(); activity.finish();

View File

@@ -27,7 +27,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback; import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.PromptInfo;
@@ -81,18 +80,6 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
return intent; return intent;
} }
public static Intent createIntent(CharSequence title, CharSequence details, long challenge) {
Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME,
ConfirmDeviceCredentialActivity.class.getName());
intent.putExtra(KeyguardManager.EXTRA_TITLE, title);
intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION, details);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
return intent;
}
private BiometricManager mBiometricManager;
private BiometricFragment mBiometricFragment; private BiometricFragment mBiometricFragment;
private DevicePolicyManager mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
@@ -181,7 +168,6 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(Color.TRANSPARENT); getWindow().setStatusBarColor(Color.TRANSPARENT);
mBiometricManager = getSystemService(BiometricManager.class);
mDevicePolicyManager = getSystemService(DevicePolicyManager.class); mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
mUserManager = UserManager.get(this); mUserManager = UserManager.get(this);
mTrustManager = getSystemService(TrustManager.class); mTrustManager = getSystemService(TrustManager.class);
@@ -394,7 +380,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
.setDescription(mDetails) .setDescription(mDetails)
.setExternal(true) .setExternal(true)
.setUserId(mUserId) .setUserId(mUserId)
.setChallenge(0L) .setForceVerifyPath(true)
.show(); .show();
} else if (mCredentialMode == CREDENTIAL_NORMAL) { } else if (mCredentialMode == CREDENTIAL_NORMAL) {
final ChooseLockSettingsHelper.Builder builder = final ChooseLockSettingsHelper.Builder builder =

View File

@@ -71,6 +71,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
protected static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 3000; protected static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 3000;
protected boolean mReturnCredentials = false; protected boolean mReturnCredentials = false;
protected boolean mReturnGatekeeperPassword = false;
protected boolean mForceVerifyPath = false;
protected Button mCancelButton; protected Button mCancelButton;
/** Button allowing managed profile password reset, null when is not shown. */ /** Button allowing managed profile password reset, null when is not shown. */
@Nullable protected Button mForgotButton; @Nullable protected Button mForgotButton;
@@ -93,12 +95,18 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mFrpAlternateButtonText = getActivity().getIntent().getCharSequenceExtra( final Intent intent = getActivity().getIntent();
mFrpAlternateButtonText = intent.getCharSequenceExtra(
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL); KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
mReturnCredentials = getActivity().getIntent().getBooleanExtra( mReturnCredentials = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false); ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
mReturnGatekeeperPassword = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
mForceVerifyPath = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, false);
// Only take this argument into account if it belongs to the current profile. // Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent();
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras(), mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras(),
isInternalActivity()); isInternalActivity());
mFrp = (mUserId == LockPatternUtils.USER_FRP); mFrp = (mUserId == LockPatternUtils.USER_FRP);

View File

@@ -380,13 +380,18 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
: LockscreenCredential.createPin(passwordText); : LockscreenCredential.createPin(passwordText);
mPasswordEntryInputDisabler.setInputEnabled(false); mPasswordEntryInputDisabler.setInputEnabled(false);
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
Intent intent = new Intent(); Intent intent = new Intent();
if (verifyChallenge) { // TODO(b/161956762): Sanitize this
if (mReturnGatekeeperPassword) {
if (isInternalActivity()) { if (isInternalActivity()) {
startVerifyPassword(credential, intent); startVerifyPassword(credential, intent,
LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
return;
}
} else if (mForceVerifyPath) {
if (isInternalActivity()) {
startVerifyPassword(credential, intent, 0 /* flags */);
return; return;
} }
} else { } else {
@@ -401,35 +406,31 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return getActivity() instanceof ConfirmLockPassword.InternalActivity; return getActivity() instanceof ConfirmLockPassword.InternalActivity;
} }
private void startVerifyPassword(LockscreenCredential credential, final Intent intent) { private void startVerifyPassword(LockscreenCredential credential, final Intent intent,
long challenge = getActivity().getIntent().getLongExtra( @LockPatternUtils.VerifyFlag int flags) {
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
final int localUserId = mUserId; final int localUserId = mUserId;
final LockPatternChecker.OnVerifyCallback onVerifyCallback = final LockPatternChecker.OnVerifyCallback onVerifyCallback = (response, timeoutMs) -> {
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token, int timeoutMs) {
mPendingLockCheck = null; mPendingLockCheck = null;
boolean matched = false; final boolean matched = response.isMatched();
if (token != null) { if (matched && mReturnCredentials) {
matched = true; if ((flags & LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW) != 0) {
if (mReturnCredentials) { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
response.getGatekeeperPw());
} else {
intent.putExtra( intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
token); response.getGatekeeperHAT());
} }
} }
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
localEffectiveUserId); localEffectiveUserId);
}
}; };
mPendingLockCheck = (localEffectiveUserId == localUserId) mPendingLockCheck = (localEffectiveUserId == localUserId)
? LockPatternChecker.verifyCredential( ? LockPatternChecker.verifyCredential(mLockPatternUtils, credential,
mLockPatternUtils, credential, challenge, localUserId, onVerifyCallback) localUserId, flags, onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge( : LockPatternChecker.verifyTiedProfileChallenge(mLockPatternUtils, credential,
mLockPatternUtils, credential, challenge, localUserId, localUserId, flags, onVerifyCallback);
onVerifyCallback);
} }
private void startCheckPassword(final LockscreenCredential credential, private void startCheckPassword(final LockscreenCredential credential,

View File

@@ -422,14 +422,18 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mLockPatternView.setEnabled(false); mLockPatternView.setEnabled(false);
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
final LockscreenCredential credential = LockscreenCredential.createPattern(pattern); final LockscreenCredential credential = LockscreenCredential.createPattern(pattern);
//TODO: how to sanitize this? // TODO(b/161956762): Sanitize this
Intent intent = new Intent(); Intent intent = new Intent();
if (verifyChallenge) { if (mReturnGatekeeperPassword) {
if (isInternalActivity()) { if (isInternalActivity()) {
startVerifyPattern(credential, intent); startVerifyPattern(credential, intent,
LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
return;
}
} else if (mForceVerifyPath) {
if (isInternalActivity()) {
startVerifyPattern(credential, intent, 0 /* flags */);
return; return;
} }
} else { } else {
@@ -445,36 +449,33 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
} }
private void startVerifyPattern(final LockscreenCredential pattern, private void startVerifyPattern(final LockscreenCredential pattern,
final Intent intent) { final Intent intent, @LockPatternUtils.VerifyFlag int flags) {
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
final int localUserId = mUserId; final int localUserId = mUserId;
long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
final LockPatternChecker.OnVerifyCallback onVerifyCallback = final LockPatternChecker.OnVerifyCallback onVerifyCallback =
new LockPatternChecker.OnVerifyCallback() { (response, timeoutMs) -> {
@Override
public void onVerified(byte[] token, int timeoutMs) {
mPendingLockCheck = null; mPendingLockCheck = null;
boolean matched = false; final boolean matched = response.isMatched();
if (token != null) { if (matched && mReturnCredentials) {
matched = true; if ((flags & LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW) != 0) {
if (mReturnCredentials) { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
response.getGatekeeperPw());
} else {
intent.putExtra( intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
token); response.getGatekeeperHAT());
} }
} }
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
localEffectiveUserId); localEffectiveUserId);
}
}; };
mPendingLockCheck = (localEffectiveUserId == localUserId) mPendingLockCheck = (localEffectiveUserId == localUserId)
? LockPatternChecker.verifyCredential( ? LockPatternChecker.verifyCredential(
mLockPatternUtils, pattern, challenge, localUserId, mLockPatternUtils, pattern, localUserId, flags,
onVerifyCallback) onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge( : LockPatternChecker.verifyTiedProfileChallenge(
mLockPatternUtils, pattern, mLockPatternUtils, pattern, localUserId, flags,
challenge, localUserId, onVerifyCallback); onVerifyCallback);
} }
private void startCheckPattern(final LockscreenCredential pattern, private void startCheckPattern(final LockscreenCredential pattern,

View File

@@ -42,8 +42,7 @@ abstract class SaveChosenLockWorkerBase extends Fragment {
private Intent mResultData; private Intent mResultData;
protected LockPatternUtils mUtils; protected LockPatternUtils mUtils;
protected boolean mHasChallenge; protected boolean mRequestGatekeeperPassword;
protected long mChallenge;
protected boolean mWasSecureBefore; protected boolean mWasSecureBefore;
protected int mUserId; protected int mUserId;
protected int mUnificationProfileId = UserHandle.USER_NULL; protected int mUnificationProfileId = UserHandle.USER_NULL;
@@ -69,12 +68,10 @@ abstract class SaveChosenLockWorkerBase extends Fragment {
} }
protected void prepare(LockPatternUtils utils, boolean credentialRequired, protected void prepare(LockPatternUtils utils, boolean credentialRequired,
boolean hasChallenge, long challenge, int userId) { boolean requestGatekeeperPassword, int userId) {
mUtils = utils; mUtils = utils;
mUserId = userId; mUserId = userId;
mRequestGatekeeperPassword = requestGatekeeperPassword;
mHasChallenge = hasChallenge;
mChallenge = challenge;
// This will be a no-op for non managed profiles. // This will be a no-op for non managed profiles.
mWasSecureBefore = mUtils.isSecure(mUserId); mWasSecureBefore = mUtils.isSecure(mUserId);

View File

@@ -135,26 +135,22 @@ final class SetNewPasswordController {
private Bundle getFingerprintChooseLockExtras() { private Bundle getFingerprintChooseLockExtras() {
Bundle chooseLockExtras = new Bundle(); Bundle chooseLockExtras = new Bundle();
long challenge = mFingerprintManager.generateChallengeBlocking();
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
PASSWORD_QUALITY_SOMETHING); PASSWORD_QUALITY_SOMETHING);
chooseLockExtras.putBoolean( chooseLockExtras.putBoolean(
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, true);
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
return chooseLockExtras; return chooseLockExtras;
} }
private Bundle getFaceChooseLockExtras() { private Bundle getFaceChooseLockExtras() {
Bundle chooseLockExtras = new Bundle(); Bundle chooseLockExtras = new Bundle();
long challenge = mFaceManager.generateChallengeBlocking();
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
PASSWORD_QUALITY_SOMETHING); PASSWORD_QUALITY_SOMETHING);
chooseLockExtras.putBoolean( chooseLockExtras.putBoolean(
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, true);
chooseLockExtras.putLong(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true); chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
return chooseLockExtras; return chooseLockExtras;
} }

View File

@@ -92,8 +92,8 @@ public class ChooseLockPasswordTest {
.setUserId(123) .setUserId(123)
.build(); .build();
assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true)) assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, false))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_FORCE_VERIFY")
.isFalse(); .isFalse();
assertThat((LockscreenCredential) intent.getParcelableExtra( assertThat((LockscreenCredential) intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
@@ -108,19 +108,16 @@ public class ChooseLockPasswordTest {
} }
@Test @Test
public void intentBuilder_setChallenge_shouldAddExtras() { public void intentBuilder_setRequestGatekeeperPassword_shouldAddExtras() {
Intent intent = new IntentBuilder(application) Intent intent = new IntentBuilder(application)
.setChallenge(12345L) .setRequestGatekeeperPassword(true)
.setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC) .setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC)
.setUserId(123) .setUserId(123)
.build(); .build();
assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false)) assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_REQUEST_GK_PW")
.isTrue(); .isTrue();
assertThat(intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0L))
.named("EXTRA_KEY_CHALLENGE")
.isEqualTo(12345L);
assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0)) assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0))
.named("PASSWORD_TYPE_KEY") .named("PASSWORD_TYPE_KEY")
.isEqualTo(PASSWORD_QUALITY_ALPHANUMERIC); .isEqualTo(PASSWORD_QUALITY_ALPHANUMERIC);

View File

@@ -59,8 +59,8 @@ public class ChooseLockPatternTest {
.build(); .build();
assertThat(intent assertThat(intent
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true)) .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, false))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_FORCE_VERIFY")
.isFalse(); .isFalse();
assertThat((LockscreenCredential) intent assertThat((LockscreenCredential) intent
.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) .getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
@@ -72,20 +72,16 @@ public class ChooseLockPatternTest {
} }
@Test @Test
public void intentBuilder_setChallenge_shouldAddExtras() { public void intentBuilder_setRequestGatekeeperPassword_shouldAddExtras() {
Intent intent = new IntentBuilder(application) Intent intent = new IntentBuilder(application)
.setChallenge(12345L) .setRequestGatekeeperPassword(true)
.setUserId(123) .setUserId(123)
.build(); .build();
assertThat(intent assertThat(intent
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false)) .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_REQUEST_GK_PW")
.isTrue(); .isTrue();
assertThat(intent
.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0L))
.named("EXTRA_KEY_CHALLENGE")
.isEqualTo(12345L);
assertThat(intent assertThat(intent
.getIntExtra(Intent.EXTRA_USER_ID, 0)) .getIntExtra(Intent.EXTRA_USER_ID, 0))
.named("EXTRA_USER_ID") .named("EXTRA_USER_ID")

View File

@@ -36,7 +36,7 @@ import org.robolectric.shadows.ShadowActivity.IntentForResult;
public class ChooseLockSettingsHelperTest { public class ChooseLockSettingsHelperTest {
@Test @Test
public void testLaunchConfirmationActivityWithExternalAndChallenge() { public void testLaunchConfirmationActivityWithExternal() {
final Activity activity = Robolectric.setupActivity(Activity.class); final Activity activity = Robolectric.setupActivity(Activity.class);
ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity); ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity);
@@ -45,7 +45,6 @@ public class ChooseLockSettingsHelperTest {
.setHeader("header") .setHeader("header")
.setDescription("description") .setDescription("description")
.setExternal(true) .setExternal(true)
.setChallenge(10000L)
.setUserId(UserHandle.myUserId()); .setUserId(UserHandle.myUserId());
ChooseLockSettingsHelper helper = getChooseLockSettingsHelper(builder); ChooseLockSettingsHelper helper = getChooseLockSettingsHelper(builder);
helper.launch(); helper.launch();
@@ -53,15 +52,10 @@ public class ChooseLockSettingsHelperTest {
ShadowActivity shadowActivity = Shadows.shadowOf(activity); ShadowActivity shadowActivity = Shadows.shadowOf(activity);
Intent startedIntent = shadowActivity.getNextStartedActivity(); Intent startedIntent = shadowActivity.getNextStartedActivity();
assertEquals(new ComponentName("com.android.settings", assertEquals(new ComponentName("com.android.settings", ConfirmLockPattern.class.getName()),
ConfirmLockPattern.InternalActivity.class.getName()),
startedIntent.getComponent()); startedIntent.getComponent());
assertFalse(startedIntent.getBooleanExtra( assertFalse(startedIntent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false)); ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false));
assertTrue(startedIntent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false));
assertEquals(10000L, startedIntent.getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0L));
assertTrue((startedIntent.getFlags() & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0); assertTrue((startedIntent.getFlags() & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0);
assertFalse(startedIntent.getBooleanExtra( assertFalse(startedIntent.getBooleanExtra(
ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)); ConfirmDeviceCredentialBaseFragment.DARK_THEME, false));
@@ -72,7 +66,7 @@ public class ChooseLockSettingsHelperTest {
} }
@Test @Test
public void testLaunchConfirmationActivityInternalAndChallenge() { public void testLaunchConfirmationActivityInternal() {
final Activity activity = Robolectric.setupActivity(Activity.class); final Activity activity = Robolectric.setupActivity(Activity.class);
ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity); ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity);
@@ -80,7 +74,8 @@ public class ChooseLockSettingsHelperTest {
.setTitle("title") .setTitle("title")
.setHeader("header") .setHeader("header")
.setDescription("description") .setDescription("description")
.setChallenge(10000L) .setForceVerifyPath(true)
.setReturnCredentials(true)
.setUserId(UserHandle.myUserId()); .setUserId(UserHandle.myUserId());
ChooseLockSettingsHelper helper = getChooseLockSettingsHelper(builder); ChooseLockSettingsHelper helper = getChooseLockSettingsHelper(builder);
helper.launch(); helper.launch();
@@ -91,12 +86,10 @@ public class ChooseLockSettingsHelperTest {
assertEquals(new ComponentName("com.android.settings", assertEquals(new ComponentName("com.android.settings",
ConfirmLockPattern.InternalActivity.class.getName()), ConfirmLockPattern.InternalActivity.class.getName()),
startedIntent.getComponent()); startedIntent.getComponent());
assertFalse(startedIntent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false));
assertTrue(startedIntent.getBooleanExtra( assertTrue(startedIntent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false)); ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, true));
assertEquals(10000L, startedIntent.getLongExtra( assertTrue(startedIntent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0L)); ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, true));
assertFalse((startedIntent.getFlags() & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0); assertFalse((startedIntent.getFlags() & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0);
assertFalse(startedIntent.getBooleanExtra( assertFalse(startedIntent.getBooleanExtra(
ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)); ConfirmDeviceCredentialBaseFragment.DARK_THEME, false));

View File

@@ -19,14 +19,11 @@ package com.android.settings.password;
import static android.content.pm.PackageManager.FEATURE_FACE; import static android.content.pm.PackageManager.FEATURE_FACE;
import static android.content.pm.PackageManager.FEATURE_FINGERPRINT; import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS;
.HIDE_DISABLED_PREFS; import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY;
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment
.MINIMUM_QUALITY_KEY;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -57,8 +54,6 @@ import org.robolectric.RobolectricTestRunner;
public final class SetNewPasswordControllerTest { public final class SetNewPasswordControllerTest {
private static final int CURRENT_USER_ID = 101; private static final int CURRENT_USER_ID = 101;
private static final long FINGERPRINT_CHALLENGE = -9876512313131L;
private static final long FACE_CHALLENGE = 1352057789L;
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@@ -79,11 +74,7 @@ public final class SetNewPasswordControllerTest {
mSetNewPasswordController = new SetNewPasswordController( mSetNewPasswordController = new SetNewPasswordController(
CURRENT_USER_ID, mPackageManager, mFingerprintManager, mFaceManager, CURRENT_USER_ID, mPackageManager, mFingerprintManager, mFaceManager,
mDevicePolicyManager, mUi); mDevicePolicyManager, mUi);
when(mFingerprintManager.generateChallengeBlocking()).thenReturn(FINGERPRINT_CHALLENGE);
when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true); when(mPackageManager.hasSystemFeature(eq(FEATURE_FINGERPRINT))).thenReturn(true);
when(mFaceManager.generateChallengeBlocking()).thenReturn(FACE_CHALLENGE);
when(mPackageManager.hasSystemFeature(eq(FEATURE_FACE))).thenReturn(true); when(mPackageManager.hasSystemFeature(eq(FEATURE_FACE))).thenReturn(true);
} }
@@ -278,12 +269,8 @@ public final class SetNewPasswordControllerTest {
"All disabled preference should be removed.", "All disabled preference should be removed.",
actualBundle.getBoolean(HIDE_DISABLED_PREFS)); actualBundle.getBoolean(HIDE_DISABLED_PREFS));
assertTrue( assertTrue(
"There must be a fingerprint challenge.", "Fingerprint enroll must request Gatekeeper Password.",
actualBundle.getBoolean(EXTRA_KEY_HAS_CHALLENGE)); actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW));
assertEquals(
"The fingerprint challenge must come from the FingerprintManager",
FINGERPRINT_CHALLENGE,
actualBundle.getLong(EXTRA_KEY_CHALLENGE));
assertTrue( assertTrue(
"The request must be a fingerprint set up request.", "The request must be a fingerprint set up request.",
actualBundle.getBoolean(EXTRA_KEY_FOR_FINGERPRINT)); actualBundle.getBoolean(EXTRA_KEY_FOR_FINGERPRINT));
@@ -302,12 +289,8 @@ public final class SetNewPasswordControllerTest {
"All disabled preference should be removed.", "All disabled preference should be removed.",
actualBundle.getBoolean(HIDE_DISABLED_PREFS)); actualBundle.getBoolean(HIDE_DISABLED_PREFS));
assertTrue( assertTrue(
"There must be a face challenge.", "Face enroll must request Gatekeeper Password",
actualBundle.getBoolean(EXTRA_KEY_HAS_CHALLENGE)); actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW));
assertEquals(
"The face challenge must come from the FaceManager",
FACE_CHALLENGE,
actualBundle.getLong(EXTRA_KEY_CHALLENGE));
assertTrue( assertTrue(
"The request must be a face set up request.", "The request must be a face set up request.",
actualBundle.getBoolean(EXTRA_KEY_FOR_FACE)); actualBundle.getBoolean(EXTRA_KEY_FOR_FACE));