Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24b81dcf authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge "Convert biometrics to RestrictedPreference" into sc-dev

parents 19baf0df 9af27677
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -43,19 +43,19 @@
            android:summary="@string/summary_placeholder"
            settings:keywords="@string/keywords_lockscreen" />

        <Preference
        <com.android.settingslib.RestrictedPreference
            android:key="fingerprint_settings"
            android:title="@string/security_settings_fingerprint_preference_title"
            android:summary="@string/summary_placeholder"
            settings:keywords="@string/keywords_fingerprint_settings" />

        <Preference
        <com.android.settingslib.RestrictedPreference
            android:key="face_settings"
            android:title="@string/security_settings_face_preference_title"
            android:summary="@string/summary_placeholder"
            settings:keywords="@string/keywords_face_settings" />

        <Preference
        <com.android.settingslib.RestrictedPreference
            android:key="biometric_settings"
            android:title="@string/security_settings_biometric_preference_title"
            android:summary="@string/summary_placeholder"
+108 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.RestrictedLockUtils;

/**
 * Utilities for things at the cross-section of biometrics and parental controls. For example,
 * determining if parental consent is required, determining which strings should be shown, etc.
 */
public class ParentalControlsUtils {

    private static final String TAG = "ParentalControlsUtils";
    private static final String TEST_ALWAYS_REQUIRE_CONSENT =
            "com.android.settings.biometrics.ParentalControlsUtils.always_require_consent";

    /**
     * Public version that enables test paths based on {@link #TEST_ALWAYS_REQUIRE_CONSENT}
     * @return non-null EnforcedAdmin if parental consent is required
     */
    public static RestrictedLockUtils.EnforcedAdmin parentConsentRequired(@NonNull Context context,
            @BiometricAuthenticator.Modality int modality) {

        final UserHandle userHandle = new UserHandle(UserHandle.myUserId());
        if (Build.IS_USERDEBUG || Build.IS_ENG) {
            final boolean testAlwaysRequireConsent = Settings.Secure.getInt(
                    context.getContentResolver(), TEST_ALWAYS_REQUIRE_CONSENT, 0) != 0;
            if (testAlwaysRequireConsent) {
                Log.d(TAG, "Requiring consent for test flow");
                return new RestrictedLockUtils.EnforcedAdmin(null /* ComponentName */, userHandle);
            }
        }

        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
        return parentConsentRequiredInternal(dpm, modality, userHandle);
    }

    /**
     * Internal testable version.
     * @return non-null EnforcedAdmin if parental consent is required
     */
    @Nullable
    @VisibleForTesting
    static RestrictedLockUtils.EnforcedAdmin parentConsentRequiredInternal(
            @NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality,
            @NonNull UserHandle userHandle) {
        final ComponentName cn = dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle);
        if (cn == null) {
            return null;
        }

        final int keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(cn);
        final boolean dpmFpDisabled = containsFlag(keyguardDisabledFeatures,
                DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
        final boolean dpmFaceDisabled = containsFlag(keyguardDisabledFeatures,
                DevicePolicyManager.KEYGUARD_DISABLE_FACE);
        final boolean dpmIrisDisabled = containsFlag(keyguardDisabledFeatures,
                DevicePolicyManager.KEYGUARD_DISABLE_IRIS);

        final boolean consentRequired;
        if (containsFlag(modality, BiometricAuthenticator.TYPE_FINGERPRINT) && dpmFpDisabled) {
            consentRequired = true;
        } else if (containsFlag(modality, BiometricAuthenticator.TYPE_FACE) && dpmFaceDisabled) {
            consentRequired = true;
        } else if (containsFlag(modality, BiometricAuthenticator.TYPE_IRIS) && dpmIrisDisabled) {
            consentRequired = true;
        } else {
            consentRequired = false;
        }

        if (consentRequired) {
            return new RestrictedLockUtils.EnforcedAdmin(cn, userHandle);
        } else {
            return null;
        }
    }

    private static boolean containsFlag(int haystack, int needle) {
        return (haystack & needle) != 0;
    }
}
+33 −0
Original line number Diff line number Diff line
@@ -16,15 +16,22 @@
package com.android.settings.biometrics.combination;

import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;

import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;

