Merge "[Biometric Onboarding & Edu] Support ways to use section for Face & FP" into main

This commit is contained in:
Shawn Lin
2025-01-19 19:05:07 -08:00
committed by Android (Google) Code Review
15 changed files with 573 additions and 0 deletions

View File

@@ -29,6 +29,7 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollBase;
@@ -76,6 +77,12 @@ public class CombinedBiometricSettings extends BiometricsSettingsBase {
if (mActiveUnlockStatusUtils.isAvailable()) {
updateUiForActiveUnlock();
}
if (Flags.biometricsOnboardingEducation()) {
final PreferenceCategory category = findPreference(KEY_USE_BIOMETRIC_PREFERENCE);
if (category != null) {
category.setVisible(false);
}
}
}
private void updateUiForActiveUnlock() {

View File

@@ -47,6 +47,7 @@ import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
@@ -76,6 +77,8 @@ public class FaceSettings extends DashboardFragment {
"security_settings_face_delete_faces_container";
private static final String PREF_KEY_ENROLL_FACE_UNLOCK =
"security_settings_face_enroll_faces_container";
private static final String PREF_KEY_USE_FACE_TO_CATEGORY =
"biometric_settings_use_face_to";
public static final String SECURITY_SETTINGS_FACE_MANAGE_CATEGORY =
"security_settings_face_manage_category";
@@ -238,6 +241,12 @@ public class FaceSettings extends DashboardFragment {
if (savedInstanceState != null) {
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
}
if (Flags.biometricsOnboardingEducation()) {
final PreferenceCategory category =
findPreference(PREF_KEY_USE_FACE_TO_CATEGORY);
category.setVisible(true);
}
}
@Override

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2025 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.face;
import static android.provider.Settings.Secure.FACE_APP_ENABLED;
import android.content.Context;
import android.hardware.face.FaceManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.android.settings.Utils;
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
public class FaceSettingsAppsPreferenceController extends
FaceSettingsPreferenceController {
private static final int ON = 1;
private static final int OFF = 0;
private static final int DEFAULT = ON;
private FaceManager mFaceManager;
public FaceSettingsAppsPreferenceController(@NonNull Context context, @NonNull String key) {
super(context, key);
mFaceManager = Utils.getFaceManagerOrNull(context);
}
@Override
public boolean isChecked() {
return Settings.Secure.getIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED,
DEFAULT, getUserId()) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED,
isChecked ? ON : OFF, getUserId());
}
@Override
public int getAvailabilityStatus() {
final ActiveUnlockStatusUtils activeUnlockStatusUtils =
new ActiveUnlockStatusUtils(mContext);
if (!Utils.hasFaceHardware(mContext)
&& !activeUnlockStatusUtils.isAvailable()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mFaceManager == null) {
return AVAILABLE_UNSEARCHABLE;
}
// This preference will be available only if the user has registered face.
final boolean hasFaceEnrolledUser = mFaceManager.hasEnrolledTemplates(getUserId());
if (hasFaceEnrolledUser) {
return AVAILABLE;
} else {
return AVAILABLE_UNSEARCHABLE;
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2025 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.face;
import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED;
import android.content.Context;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.android.settings.Utils;
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
public class FaceSettingsKeyguardUnlockPreferenceController extends
FaceSettingsPreferenceController {
private static final int ON = 1;
private static final int OFF = 0;
private static final int DEFAULT = ON;
public FaceSettingsKeyguardUnlockPreferenceController(
@NonNull Context context, @NonNull String key) {
super(context, key);
}
@Override
public boolean isChecked() {
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
FACE_KEYGUARD_ENABLED, DEFAULT, getUserId()) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putIntForUser(mContext.getContentResolver(),
FACE_KEYGUARD_ENABLED, isChecked ? ON : OFF, getUserId());
}
@Override
public int getAvailabilityStatus() {
final ActiveUnlockStatusUtils activeUnlockStatusUtils =
new ActiveUnlockStatusUtils(mContext);
if (activeUnlockStatusUtils.isAvailable()) {
return getAvailabilityFromRestrictingAdmin();
}
if (!Utils.hasFaceHardware(mContext)) {
return UNSUPPORTED_ON_DEVICE;
}
return getAvailabilityFromRestrictingAdmin();
}
private int getAvailabilityFromRestrictingAdmin() {
return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE;
}
}

View File

@@ -273,6 +273,8 @@ public class FingerprintSettings extends SubSettings {
"security_settings_fingerprint_footer";
private static final String KEY_BIOMETRICS_AUTHENTICATION_REQUESTED =
"biometrics_authentication_requested";
private static final String KEY_BIOMETRICS_USE_FINGERPRINT_TO_CATEGORY =
"biometric_settings_use_fingerprint_to";
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
@@ -656,6 +658,9 @@ public class FingerprintSettings extends SubSettings {
private PreferenceScreen createPreferenceHierarchy() {
PreferenceScreen root = getPreferenceScreen();
addFingerprintPreferences(root);
if (Flags.biometricsOnboardingEducation()) {
setupUseFingerprintToPreferences();
}
setPreferenceScreen(root);
return root;
}
@@ -685,6 +690,10 @@ public class FingerprintSettings extends SubSettings {
if (mFingerprintsEnrolledCategory != null) {
mFingerprintsEnrolledCategory.removeAll();
}
if (Flags.biometricsOnboardingEducation()) {
mFingerprintsEnrolledCategory.setTitle(root.getContext().getString(
R.string.security_settings_fingerprint_title));
}
String keyToReturn = mIsExpressiveThemeStyle
? KEY_FINGERPRINT_ADD_EXPRESSIVE : KEY_FINGERPRINT_ADD;
@@ -815,6 +824,26 @@ public class FingerprintSettings extends SubSettings {
});
}
private void setupUseFingerprintToPreferences() {
final PreferenceCategory category =
findPreference(KEY_BIOMETRICS_USE_FINGERPRINT_TO_CATEGORY);
category.setVisible(true);
// Setup use fingerprint to unlock preference
final FingerprintSettingsKeyguardUnlockPreferenceController fpUnlockController =
use(FingerprintSettingsKeyguardUnlockPreferenceController.class);
fpUnlockController.setUserId(mUserId);
findPreference(fpUnlockController.getPreferenceKey())
.setOnPreferenceChangeListener(fpUnlockController);
// Setup use fingerprint to verify it's you in apps preference
final FingerprintSettingsAppsPreferenceController fingerprintAppController =
use(FingerprintSettingsAppsPreferenceController.class);
fingerprintAppController.setUserId(mUserId);
findPreference(fingerprintAppController.getPreferenceKey())
.setOnPreferenceChangeListener(fingerprintAppController);
}
private void updatePreferencesAfterFingerprintRemoved() {
updateAddPreference();
if (isSfps() || (screenOffUnlockUdfps() && isUltrasnoicUdfps())) {

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2025 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.fingerprint;
import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.android.settings.Utils;
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
public class FingerprintSettingsAppsPreferenceController
extends FingerprintSettingsPreferenceController {
private static final int ON = 1;
private static final int OFF = 0;
private static final int DEFAULT = ON;
private FingerprintManager mFingerprintManager;
public FingerprintSettingsAppsPreferenceController(
@NonNull Context context, @NonNull String key) {
super(context, key);
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
}
@Override
public boolean isChecked() {
return Settings.Secure.getIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED,
DEFAULT, getUserId()) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED,
isChecked ? ON : OFF, getUserId());
}
@Override
public int getAvailabilityStatus() {
final ActiveUnlockStatusUtils activeUnlockStatusUtils =
new ActiveUnlockStatusUtils(mContext);
if (!Utils.hasFingerprintHardware(mContext)
&& !activeUnlockStatusUtils.isAvailable()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mFingerprintManager == null) {
return AVAILABLE_UNSEARCHABLE;
}
// This preference will be available only if the user has registered fingerprint.
final boolean hasFingerprintEnrolledUser =
mFingerprintManager.hasEnrolledTemplates(getUserId());
if (hasFingerprintEnrolledUser) {
return AVAILABLE;
} else {
return AVAILABLE_UNSEARCHABLE;
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2025 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.fingerprint;
import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED;
import android.content.Context;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.android.settings.Utils;
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
public class FingerprintSettingsKeyguardUnlockPreferenceController
extends FingerprintSettingsPreferenceController {
private static final int ON = 1;
private static final int OFF = 0;
private static final int DEFAULT = ON;
public FingerprintSettingsKeyguardUnlockPreferenceController(
@NonNull Context context, @NonNull String key) {
super(context, key);
}
@Override
public boolean isChecked() {
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
FINGERPRINT_KEYGUARD_ENABLED, DEFAULT, getUserId()) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putIntForUser(mContext.getContentResolver(),
FINGERPRINT_KEYGUARD_ENABLED, isChecked ? ON : OFF, getUserId());
}
@Override
public int getAvailabilityStatus() {
final ActiveUnlockStatusUtils activeUnlockStatusUtils =
new ActiveUnlockStatusUtils(mContext);
if (activeUnlockStatusUtils.isAvailable()) {
return getAvailabilityFromRestrictingAdmin();
}
if (!Utils.hasFingerprintHardware(mContext)) {
return UNSUPPORTED_ON_DEVICE;
}
return getAvailabilityFromRestrictingAdmin();
}
private int getAvailabilityFromRestrictingAdmin() {
return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE;
}
}