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

Commit cdab1e24 authored by Diya Bera's avatar Diya Bera Committed by Automerger Merge Worker
Browse files

Make face auth ineligible when camera access is disabled am: 7770222f

parents 29384f92 7770222f
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.server.biometrics;

/**
 * Interface for biometric operations to get camera privacy state.
 */
public interface BiometricSensorPrivacy {
    /* Returns true if privacy is enabled and camera access is disabled. */
    boolean isCameraPrivacyEnabled();
}
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.server.biometrics;

import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;

import android.annotation.Nullable;
import android.hardware.SensorPrivacyManager;

public class BiometricSensorPrivacyImpl implements
        BiometricSensorPrivacy {
    private final SensorPrivacyManager mSensorPrivacyManager;

    public BiometricSensorPrivacyImpl(@Nullable SensorPrivacyManager sensorPrivacyManager) {
        mSensorPrivacyManager = sensorPrivacyManager;
    }

    @Override
    public boolean isCameraPrivacyEnabled() {
        return mSensorPrivacyManager != null && mSensorPrivacyManager
                .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, CAMERA);
    }
}
+12 −5
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
@@ -124,6 +125,8 @@ public class BiometricService extends SystemService {
    AuthSession mAuthSession;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    private final BiometricSensorPrivacy mBiometricSensorPrivacy;

    /**
     * Tracks authenticatorId invalidation. For more details, see
     * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}.
@@ -933,7 +936,7 @@ public class BiometricService extends SystemService {

        return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors,
                userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */,
                getContext());
                getContext(), mBiometricSensorPrivacy);
    }

    /**
@@ -1026,6 +1029,11 @@ public class BiometricService extends SystemService {
        public UserManager getUserManager(Context context) {
            return context.getSystemService(UserManager.class);
        }

        public BiometricSensorPrivacy getBiometricSensorPrivacy(Context context) {
            return new BiometricSensorPrivacyImpl(context.getSystemService(
                    SensorPrivacyManager.class));
        }
    }

    /**
@@ -1054,6 +1062,7 @@ public class BiometricService extends SystemService {
        mRequestCounter = mInjector.getRequestGenerator();
        mBiometricContext = injector.getBiometricContext(context);
        mUserManager = injector.getUserManager(context);
        mBiometricSensorPrivacy = injector.getBiometricSensorPrivacy(context);

        try {
            injector.getActivityManagerService().registerUserSwitchObserver(
@@ -1290,7 +1299,7 @@ public class BiometricService extends SystemService {
                final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager,
                        mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo,
                        opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(),
                        getContext());
                        getContext(), mBiometricSensorPrivacy);

                final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus();

@@ -1300,9 +1309,7 @@ public class BiometricService extends SystemService {
                        + promptInfo.isIgnoreEnrollmentState());
                // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can
                // be shown for this case.
                if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS
                        || preAuthStatus.second
                        == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) {
                if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) {
                    // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but
                    // CREDENTIAL is requested and available, set the bundle to only request
                    // CREDENTIAL.
+17 −20
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.PromptInfo;
@@ -73,13 +72,16 @@ class PreAuthInfo {
    final Context context;
    private final boolean mBiometricRequested;
    private final int mBiometricStrengthRequested;
    private final BiometricSensorPrivacy mBiometricSensorPrivacy;

    private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested,
            boolean credentialRequested, List<BiometricSensor> eligibleSensors,
            List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable,
            boolean confirmationRequested, boolean ignoreEnrollmentState, int userId,
            Context context) {
            Context context, BiometricSensorPrivacy biometricSensorPrivacy) {
        mBiometricRequested = biometricRequested;
        mBiometricStrengthRequested = biometricStrengthRequested;
        mBiometricSensorPrivacy = biometricSensorPrivacy;
        this.credentialRequested = credentialRequested;

        this.eligibleSensors = eligibleSensors;
@@ -96,7 +98,8 @@ class PreAuthInfo {
            BiometricService.SettingObserver settingObserver,
            List<BiometricSensor> sensors,
            int userId, PromptInfo promptInfo, String opPackageName,
            boolean checkDevicePolicyManager, Context context)
            boolean checkDevicePolicyManager, Context context,
            BiometricSensorPrivacy biometricSensorPrivacy)
            throws RemoteException {

        final boolean confirmationRequested = promptInfo.isConfirmationRequested();
@@ -124,7 +127,7 @@ class PreAuthInfo {
                        checkDevicePolicyManager, requestedStrength,
                        promptInfo.getAllowedSensorIds(),
                        promptInfo.isIgnoreEnrollmentState(),
                        context);
                        biometricSensorPrivacy);

                Slog.d(TAG, "Package: " + opPackageName
                        + " Sensor ID: " + sensor.id
@@ -138,7 +141,7 @@ class PreAuthInfo {
                //
                // Note: if only a certain sensor is required and the privacy is enabled,
                // canAuthenticate() will return false.
                if (status == AUTHENTICATOR_OK || status == BIOMETRIC_SENSOR_PRIVACY_ENABLED) {
                if (status == AUTHENTICATOR_OK) {
                    eligibleSensors.add(sensor);
                } else {
                    ineligibleSensors.add(new Pair<>(sensor, status));
@@ -148,7 +151,7 @@ class PreAuthInfo {

        return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested,
                eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested,
                promptInfo.isIgnoreEnrollmentState(), userId, context);
                promptInfo.isIgnoreEnrollmentState(), userId, context, biometricSensorPrivacy);
    }

    /**
@@ -165,7 +168,7 @@ class PreAuthInfo {
            BiometricSensor sensor, int userId, String opPackageName,
            boolean checkDevicePolicyManager, int requestedStrength,
            @NonNull List<Integer> requestedSensorIds,
            boolean ignoreEnrollmentState, Context context) {
            boolean ignoreEnrollmentState, BiometricSensorPrivacy biometricSensorPrivacy) {

        if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) {
            return BIOMETRIC_NO_HARDWARE;
@@ -191,12 +194,10 @@ class PreAuthInfo {
                    && !ignoreEnrollmentState) {
                return BIOMETRIC_NOT_ENROLLED;
            }
            final SensorPrivacyManager sensorPrivacyManager = context
                    .getSystemService(SensorPrivacyManager.class);

            if (sensorPrivacyManager != null && sensor.modality == TYPE_FACE) {
                if (sensorPrivacyManager
                        .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId)) {
            if (biometricSensorPrivacy != null && sensor.modality == TYPE_FACE) {
                if (biometricSensorPrivacy.isCameraPrivacyEnabled()) {
                    //Camera privacy is enabled as the access is disabled
                    return BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                }
            }
@@ -292,13 +293,9 @@ class PreAuthInfo {
        @AuthenticatorStatus final int status;
        @BiometricAuthenticator.Modality int modality = TYPE_NONE;

        final SensorPrivacyManager sensorPrivacyManager = context
                .getSystemService(SensorPrivacyManager.class);

        boolean cameraPrivacyEnabled = false;
        if (sensorPrivacyManager != null) {
            cameraPrivacyEnabled = sensorPrivacyManager
                    .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId);
        if (mBiometricSensorPrivacy != null) {
            cameraPrivacyEnabled = mBiometricSensorPrivacy.isCameraPrivacyEnabled();
        }

        if (mBiometricRequested && credentialRequested) {
@@ -315,7 +312,7 @@ class PreAuthInfo {
                    // and the face sensor privacy is enabled then return
                    // BIOMETRIC_SENSOR_PRIVACY_ENABLED.
                    //
                    // Note: This sensor will still be eligible for calls to authenticate.
                    // Note: This sensor will not be eligible for calls to authenticate.
                    status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                } else {
                    status = AUTHENTICATOR_OK;
@@ -340,7 +337,7 @@ class PreAuthInfo {
                    // If the only modality requested is face and the privacy is enabled
                    // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED.
                    //
                    // Note: This sensor will still be eligible for calls to authenticate.
                    // Note: This sensor will not be eligible for calls to authenticate.
                    status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                } else {
                    status = AUTHENTICATOR_OK;
+3 −1
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ public class AuthSessionTest {
    @Mock private KeyStore mKeyStore;
    @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
    @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
    @Mock BiometricSensorPrivacy mBiometricSensorPrivacy;

    private Random mRandom;
    private IBinder mToken;
@@ -571,7 +572,8 @@ public class AuthSessionTest {
                promptInfo,
                TEST_PACKAGE,
                checkDevicePolicyManager,
                mContext);
                mContext,
                mBiometricSensorPrivacy);
    }

    private AuthSession createAuthSession(List<BiometricSensor> sensors,
Loading