Merge "Implement SFPS “require screen on to auth”" into tm-qpr-dev am: db266ca6b2
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/20215190 Change-Id: I7f485c93b429fc2d2f75b1fc3e46d82a47e31c25 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -25,6 +25,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
@@ -44,16 +45,24 @@ import java.util.List;
|
||||
public class FingerprintEnrollFinish extends BiometricEnrollBase {
|
||||
|
||||
private static final String TAG = "FingerprintEnrollFinish";
|
||||
private static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH = "require_screen_on_to_auth_toggle";
|
||||
private static final String ACTION_FINGERPRINT_SETTINGS =
|
||||
"android.settings.FINGERPRINT_SETTINGS";
|
||||
@VisibleForTesting
|
||||
static final String FINGERPRINT_SUGGESTION_ACTIVITY =
|
||||
"com.android.settings.SetupFingerprintSuggestionActivity";
|
||||
|
||||
private FingerprintManager mFingerprintManager;
|
||||
|
||||
private FingerprintSettingsRequireScreenOnToAuthPreferenceController
|
||||
mRequireScreenOnToAuthPreferenceController;
|
||||
private FingerprintRequireScreenOnToAuthToggle mRequireScreenOnToAuthToggle;
|
||||
private boolean mCanAssumeSfps;
|
||||
|
||||
private boolean mIsAddAnotherOrFinish;
|
||||
|
||||
private CompoundButton.OnCheckedChangeListener mRequireScreenOnToAuthToggleListener;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -63,6 +72,11 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
|
||||
mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
|
||||
if (mCanAssumeSfps) {
|
||||
setContentView(R.layout.sfps_enroll_finish);
|
||||
mRequireScreenOnToAuthPreferenceController =
|
||||
new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
|
||||
getApplicationContext(),
|
||||
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
||||
);
|
||||
} else {
|
||||
setContentView(R.layout.fingerprint_enroll_finish);
|
||||
}
|
||||
@@ -90,6 +104,20 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
|
||||
.setTheme(R.style.SudGlifButton_Primary)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (mCanAssumeSfps) {
|
||||
mRequireScreenOnToAuthToggleListener =
|
||||
(buttonView, isChecked) -> {
|
||||
mRequireScreenOnToAuthPreferenceController.setChecked(isChecked);
|
||||
};
|
||||
mRequireScreenOnToAuthToggle = findViewById(R.id.require_screen_on_to_auth_toggle);
|
||||
mRequireScreenOnToAuthToggle.setChecked(
|
||||
mRequireScreenOnToAuthPreferenceController.isChecked());
|
||||
mRequireScreenOnToAuthToggle.setListener(mRequireScreenOnToAuthToggleListener);
|
||||
mRequireScreenOnToAuthToggle.setOnClickListener(v -> {
|
||||
mRequireScreenOnToAuthToggle.getSwitch().toggle();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,6 +131,12 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (mCanAssumeSfps) {
|
||||
mRequireScreenOnToAuthToggleListener.onCheckedChanged(
|
||||
mRequireScreenOnToAuthToggle.getSwitch(),
|
||||
mRequireScreenOnToAuthToggle.isChecked()
|
||||
);
|
||||
}
|
||||
|
||||
FooterButton addButton = mFooterBarMixin.getSecondaryButton();
|
||||
|
||||
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* A layout that contains a start-justified title, and an end-justified switch.
|
||||
*/
|
||||
public class FingerprintRequireScreenOnToAuthToggle extends LinearLayout {
|
||||
private Switch mSwitch;
|
||||
|
||||
public FingerprintRequireScreenOnToAuthToggle(Context context) {
|
||||
this(context, null /* attrs */);
|
||||
}
|
||||
|
||||
public FingerprintRequireScreenOnToAuthToggle(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FingerprintRequireScreenOnToAuthToggle(
|
||||
Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.sfps_require_screen_on_to_auth_toggle,
|
||||
this, true /* attachToRoot */);
|
||||
|
||||
mSwitch = findViewById(R.id.toggle);
|
||||
mSwitch.setClickable(true);
|
||||
mSwitch.setFocusable(false);
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return mSwitch.isChecked();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param checked
|
||||
*/
|
||||
public void setChecked(boolean checked) {
|
||||
mSwitch.setChecked(checked);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void setListener(CompoundButton.OnCheckedChangeListener listener) {
|
||||
mSwitch.setOnCheckedChangeListener(listener);
|
||||
}
|
||||
|
||||
public Switch getSwitch() {
|
||||
return mSwitch;
|
||||
}
|
||||
}
|
@@ -56,21 +56,24 @@ import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
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.dashboard.DashboardFragment;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
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.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.transition.SettingsTransitionHelper;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.widget.TwoTargetPreference;
|
||||
@@ -115,7 +118,26 @@ public class FingerprintSettings extends SubSettings {
|
||||
setTitle(msg);
|
||||
}
|
||||
|
||||
public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
|
||||
/**
|
||||
* @param context
|
||||
* @return true if the Fingerprint hardware is detected.
|
||||
*/
|
||||
public static boolean isFingerprintHardwareDetected(Context context) {
|
||||
FingerprintManager manager = Utils.getFingerprintManagerOrNull(context);
|
||||
boolean isHardwareDetected = false;
|
||||
if (manager == null) {
|
||||
Log.d(TAG, "FingerprintManager is null");
|
||||
} else {
|
||||
isHardwareDetected = manager.isHardwareDetected();
|
||||
Log.d(TAG, "FingerprintManager is not null. Hardware detected: " + isHardwareDetected);
|
||||
}
|
||||
return manager != null && isHardwareDetected;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static class FingerprintSettingsFragment extends DashboardFragment
|
||||
implements OnPreferenceChangeListener, FingerprintPreference.OnDeleteClickListener {
|
||||
|
||||
private static class FooterColumn {
|
||||
@@ -134,6 +156,8 @@ public class FingerprintSettings extends SubSettings {
|
||||
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 String KEY_REQUIRE_SCREEN_ON_TO_AUTH =
|
||||
"security_settings_require_screen_on_to_auth";
|
||||
|
||||
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
|
||||
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
|
||||
@@ -149,6 +173,11 @@ public class FingerprintSettings extends SubSettings {
|
||||
|
||||
protected static final boolean DEBUG = false;
|
||||
|
||||
private List<AbstractPreferenceController> mControllers;
|
||||
private FingerprintSettingsRequireScreenOnToAuthPreferenceController
|
||||
mRequireScreenOnToAuthPreferenceController;
|
||||
private RestrictedSwitchPreference mRequireScreenOnToAuthPreference;
|
||||
|
||||
private FingerprintManager mFingerprintManager;
|
||||
private FingerprintUpdater mFingerprintUpdater;
|
||||
private List<FingerprintSensorPropertiesInternal> mSensorProperties;
|
||||
@@ -214,6 +243,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
}
|
||||
|
||||
private void updateDialog() {
|
||||
setRequireScreenOnToAuthVisibility();
|
||||
RenameDialog renameDialog = (RenameDialog) getFragmentManager().
|
||||
findFragmentByTag(RenameDialog.class.getName());
|
||||
if (renameDialog != null) {
|
||||
@@ -448,13 +478,36 @@ public class FingerprintSettings extends SubSettings {
|
||||
if (root != null) {
|
||||
root.removeAll();
|
||||
}
|
||||
addPreferencesFromResource(R.xml.security_settings_fingerprint);
|
||||
root = getPreferenceScreen();
|
||||
addFingerprintItemPreferences(root);
|
||||
addPreferencesFromResource(getPreferenceScreenResId());
|
||||
mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
|
||||
for (AbstractPreferenceController controller : mControllers) {
|
||||
((FingerprintSettingsPreferenceController) controller).setUserId(mUserId);
|
||||
}
|
||||
mRequireScreenOnToAuthPreference.setChecked(
|
||||
mRequireScreenOnToAuthPreferenceController.isChecked());
|
||||
mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
boolean isChecked = ((SwitchPreference) preference).isChecked();
|
||||
mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
|
||||
return true;
|
||||
});
|
||||
setPreferenceScreen(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
private void setRequireScreenOnToAuthVisibility() {
|
||||
int fingerprintsEnrolled = mFingerprintManager.getEnrolledFingerprints(mUserId).size();
|
||||
final boolean removalInProgress = mRemovalSidecar.inProgress();
|
||||
// Removing last remaining fingerprint
|
||||
if (fingerprintsEnrolled == 0 && removalInProgress) {
|
||||
mRequireScreenOnToAuthPreference.setVisible(false);
|
||||
} else {
|
||||
mRequireScreenOnToAuthPreference.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFingerprintItemPreferences(PreferenceGroup root) {
|
||||
root.removeAll();
|
||||
final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(mUserId);
|
||||
@@ -477,6 +530,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
root.addPreference(pref);
|
||||
pref.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
Preference addPreference = new Preference(root.getContext());
|
||||
addPreference.setKey(KEY_FINGERPRINT_ADD);
|
||||
addPreference.setTitle(R.string.fingerprint_add_title);
|
||||
@@ -568,6 +622,16 @@ public class FingerprintSettings extends SubSettings {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.security_settings_fingerprint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
@@ -662,6 +726,27 @@ public class FingerprintSettings extends SubSettings {
|
||||
return R.string.help_url_fingerprint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
if (!isFingerprintHardwareDetected(context)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
mControllers = buildPreferenceControllers(context);
|
||||
return mControllers;
|
||||
}
|
||||
|
||||
private List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mRequireScreenOnToAuthPreferenceController =
|
||||
new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
|
||||
context,
|
||||
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
||||
);
|
||||
controllers.add(mRequireScreenOnToAuthPreferenceController);
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
|
||||
/**
|
||||
* Abstract base class for all fingerprint settings toggles.
|
||||
*/
|
||||
public abstract class FingerprintSettingsPreferenceController extends TogglePreferenceController {
|
||||
|
||||
private int mUserId;
|
||||
|
||||
public FingerprintSettingsPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
protected int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
protected EnforcedAdmin getRestrictingAdmin() {
|
||||
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
|
||||
mContext, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isSliceable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSliceHighlightMenuRes() {
|
||||
// not needed since it's not sliceable
|
||||
return NO_RES;
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.content.Context;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
/**
|
||||
* Preference controller that controls whether a SFPS device is required to be interactive for
|
||||
* fingerprint authentication to unlock the device.
|
||||
*/
|
||||
public class FingerprintSettingsRequireScreenOnToAuthPreferenceController
|
||||
extends FingerprintSettingsPreferenceController {
|
||||
private static final String TAG =
|
||||
"FingerprintSettingsRequireScreenOnToAuthPreferenceController";
|
||||
|
||||
@VisibleForTesting
|
||||
protected FingerprintManager mFingerprintManager;
|
||||
|
||||
public FingerprintSettingsRequireScreenOnToAuthPreferenceController(
|
||||
Context context, String prefKey) {
|
||||
super(context, prefKey);
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
|
||||
return false;
|
||||
} else if (getRestrictingAdmin() != null) {
|
||||
return false;
|
||||
}
|
||||
int defaultValue = mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_requireScreenOnToAuthEnabled) ? 1 : 0;
|
||||
|
||||
return Settings.Secure.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
|
||||
defaultValue,
|
||||
getUserHandle()) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
Settings.Secure.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
|
||||
isChecked ? 1 : 0,
|
||||
getUserHandle());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
|
||||
preference.setEnabled(false);
|
||||
} else if (!mFingerprintManager.hasEnrolledTemplates(getUserId())) {
|
||||
preference.setEnabled(false);
|
||||
} else {
|
||||
preference.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (mFingerprintManager != null
|
||||
&& mFingerprintManager.isHardwareDetected()
|
||||
&& mFingerprintManager.isPowerbuttonFps()) {
|
||||
return mFingerprintManager.hasEnrolledTemplates(getUserId())
|
||||
? AVAILABLE : DISABLED_DEPENDENT_SETTING;
|
||||
} else {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
private int getUserHandle() {
|
||||
return UserHandle.of(getUserId()).getIdentifier();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user