Use setting as base activity for fingerprint

Change to use FingerprintSetting as base activity when use launch
"Fingerprint Unlock" from Settings -> Security. And then we can prevent
that necesssary pop-up activites become full-screen.

Bug: 232874879

Test: manual test following cases on fp-only devices, and enable don't
      keep activity and test them again.
      1. fp enrollment on SUW
      2. fp add another on SUW
      3. add first fp on Security Settings
      4. add another fp on Security Settings
Test: atest FingerprintStatusUtilsTest BiometricsSafetySourceTest
Test: robo test for SetupFingerprintEnrollFindSensorTest
      SetupFingerprintEnrollFinishTest
      FingerprintEnrollFindSensorTest FingerprintEnrollEnrollingTest

Change-Id: Ib1c2ef9f93fb910eed2930f871c0c69bdb94bcbd
This commit is contained in:
Milton Wu
2022-07-28 08:15:27 +00:00
parent 66479d6de4
commit 84b39c3ed0
10 changed files with 178 additions and 45 deletions

View File

@@ -24,8 +24,6 @@ import android.view.View;
import com.android.settings.R;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.util.WizardManagerHelper;
/**
* Abstract base activity which handles the actual enrolling for biometrics.
*/
@@ -62,30 +60,18 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
@Override
protected void onStop() {
super.onStop();
if (mSidecar != null) {
mSidecar.setListener(null);
}
if (!isChangingConfigurations()) {
if (mSidecar != null) {
mSidecar.cancelEnrollment();
getSupportFragmentManager()
.beginTransaction().remove(mSidecar).commitAllowingStateLoss();
}
if (!WizardManagerHelper.isAnySetupWizard(getIntent())
&& !BiometricUtils.isAnyMultiBiometricFlow(this)) {
setResult(RESULT_TIMEOUT);
}
finish();
}
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
// Prevent super.onStop() from finishing, since we handle this in our onStop().
return false;
super.onStop();
}
@Override

View File

@@ -31,11 +31,13 @@ import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricErrorDialog;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.slices.CustomSliceRegistry;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import java.util.ArrayList;
@@ -112,6 +114,25 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
startEnrollment();
}
@Override
protected void onStop() {
if (!isChangingConfigurations()) {
if (!WizardManagerHelper.isAnySetupWizard(getIntent())
&& !BiometricUtils.isAnyMultiBiometricFlow(this)) {
setResult(RESULT_TIMEOUT);
}
finish();
}
super.onStop();
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
// Prevent super.onStop() from finishing, since we handle this in our onStop().
return false;
}
@Override
public void startEnrollment() {
super.startEnrollment();

View File

@@ -339,8 +339,23 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected void onStop() {
super.onStop();
if (!isChangingConfigurations()) {
if (!WizardManagerHelper.isAnySetupWizard(getIntent())
&& !BiometricUtils.isAnyMultiBiometricFlow(this)
&& !mFromSettingsSummary) {
setResult(RESULT_TIMEOUT);
}
finish();
}
stopIconAnimation();
super.onStop();
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
// Prevent super.onStop() from finishing, since we handle this in our onStop().
return false;
}
@Override

View File

@@ -49,8 +49,8 @@ import java.util.List;
public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
BiometricEnrollSidecar.Listener {
private static final String TAG = "FingerprintEnrollFindSensor";
private static final String SAVED_STATE_IS_NEXT_CLICKED = "is_next_clicked";
@Nullable
private FingerprintFindSensorAnimation mAnimation;
@@ -174,6 +174,15 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
mAnimation = (FingerprintFindSensorAnimation) animationView;
}
}
if (savedInstanceState != null) {
mNextClicked = savedInstanceState.getBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_STATE_IS_NEXT_CLICKED, mNextClicked);
}
@Override
@@ -240,7 +249,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
mNextClicked = false;
proceedToEnrolling(false /* cancelEnrollment */);
} else {
FingerprintErrorDialog.showErrorDialog(this, errMsgId);
@@ -341,6 +349,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
finish();
} else {
// We came back from enrolling but it wasn't completed, start again.
mNextClicked = false;
startLookingForFingerprint();
}
break;

View File

