Merge "Route to active unlock component"

This commit is contained in:
Derek Jedral
2023-01-31 19:43:05 +00:00
committed by Android (Google) Code Review
6 changed files with 173 additions and 18 deletions

View File

@@ -49,14 +49,17 @@ public class ActiveUnlockRequireBiometricSetup extends BiometricEnrollBase {
@VisibleForTesting @VisibleForTesting
static final int BIOMETRIC_ENROLL_REQUEST = 1001; static final int BIOMETRIC_ENROLL_REQUEST = 1001;
private static final int ACTIVE_UNLOCK_REQUEST = 1002;
private long mGkPwHandle; private long mGkPwHandle;
private boolean mNextClicked; private boolean mNextClicked;
private ActiveUnlockStatusUtils mActiveUnlockStatusUtils;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activeunlock_require_biometric_setup); setContentView(R.layout.activeunlock_require_biometric_setup);
mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(this);
mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
Log.i(TAG, "mUserId = " + mUserId); Log.i(TAG, "mUserId = " + mUserId);
mGkPwHandle = getIntent().getLongExtra(EXTRA_KEY_GK_PW_HANDLE, 0L); mGkPwHandle = getIntent().getLongExtra(EXTRA_KEY_GK_PW_HANDLE, 0L);
@@ -132,8 +135,10 @@ public class ActiveUnlockRequireBiometricSetup extends BiometricEnrollBase {
CombinedBiometricStatusUtils combinedBiometricStatusUtils = CombinedBiometricStatusUtils combinedBiometricStatusUtils =
new CombinedBiometricStatusUtils(this, mUserId); new CombinedBiometricStatusUtils(this, mUserId);
if (combinedBiometricStatusUtils.hasEnrolled()) { if (combinedBiometricStatusUtils.hasEnrolled()) {
// TODO(b/264813444): launch active unlock setting page in GmsCore without double Intent activeUnlockIntent = mActiveUnlockStatusUtils.getIntent();
// authentication. if (activeUnlockIntent != null) {
startActivityForResult(activeUnlockIntent, ACTIVE_UNLOCK_REQUEST);
}
} }
} }
mNextClicked = false; mNextClicked = false;

View File

