Merge "Launch Face Settings when device enrolled face" into tm-qpr-dev am: 1d68fbf007 am: 544feb9013

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

Change-Id: I748aafeb257bfc6325f5e3a0ef724dbd0e36d697
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Milton Wu
2023-03-22 01:33:58 +00:00
committed by Automerger Merge Worker
4 changed files with 160 additions and 6 deletions

View File

@@ -185,7 +185,9 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
mUserManager = getUserManager(); mUserManager = getUserManager();
updatePasswordQuality(); updatePasswordQuality();
if (!mConfirmingCredentials) { // Check isFinishing() because FaceEnrollIntroduction may finish self to launch
// FaceSettings during onCreate()
if (!mConfirmingCredentials && !isFinishing()) {
if (!mHasPassword) { if (!mHasPassword) {
// No password registered, launch into enrollment wizard. // No password registered, launch into enrollment wizard.
mConfirmingCredentials = true; mConfirmingCredentials = true;

View File

@@ -28,6 +28,7 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager; import android.hardware.face.FaceManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.text.Html; import android.text.Html;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.util.Log; import android.util.Log;
@@ -42,6 +43,7 @@ import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollActivity; import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricEnrollIntroduction; import com.android.settings.biometrics.BiometricEnrollIntroduction;
@@ -110,8 +112,26 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
mFaceManager = getFaceManager();
if (savedInstanceState == null
&& !WizardManagerHelper.isAnySetupWizard(getIntent())
&& !getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false)
&& maxFacesEnrolled()) {
// from tips && maxEnrolled
Log.d(TAG, "launch face settings");
launchFaceSettingsActivity();
finish();
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Wait super::onCreated() then return because SuperNotCalledExceptio will be thrown
// if we don't wait for it.
if (isFinishing()) {
return;
}
// Apply extracted theme color to icons. // Apply extracted theme color to icons.
final ImageView iconGlasses = findViewById(R.id.icon_glasses); final ImageView iconGlasses = findViewById(R.id.icon_glasses);
final ImageView iconLooking = findViewById(R.id.icon_looking); final ImageView iconLooking = findViewById(R.id.icon_looking);
@@ -152,8 +172,6 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
infoMessageRequireEyes.setText(getInfoMessageRequireEyes()); infoMessageRequireEyes.setText(getInfoMessageRequireEyes());
} }
mFaceManager = getFaceManager();
// This path is an entry point for SetNewPasswordController, e.g. // This path is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD // adb shell am start -a android.app.action.SET_NEW_PASSWORD
if (mToken == null && BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) { if (mToken == null && BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
@@ -191,6 +209,24 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
Log.v(TAG, "cameraPrivacyEnabled : " + cameraPrivacyEnabled); Log.v(TAG, "cameraPrivacyEnabled : " + cameraPrivacyEnabled);
} }
private void launchFaceSettingsActivity() {
final Intent intent = new Intent(this, Settings.FaceSettingsInternalActivity.class);
final byte[] token = getIntent().getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
if (token != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
}
final int userId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
if (userId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, userId);
}
BiometricUtils.copyMultiBiometricExtras(getIntent(), intent);
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(EXTRA_KEY_CHALLENGE, getIntent().getLongExtra(EXTRA_KEY_CHALLENGE, -1L));
intent.putExtra(EXTRA_KEY_SENSOR_ID, getIntent().getIntExtra(EXTRA_KEY_SENSOR_ID, -1));
startActivity(intent);
}
@VisibleForTesting @VisibleForTesting
@Nullable @Nullable
protected FaceManager getFaceManager() { protected FaceManager getFaceManager() {
@@ -232,6 +268,15 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
listenFoldEventForPostureGuidance();
}
private void listenFoldEventForPostureGuidance() {
if (maxFacesEnrolled()) {
Log.d(TAG, "Device has enrolled face, do not show posture guidance");
return;
}
if (getPostureGuidanceIntent() == null) { if (getPostureGuidanceIntent() == null) {
Log.d(TAG, "Device do not support posture guidance"); Log.d(TAG, "Device do not support posture guidance");
return; return;

View File

@@ -51,6 +51,8 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
@@ -62,6 +64,7 @@ import com.android.settings.testutils.shadow.ShadowUtils;
import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifLayout; import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupdesign.view.BottomScrollView; import com.google.android.setupdesign.view.BottomScrollView;
@@ -168,6 +171,7 @@ public class FaceEnrollIntroductionTest {
@After @After
public void tearDown() { public void tearDown() {
ShadowUtils.reset(); ShadowUtils.reset();
ShadowLockPatternUtils.reset();
} }
private void setupActivity() { private void setupActivity() {
@@ -315,7 +319,7 @@ public class FaceEnrollIntroductionTest {
} }
@Test @Test
public void testFaceEnrollEducation_hasBottomScrollView() { public void testFaceEnrollIntroduction_hasBottomScrollView() {
setupActivity(); setupActivity();
BottomScrollView scrollView = getGlifLayout(mActivity).findViewById(R.id.sud_scroll_view); BottomScrollView scrollView = getGlifLayout(mActivity).findViewById(R.id.sud_scroll_view);
@@ -387,7 +391,7 @@ public class FaceEnrollIntroductionTest {
} }
@Test @Test
public void testFaceEnrollEducation_onFoldedUpdated_folded() { public void testFaceEnrollIntroduction_onFoldedUpdated_folded() {
final Configuration newConfig = new Configuration(); final Configuration newConfig = new Configuration();
newConfig.smallestScreenWidthDp = DENSITY_DEFAULT; newConfig.smallestScreenWidthDp = DENSITY_DEFAULT;
setupActivityForPosture(); setupActivityForPosture();
@@ -400,4 +404,97 @@ public class FaceEnrollIntroductionTest {
assertThat(mSpyActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_CLOSED); assertThat(mSpyActivity.getDevicePostureState()).isEqualTo(DEVICE_POSTURE_CLOSED);
} }
@Test
public void testFaceEnrollIntroduction_maxFacesEnrolled_launchFaceSettings() {
setFaceManagerToHave(1 /* numEnrollments */);
final Intent intent = new Intent();
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
mController.create();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
final Intent nextStartedActivity = shadowActivity.getNextStartedActivity();
assertThat(nextStartedActivity).isNotNull();
assertThat(nextStartedActivity.getComponent().getClassName())
.isEqualTo(Settings.FaceSettingsInternalActivity.class.getName());
}
@Test
public void testFaceEnrollIntroduction_maxFacesEnrolled_isSuw_notLaunchFaceSettings() {
setFaceManagerToHave(1 /* numEnrollments */);
ShadowLockPatternUtils.setActivePasswordQuality(PASSWORD_QUALITY_NUMERIC);
final Intent intent = new Intent();
intent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
mController.create();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
final Intent nextStartedActivity = shadowActivity.getNextStartedActivity();
assertThat(nextStartedActivity).isNull();
}
@Test
public void testFaceEnrollIntroduction_maxFacesEnrolled_fromSettings_notLaunchFaceSettings() {
setFaceManagerToHave(1 /* numEnrollments */);
ShadowLockPatternUtils.setActivePasswordQuality(PASSWORD_QUALITY_NUMERIC);
final Intent intent = new Intent();
intent.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
mController.create();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
final Intent nextStartedActivity = shadowActivity.getNextStartedActivity();
assertThat(nextStartedActivity).isNull();
}
@Test
public void testFaceEnrollIntroduction_hasPostureCallback() {
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any()))
.thenReturn(new Intent());
setFaceManagerToHave(0 /* numEnrollments */);
ShadowLockPatternUtils.setActivePasswordQuality(PASSWORD_QUALITY_NUMERIC);
final Intent intent = new Intent();
intent.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
mController.create();
mController.start();
assertThat(mActivity.getPostureCallback()).isNotNull();
}
@Test
public void testFaceEnrollIntroduction_maxFacesEnrolled_noPostureCallback() {
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any()))
.thenReturn(new Intent());
setFaceManagerToHave(1 /* numEnrollments */);
ShadowLockPatternUtils.setActivePasswordQuality(PASSWORD_QUALITY_NUMERIC);
final Intent intent = new Intent();
intent.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
mActivity = (TestFaceEnrollIntroduction) mController.get();
mActivity.mOverrideFaceManager = mFaceManager;
mController.create();
mController.start();
assertThat(mActivity.getPostureCallback()).isNull();
}
} }

View File

@@ -40,6 +40,7 @@ import java.util.Map;
public class ShadowLockPatternUtils { public class ShadowLockPatternUtils {
private static boolean sDeviceEncryptionEnabled; private static boolean sDeviceEncryptionEnabled;
private static Map<Integer, Integer> sUserToActivePasswordQualityMap = new HashMap<>();
private static Map<Integer, Integer> sUserToComplexityMap = new HashMap<>(); private static Map<Integer, Integer> sUserToComplexityMap = new HashMap<>();
private static Map<Integer, Integer> sUserToProfileComplexityMap = new HashMap<>(); private static Map<Integer, Integer> sUserToProfileComplexityMap = new HashMap<>();
private static Map<Integer, PasswordMetrics> sUserToMetricsMap = new HashMap<>(); private static Map<Integer, PasswordMetrics> sUserToMetricsMap = new HashMap<>();
@@ -54,6 +55,7 @@ public class ShadowLockPatternUtils {
@Resetter @Resetter
public static void reset() { public static void reset() {
sUserToActivePasswordQualityMap.clear();
sUserToComplexityMap.clear(); sUserToComplexityMap.clear();
sUserToProfileComplexityMap.clear(); sUserToProfileComplexityMap.clear();
sUserToMetricsMap.clear(); sUserToMetricsMap.clear();
@@ -87,7 +89,11 @@ public class ShadowLockPatternUtils {
@Implementation @Implementation
protected int getActivePasswordQuality(int userId) { protected int getActivePasswordQuality(int userId) {
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; final Integer activePasswordQuality = sUserToActivePasswordQualityMap.get(userId);
if (activePasswordQuality == null) {
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
return activePasswordQuality;
} }
@Implementation @Implementation
@@ -227,6 +233,10 @@ public class ShadowLockPatternUtils {
sUserToProfileMetricsMap.put(UserHandle.myUserId(), metrics); sUserToProfileMetricsMap.put(UserHandle.myUserId(), metrics);
} }
public static void setActivePasswordQuality(int quality) {
sUserToActivePasswordQualityMap.put(UserHandle.myUserId(), quality);
}
@Implementation @Implementation
public boolean isLockScreenDisabled(int userId) { public boolean isLockScreenDisabled(int userId) {
return false; return false;