@@ -32,7 +32,6 @@ import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
@@ -114,9 +113,6 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
setResult(RESULT_FINISHED);
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
postEnroll();
} else if (mFromSettingsSummary) {
// Only launch fingerprint settings if enrollment was triggered through settings summary
launchFingerprintSettings();
}
finish();
}
@@ -148,21 +144,15 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
}
}
private void launchFingerprintSettings() {
final Intent intent = new Intent(ACTION_FINGERPRINT_SETTINGS);
intent.setPackage(Utils.SETTINGS_PACKAGE_NAME);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, mChallenge);
startActivity(intent);
overridePendingTransition(R.anim.sud_slide_back_in, R.anim.sud_slide_back_out);
}
private void onAddAnotherButtonClick(View view) {
startActivityForResult(getFingerprintEnrollingIntent(), BiometricUtils.REQUEST_ADD_ANOTHER);
}
@Override
protected boolean shouldFinishWhenBackgrounded() {
return !isFinishing() && super.shouldFinishWhenBackgrounded();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
updateFingerprintSuggestionEnableState();

View File

@@ -22,6 +22,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROF
import static android.app.admin.DevicePolicyResources.UNDEFINED;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY;
import android.app.Activity;
import android.app.Dialog;
@@ -62,6 +63,7 @@ import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
@@ -69,6 +71,7 @@ import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.transition.SettingsTransitionHelper;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.TwoTargetPreference;
@@ -129,6 +132,8 @@ public class FingerprintSettings extends SubSettings {
private static final String KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE =
"fingerprint_enable_keyguard_toggle";
private static final String KEY_LAUNCHED_CONFIRM = "launched_confirm";
private static final String KEY_HAS_FIRST_ENROLLED = "has_first_enrolled";
private static final String KEY_IS_ENROLLING = "is_enrolled";
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
@@ -140,6 +145,7 @@ public class FingerprintSettings extends SubSettings {
private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102;
private static final int ADD_FINGERPRINT_REQUEST = 10;
private static final int AUTO_ADD_FIRST_FINGERPRINT_REQUEST = 11;
protected static final boolean DEBUG = false;
@@ -149,10 +155,11 @@ public class FingerprintSettings extends SubSettings {
private boolean mInFingerprintLockout;
private byte[] mToken;
private boolean mLaunchedConfirm;
private boolean mHasFirstEnrolled = true;
private Drawable mHighlightDrawable;
private int mUserId;
private final List<FooterColumn> mFooterColumns = new ArrayList<>();
private boolean mEnrollClicked;
private boolean mIsEnrolling;
private long mChallenge;
@@ -341,6 +348,9 @@ public class FingerprintSettings extends SubSettings {
}
mFingerprintsRenaming = new HashMap<Integer, String>();
mUserId = getActivity().getIntent().getIntExtra(
Intent.EXTRA_USER_ID, UserHandle.myUserId());
mHasFirstEnrolled = mFingerprintManager.hasEnrolledFingerprints(mUserId);
if (savedInstanceState != null) {
mFingerprintsRenaming = (HashMap<Integer, String>)
@@ -349,9 +359,10 @@ public class FingerprintSettings extends SubSettings {
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
mLaunchedConfirm = savedInstanceState.getBoolean(
KEY_LAUNCHED_CONFIRM, false);
mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling);
mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED,
mHasFirstEnrolled);
}
mUserId = getActivity().getIntent().getIntExtra(
Intent.EXTRA_USER_ID, UserHandle.myUserId());
// Need to authenticate a session token if none
if (mToken == null && mLaunchedConfirm == false) {
@@ -546,7 +557,7 @@ public class FingerprintSettings extends SubSettings {
@Override
public void onStop() {
super.onStop();
if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mEnrollClicked) {
if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mIsEnrolling) {
getActivity().finish();
}
}
@@ -557,13 +568,15 @@ public class FingerprintSettings extends SubSettings {
mToken);
outState.putBoolean(KEY_LAUNCHED_CONFIRM, mLaunchedConfirm);
outState.putSerializable("mFingerprintsRenaming", mFingerprintsRenaming);
outState.putBoolean(KEY_IS_ENROLLING, mIsEnrolling);
outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled);
}
@Override
public boolean onPreferenceTreeClick(Preference pref) {
final String key = pref.getKey();
if (KEY_FINGERPRINT_ADD.equals(key)) {
mEnrollClicked = true;
mIsEnrolling = true;
Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME,
FingerprintEnrollEnrolling.class.getName());
@@ -659,6 +672,11 @@ public class FingerprintSettings extends SubSettings {
BiometricUtils.removeGatekeeperPasswordHandle(getActivity(),
data);
updateAddPreference();
if (!mHasFirstEnrolled && !mIsEnrolling) {
mIsEnrolling = true;
addFirstFingerprint(
BiometricUtils.getGatekeeperPasswordHandle(data));
}
});
} else {
Log.d(TAG, "Data null or GK PW missing");
@@ -669,12 +687,19 @@ public class FingerprintSettings extends SubSettings {
finish();
}
} else if (requestCode == ADD_FINGERPRINT_REQUEST) {
mEnrollClicked = false;
mIsEnrolling = false;
if (resultCode == RESULT_TIMEOUT) {
Activity activity = getActivity();
activity.setResult(resultCode);
activity.finish();
}
} else if (requestCode == AUTO_ADD_FIRST_FINGERPRINT_REQUEST) {
mIsEnrolling = false;
mHasFirstEnrolled = false;
if (resultCode != RESULT_FINISHED) {
Log.d(TAG, "Add first fingerprint fail, result:" + resultCode);
finish();
}
}
}
@@ -746,6 +771,23 @@ public class FingerprintSettings extends SubSettings {
}
}
private void addFirstFingerprint(@Nullable Long gkPwHandle) {
Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME,
FingerprintEnrollIntroductionInternal.class.getName());
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE);
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
if (gkPwHandle != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, (long) gkPwHandle);
}
startActivityForResult(intent, AUTO_ADD_FIRST_FINGERPRINT_REQUEST);
}
@VisibleForTesting
void deleteFingerPrint(Fingerprint fingerPrint) {
mRemovalSidecar.startRemove(fingerPrint, mUserId);

View File

@@ -78,8 +78,7 @@ public class FingerprintStatusUtils {
* Returns the class name of the Settings page corresponding to fingerprint settings.
*/
public String getSettingsClassName() {
return hasEnrolled() ? FingerprintSettings.class.getName()
: FingerprintEnrollIntroductionInternal.class.getName();
return FingerprintSettings.class.getName();
}
/**

View File

@@ -165,4 +165,76 @@ public class FingerprintEnrollFindSensorTest {
null);
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
}
@Test
public void onActivityResult_EnrollRequestResultFinishShallBeSentBack() {
final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode();
// Start enrolling
EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
enrollmentCallback.onEnrollmentProgress(123);
enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test");
// onStop shall not change default activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult);
// onActivityResult from Enrolling activity shall be sent back
final int testResult = BiometricEnrollBase.RESULT_FINISHED;
mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null);
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
assertThat(mActivity.isFinishing()).isEqualTo(true);
// onStop shall not change last activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
}
@Test
public void onActivityResult_EnrollRequestResultSkipShallBeSentBack() {
final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode();
// Start enrolling
EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
enrollmentCallback.onEnrollmentProgress(123);
enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test");
// onStop shall not change default activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult);
// onActivityResult from Enrolling activity shall be sent back
final int testResult = BiometricEnrollBase.RESULT_SKIP;
mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null);
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
assertThat(mActivity.isFinishing()).isEqualTo(true);
// onStop shall not change last activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
}
@Test
public void onActivityResult_EnrollRequestResultTimeoutShallBeSentBack() {
final int defaultActivityResult = Shadows.shadowOf(mActivity).getResultCode();
// Start enrolling
EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
enrollmentCallback.onEnrollmentProgress(123);
enrollmentCallback.onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, "test");
// onStop shall not change default activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(defaultActivityResult);
// onActivityResult from Enrolling activity shall be sent back
final int testResult = BiometricEnrollBase.RESULT_TIMEOUT;
mActivity.onActivityResult(BiometricEnrollBase.ENROLL_REQUEST, testResult, null);
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
assertThat(mActivity.isFinishing()).isEqualTo(true);
// onStop shall not change last activity result
mActivity.onStop();
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(testResult);
}
}

View File

@@ -179,11 +179,11 @@ public class FingerprintStatusUtilsTest {
}
@Test
public void getSettingsClassName_whenNotEnrolled_returnsFingerprintEnrollInduction() {
public void getSettingsClassName_whenNotEnrolled_returnsFingerprintSettings() {
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
assertThat(mFingerprintStatusUtils.getSettingsClassName())
.isEqualTo(FingerprintEnrollIntroductionInternal.class.getName());
.isEqualTo(FingerprintSettings.class.getName());
}
@Test

View File

@@ -47,7 +47,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.Settings;
import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal;
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
import com.android.settings.testutils.ResourcesUtils;
@@ -186,7 +185,7 @@ public class BiometricsSafetySourceTest {
assertSafetySourceEnabledDataSetWithSingularSummary(
"security_settings_fingerprint_preference_title",
"security_settings_fingerprint_preference_summary_none",
FingerprintEnrollIntroductionInternal.class.getName());
FingerprintSettings.class.getName());
}
@Test