/**
 * Preference controller for biometrics settings page controlling the ability to unlock the phone
@@ -38,6 +45,8 @@ public class CombinedBiometricStatusPreferenceController extends
    FingerprintManager mFingerprintManager;
    @Nullable
    FaceManager mFaceManager;
    @VisibleForTesting
    RestrictedPreference mPreference;

    public CombinedBiometricStatusPreferenceController(Context context) {
        this(context, KEY_BIOMETRIC_SETTINGS);
@@ -49,6 +58,12 @@ public class CombinedBiometricStatusPreferenceController extends
        mFaceManager = Utils.getFaceManagerOrNull(context);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(KEY_BIOMETRIC_SETTINGS);
    }

    @Override
    protected boolean isDeviceSupported() {
        return Utils.hasFingerprintHardware(mContext) && Utils.hasFaceHardware(mContext);
@@ -59,6 +74,24 @@ public class CombinedBiometricStatusPreferenceController extends
        return false;
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        // This controller currently is shown if fingerprint&face exist on the device. If this
        // changes in the future, the modalities passed into the below will need to be updated.
        final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
                .parentConsentRequired(mContext,
                BiometricAuthenticator.TYPE_FACE | BiometricAuthenticator.TYPE_FINGERPRINT);
        updateStateInternal(admin);
    }

    @VisibleForTesting
    void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
        if (enforcedAdmin != null && mPreference != null) {
            mPreference.setDisabledByAdmin(enforcedAdmin);
        }
    }

    @Override
    protected String getSummaryTextEnrolled() {
        // Note that this is currently never called (see the super class)
+32 −0
Original line number Diff line number Diff line
@@ -17,18 +17,29 @@
package com.android.settings.biometrics.face;

import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;

import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;

public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {

    public static final String KEY_FACE_SETTINGS = "face_settings";

    protected final FaceManager mFaceManager;
    @VisibleForTesting
    RestrictedPreference mPreference;

    public FaceStatusPreferenceController(Context context) {
        this(context, KEY_FACE_SETTINGS);
@@ -39,6 +50,12 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon
        mFaceManager = Utils.getFaceManagerOrNull(context);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(KEY_FACE_SETTINGS);
    }

    @Override
    protected boolean isDeviceSupported() {
        return !Utils.isMultipleBiometricsSupported(mContext) && Utils.hasFaceHardware(mContext);
@@ -49,6 +66,21 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon
        return mFaceManager.hasEnrolledTemplates(getUserId());
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
                .parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FACE);
        updateStateInternal(admin);
    }

    @VisibleForTesting
    void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
        if (enforcedAdmin != null && mPreference != null) {
            mPreference.setDisabledByAdmin(enforcedAdmin);
        }
    }

    @Override
    protected String getSummaryTextEnrolled() {
        return mContext.getResources()
+32 −0
Original line number Diff line number Diff line
@@ -17,17 +17,28 @@
package com.android.settings.biometrics.fingerprint;

import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.fingerprint.FingerprintManager;

import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.ParentalControlsUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;

public class FingerprintStatusPreferenceController extends BiometricStatusPreferenceController {

    private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";

    protected final FingerprintManager mFingerprintManager;
    @VisibleForTesting
    RestrictedPreference mPreference;

    public FingerprintStatusPreferenceController(Context context) {
        this(context, KEY_FINGERPRINT_SETTINGS);
@@ -38,6 +49,12 @@ public class FingerprintStatusPreferenceController extends BiometricStatusPrefer
        mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(KEY_FINGERPRINT_SETTINGS);
    }

    @Override
    protected boolean isDeviceSupported() {
        return !Utils.isMultipleBiometricsSupported(mContext)
@@ -49,6 +66,21 @@ public class FingerprintStatusPreferenceController extends BiometricStatusPrefer
        return mFingerprintManager.hasEnrolledFingerprints(getUserId());
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        final RestrictedLockUtils.EnforcedAdmin admin = ParentalControlsUtils
                .parentConsentRequired(mContext, BiometricAuthenticator.TYPE_FINGERPRINT);
        updateStateInternal(admin);
    }

    @VisibleForTesting
    void updateStateInternal(@Nullable RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
        if (enforcedAdmin != null && mPreference != null) {
            mPreference.setDisabledByAdmin(enforcedAdmin);
        }
    }

    @Override
    protected String getSummaryTextEnrolled() {
        final int numEnrolled = mFingerprintManager.getEnrolledFingerprints(getUserId()).size();
Loading