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

Commit 251b3498 authored by Joe Bolinger's avatar Joe Bolinger Committed by Automerger Merge Worker
Browse files

Merge "Propogate face unlock always require confirmation setting to biometric...

Merge "Propogate face unlock always require confirmation setting to biometric prompt." into udc-d1-dev am: 27443a9c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23668394



Change-Id: Ia2263435e31c9a87ac204c9e9c6cd3c423ef9441
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 56c04ec1 27443a9c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -374,7 +374,6 @@ public class AuthContainerView extends LinearLayout
        if (Utils.isBiometricAllowed(config.mPromptInfo)) {
            mPromptSelectorInteractorProvider.get().useBiometricsForAuthentication(
                    config.mPromptInfo,
                    config.mRequireConfirmation,
                    config.mUserId,
                    config.mOperationId,
                    new BiometricModalities(fpProps, faceProps));
+3 −0
Original line number Diff line number Diff line
@@ -1216,8 +1216,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,

        final PromptInfo promptInfo = (PromptInfo) args.arg1;
        final int[] sensorIds = (int[]) args.arg3;

        // TODO(b/251476085): remove these unused parameters (replaced with SSOT elsewhere)
        final boolean credentialAllowed = (boolean) args.arg4;
        final boolean requireConfirmation = (boolean) args.arg5;

        final int userId = args.argi1;
        final String opPackageName = (String) args.arg6;
        final long operationId = args.argl1;
+6 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.systemui.biometrics.dagger

import com.android.settingslib.udfps.UdfpsUtils
import com.android.systemui.biometrics.data.repository.FaceSettingsRepository
import com.android.systemui.biometrics.data.repository.FaceSettingsRepositoryImpl
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepositoryImpl
import com.android.systemui.biometrics.data.repository.PromptRepository
@@ -45,6 +47,10 @@ import javax.inject.Qualifier
@Module
interface BiometricsModule {

    @Binds
    @SysUISingleton
    fun faceSettings(impl: FaceSettingsRepositoryImpl): FaceSettingsRepository

    @Binds
    @SysUISingleton
    fun biometricPromptRepository(impl: PromptRepositoryImpl): PromptRepository
+57 −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.systemui.biometrics.data.repository

import android.os.Handler
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.util.settings.SecureSettings
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject

/**
 * Repository for the global state of users Face Unlock preferences.
 *
 * Largely a wrapper around [SecureSettings]'s proxy to Settings.Secure.
 */
interface FaceSettingsRepository {

    /** Get Settings for the given user [id]. */
    fun forUser(id: Int?): FaceUserSettingsRepository
}

@SysUISingleton
class FaceSettingsRepositoryImpl
@Inject
constructor(
    @Main private val mainHandler: Handler,
    private val secureSettings: SecureSettings,
) : FaceSettingsRepository {

    private val userSettings = ConcurrentHashMap<Int, FaceUserSettingsRepository>()

    override fun forUser(id: Int?): FaceUserSettingsRepository =
        if (id != null) {
            userSettings.computeIfAbsent(id) { _ ->
                FaceUserSettingsRepositoryImpl(id, mainHandler, secureSettings).also { repo ->
                    repo.start()
                }
            }
        } else {
            FaceUserSettingsRepositoryImpl.Empty
        }
}
+88 −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.systemui.biometrics.data.repository

import android.database.ContentObserver
import android.os.Handler
import android.provider.Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.util.settings.SecureSettings
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOf

/** Settings for a user. */
interface FaceUserSettingsRepository {
    /** The user's id. */
    val userId: Int

    /** If BiometricPrompt should always require confirmation (overrides app's preference). */
    val alwaysRequireConfirmationInApps: Flow<Boolean>
}

class FaceUserSettingsRepositoryImpl(
    override val userId: Int,
    @Main private val mainHandler: Handler,
    private val secureSettings: SecureSettings,
) : FaceUserSettingsRepository {

    /** Indefinitely subscribe to user preference changes. */
    fun start() {
        watch(
            FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
            _alwaysRequireConfirmationInApps,
        )
    }

    private var _alwaysRequireConfirmationInApps = MutableStateFlow(false)
    override val alwaysRequireConfirmationInApps: Flow<Boolean> =
        _alwaysRequireConfirmationInApps.asStateFlow()

    /** Defaults to use when no user is specified. */
    object Empty : FaceUserSettingsRepository {
        override val userId = -1
        override val alwaysRequireConfirmationInApps = flowOf(false)
    }

    private fun watch(
        key: String,
        toUpdate: MutableStateFlow<Boolean>,
        defaultValue: Boolean = false,
    ) = secureSettings.watch(userId, mainHandler, key, defaultValue) { v -> toUpdate.value = v }
}

private fun SecureSettings.watch(
    userId: Int,
    handler: Handler,
    key: String,
    defaultValue: Boolean = false,
    onChange: (Boolean) -> Unit,
) {
    fun fetch(): Boolean = getIntForUser(key, if (defaultValue) 1 else 0, userId) > 0

    registerContentObserverForUser(
        key,
        false /* notifyForDescendants */,
        object : ContentObserver(handler) {
            override fun onChange(selfChange: Boolean) = onChange(fetch())
        },
        userId
    )

    onChange(fetch())
}
Loading