@@ -28,6 +28,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController; import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener; import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener;
import com.android.settings.biometrics.combination.CombinedBiometricStatusUtils;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
/** /**
@@ -35,8 +36,7 @@ import com.android.settingslib.RestrictedPreference;
* controls the ability to unlock the phone with watch authentication. * controls the ability to unlock the phone with watch authentication.
*/ */
public class ActiveUnlockStatusPreferenceController public class ActiveUnlockStatusPreferenceController
extends BiometricStatusPreferenceController extends BiometricStatusPreferenceController implements LifecycleObserver {
implements LifecycleObserver, OnContentChangedListener {
/** /**
* Preference key. * Preference key.
* *
@@ -47,7 +47,9 @@ public class ActiveUnlockStatusPreferenceController
@Nullable private PreferenceScreen mPreferenceScreen; @Nullable private PreferenceScreen mPreferenceScreen;
@Nullable private String mSummary; @Nullable private String mSummary;
private final ActiveUnlockStatusUtils mActiveUnlockStatusUtils; private final ActiveUnlockStatusUtils mActiveUnlockStatusUtils;
private final CombinedBiometricStatusUtils mCombinedBiometricStatusUtils;
private final ActiveUnlockSummaryListener mActiveUnlockSummaryListener; private final ActiveUnlockSummaryListener mActiveUnlockSummaryListener;
private final ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener;
public ActiveUnlockStatusPreferenceController(@NonNull Context context) { public ActiveUnlockStatusPreferenceController(@NonNull Context context) {
this(context, KEY_ACTIVE_UNLOCK_SETTINGS); this(context, KEY_ACTIVE_UNLOCK_SETTINGS);
@@ -57,7 +59,31 @@ public class ActiveUnlockStatusPreferenceController
@NonNull Context context, @NonNull String key) { @NonNull Context context, @NonNull String key) {
super(context, key); super(context, key);
mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(context); mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(context);
mActiveUnlockSummaryListener = new ActiveUnlockSummaryListener(context, this); mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId());
OnContentChangedListener onSummaryChangedListener = new OnContentChangedListener() {
@Override
public void onContentChanged(String newContent) {
mSummary = newContent;
if (mPreference != null) {
mPreference.setSummary(getSummaryText());
}
}
};
OnContentChangedListener onDeviceNameChangedListener =
new OnContentChangedListener() {
@Override
public void onContentChanged(String newContent) {
if (mPreference != null) {
mPreference.setSummary(getSummaryText());
}
}
};
mActiveUnlockSummaryListener =
new ActiveUnlockSummaryListener(context, onSummaryChangedListener);
mActiveUnlockDeviceNameListener =
new ActiveUnlockDeviceNameListener(context, onDeviceNameChangedListener);
} }
@@ -65,6 +91,7 @@ public class ActiveUnlockStatusPreferenceController
@OnLifecycleEvent(Lifecycle.Event.ON_START) @OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() { public void onStart() {
mActiveUnlockSummaryListener.subscribe(); mActiveUnlockSummaryListener.subscribe();
mActiveUnlockDeviceNameListener.subscribe();
} }
/** Resets the preference reference on resume. */ /** Resets the preference reference on resume. */
@@ -79,14 +106,7 @@ public class ActiveUnlockStatusPreferenceController
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() { public void onStop() {
mActiveUnlockSummaryListener.unsubscribe(); mActiveUnlockSummaryListener.unsubscribe();
} mActiveUnlockDeviceNameListener.unsubscribe();
@Override
public void onContentChanged(String newContent) {
mSummary = newContent;
if (mPreference != null) {
mPreference.setSummary(getSummaryText());
}
} }
@Override @Override
@@ -120,6 +140,15 @@ public class ActiveUnlockStatusPreferenceController
@Override @Override
protected String getSummaryText() { protected String getSummaryText() {
if (mActiveUnlockStatusUtils.useBiometricFailureLayout()
&& !mActiveUnlockDeviceNameListener.hasEnrolled()
&& !mCombinedBiometricStatusUtils.hasEnrolled()) {
@Nullable final String setupString =
mActiveUnlockStatusUtils.getSummaryWhenBiometricSetupRequired();
if (setupString != null) {
return setupString;
}
}
if (mSummary == null) { if (mSummary == null) {
// return non-empty string to prevent re-sizing of the tile // return non-empty string to prevent re-sizing of the tile
return " "; return " ";
@@ -129,7 +158,6 @@ public class ActiveUnlockStatusPreferenceController
@Override @Override
protected String getSettingsClassName() { protected String getSettingsClassName() {
// TODO(b/264813445): direct user to face & fingerprint setup return ActiveUnlockRequireBiometricSetup.class.getName();
return null;
} }
} }

View File

@@ -242,6 +242,32 @@ public class ActiveUnlockStatusUtils {
} }
} }
/**
* Returns the summary of the active unlock preference when biometrics are needed to set up the
* feature.
*/
@Nullable
public String getSummaryWhenBiometricSetupRequired() {
final boolean faceAllowed = Utils.hasFaceHardware(mContext);
final boolean fingerprintAllowed = Utils.hasFingerprintHardware(mContext);
int summaryRes = getSetupBiometricRes(faceAllowed, fingerprintAllowed);
return summaryRes == 0 ? null : mContext.getString(summaryRes);
}
@StringRes
private static int getSetupBiometricRes(boolean faceAllowed, boolean fingerprintAllowed) {
if (faceAllowed && fingerprintAllowed) {
return R.string.security_settings_activeunlock_require_face_fingerprint_setup_title;
} else if (faceAllowed) {
return R.string.security_settings_activeunlock_require_face_setup_title;
} else if (fingerprintAllowed) {
return R.string.security_settings_activeunlock_require_fingerprint_setup_title;
} else {
return 0;
}
}
private static String getFlagState() { private static String getFlagState() {
return DeviceConfig.getProperty(DeviceConfig.NAMESPACE_REMOTE_AUTH, CONFIG_FLAG_NAME); return DeviceConfig.getProperty(DeviceConfig.NAMESPACE_REMOTE_AUTH, CONFIG_FLAG_NAME);
} }

View File

@@ -55,6 +55,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
@VisibleForTesting @VisibleForTesting
static final int CONFIRM_REQUEST = 2001; static final int CONFIRM_REQUEST = 2001;
private static final int CHOOSE_LOCK_REQUEST = 2002; private static final int CHOOSE_LOCK_REQUEST = 2002;
protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential"; private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity"; private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";
@@ -68,8 +69,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
private boolean mConfirmCredential; private boolean mConfirmCredential;
@Nullable private FaceManager mFaceManager; @Nullable private FaceManager mFaceManager;
@Nullable private FingerprintManager mFingerprintManager; @Nullable private FingerprintManager mFingerprintManager;
// Do not finish() if choosing/confirming credential, or showing fp/face settings // Do not finish() if choosing/confirming credential, showing fp/face settings, or launching
private boolean mDoNotFinishActivity; // active unlock
protected boolean mDoNotFinishActivity;
@Nullable private String mRetryPreferenceKey = null; @Nullable private String mRetryPreferenceKey = null;
@Nullable private Bundle mRetryPreferenceExtra = null; @Nullable private Bundle mRetryPreferenceExtra = null;
@@ -132,7 +134,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
} }
} }
private boolean onRetryPreferenceTreeClick(Preference preference, final boolean retry) { protected boolean onRetryPreferenceTreeClick(Preference preference, final boolean retry) {
final String key = preference.getKey(); final String key = preference.getKey();
final Context context = requireActivity().getApplicationContext(); final Context context = requireActivity().getApplicationContext();
@@ -323,6 +325,14 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
return resId == 0 ? "" : getString(resId); return resId == 0 ? "" : getString(resId);
} }
protected int getUserId() {
return mUserId;
}
protected long getGkPwHandle() {
return mGkPwHandle;
}
@NonNull @NonNull
private String getUseClass2BiometricSummary() { private String getUseClass2BiometricSummary() {
boolean isFaceAllowed = false; boolean isFaceAllowed = false;

View File

@@ -15,9 +15,14 @@
*/ */
package com.android.settings.biometrics.combination; package com.android.settings.biometrics.combination;
import static com.android.settings.biometrics.activeunlock.ActiveUnlockStatusPreferenceController.KEY_ACTIVE_UNLOCK_SETTINGS;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -25,6 +30,7 @@ import androidx.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener; import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener;
import com.android.settings.biometrics.activeunlock.ActiveUnlockDeviceNameListener; import com.android.settings.biometrics.activeunlock.ActiveUnlockDeviceNameListener;
import com.android.settings.biometrics.activeunlock.ActiveUnlockRequireBiometricSetup;
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
@@ -42,6 +48,7 @@ public class CombinedBiometricSettings extends BiometricsSettingsBase {
private static final String KEY_INTRO_PREFERENCE = "biometric_intro"; private static final String KEY_INTRO_PREFERENCE = "biometric_intro";
private ActiveUnlockStatusUtils mActiveUnlockStatusUtils; private ActiveUnlockStatusUtils mActiveUnlockStatusUtils;
private CombinedBiometricStatusUtils mCombinedBiometricStatusUtils;
@Nullable private ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener; @Nullable private ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener;
@Override @Override
@@ -55,6 +62,7 @@ public class CombinedBiometricSettings extends BiometricsSettingsBase {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(getActivity()); mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(getActivity());
mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(getActivity(), mUserId);
if (mActiveUnlockStatusUtils.isAvailable()) { if (mActiveUnlockStatusUtils.isAvailable()) {
updateUiForActiveUnlock(); updateUiForActiveUnlock();
} }
@@ -121,6 +129,35 @@ public class CombinedBiometricSettings extends BiometricsSettingsBase {
return SettingsEnums.COMBINED_BIOMETRIC; return SettingsEnums.COMBINED_BIOMETRIC;
} }
@Override
protected boolean onRetryPreferenceTreeClick(Preference preference, final boolean retry) {
if (!mActiveUnlockStatusUtils.isAvailable()
|| !KEY_ACTIVE_UNLOCK_SETTINGS.equals(preference.getKey())) {
return super.onRetryPreferenceTreeClick(preference, retry);
}
mDoNotFinishActivity = true;
Intent intent;
if (mActiveUnlockStatusUtils.useBiometricFailureLayout()
&& mActiveUnlockDeviceNameListener != null
&& !mActiveUnlockDeviceNameListener.hasEnrolled()
&& !mCombinedBiometricStatusUtils.hasEnrolled()) {
intent = new Intent(getActivity(), ActiveUnlockRequireBiometricSetup.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
int userId = mUserId;
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, getGkPwHandle());
} else {
intent = mActiveUnlockStatusUtils.getIntent();
}
if (intent != null) {
startActivityForResult(intent, ACTIVE_UNLOCK_REQUEST);
}
return true;
}
@Override @Override
protected String getUseAnyBiometricSummary() { protected String getUseAnyBiometricSummary() {
// either Active Unlock is not enabled or no device is enrolled. // either Active Unlock is not enabled or no device is enrolled.

View File

@@ -32,6 +32,7 @@ import android.os.UserManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.ActiveUnlockTestUtils; import com.android.settings.testutils.ActiveUnlockTestUtils;
import com.android.settings.testutils.shadow.ShadowDeviceConfig; import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
@@ -162,9 +163,57 @@ public class ActiveUnlockStatusPreferenceControllerTest {
assertThat(mPreference.getSummary().toString()).isEqualTo(summary); assertThat(mPreference.getSummary().toString()).isEqualTo(summary);
} }
@Test
public void biometricsNotSetUp_deviceNameIsNotSet_setupBiometricStringShown() {
ActiveUnlockTestUtils.enable(mContext, ActiveUnlockStatusUtils.BIOMETRIC_FAILURE_LAYOUT);
updateSummary("newSummary");
mController.displayPreference(mPreferenceScreen);
mController.onStart();
idleMainLooper();
assertThat(mPreference.getSummary()).isEqualTo(mContext.getString(
R.string.security_settings_activeunlock_require_face_fingerprint_setup_title));
}
@Test
public void biometricNotSetUp_deviceNameIsSet_summaryShown() {
ActiveUnlockTestUtils.enable(mContext, ActiveUnlockStatusUtils.BIOMETRIC_FAILURE_LAYOUT);
String summary = "newSummary";
updateSummary(summary);
updateDeviceName("deviceName");
mController.displayPreference(mPreferenceScreen);
mController.onStart();
idleMainLooper();
assertThat(mPreference.getSummary()).isEqualTo(summary);
}
@Test
public void biometricSetUp_summaryShown() {
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
ActiveUnlockTestUtils.enable(mContext, ActiveUnlockStatusUtils.BIOMETRIC_FAILURE_LAYOUT);
String summary = "newSummary";
updateSummary(summary);
mController.displayPreference(mPreferenceScreen);
mController.onStart();
idleMainLooper();
assertThat(mPreference.getSummary()).isEqualTo(summary);
}
private void updateSummary(String summary) { private void updateSummary(String summary) {
FakeContentProvider.setTileSummary(summary); FakeContentProvider.setTileSummary(summary);
mContext.getContentResolver().notifyChange(FakeContentProvider.URI, null /* observer */); mContext.getContentResolver().notifyChange(FakeContentProvider.URI, null /* observer */);
idleMainLooper(); idleMainLooper();
} }
private void updateDeviceName(String deviceName) {
FakeContentProvider.setDeviceName(deviceName);
mContext.getContentResolver().notifyChange(FakeContentProvider.URI, null /* observer */);
idleMainLooper();
}
} }