1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.biometrics.data.repository 18 19 import android.database.ContentObserver 20 import android.os.Handler 21 import android.provider.Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION 22 import com.android.systemui.dagger.qualifiers.Main 23 import com.android.systemui.util.settings.SecureSettings 24 import kotlinx.coroutines.flow.Flow 25 import kotlinx.coroutines.flow.MutableStateFlow 26 import kotlinx.coroutines.flow.asStateFlow 27 import kotlinx.coroutines.flow.flowOf 28 29 /** Settings for a user. */ 30 interface FaceUserSettingsRepository { 31 /** The user's id. */ 32 val userId: Int 33 34 /** If BiometricPrompt should always require confirmation (overrides app's preference). */ 35 val alwaysRequireConfirmationInApps: Flow<Boolean> 36 } 37 38 class FaceUserSettingsRepositoryImpl( 39 override val userId: Int, 40 @Main private val mainHandler: Handler, 41 private val secureSettings: SecureSettings, 42 ) : FaceUserSettingsRepository { 43 44 /** Indefinitely subscribe to user preference changes. */ 45 fun start() { 46 watch( 47 FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 48 _alwaysRequireConfirmationInApps, 49 ) 50 } 51 52 private var _alwaysRequireConfirmationInApps = MutableStateFlow(false) 53 override val alwaysRequireConfirmationInApps: Flow<Boolean> = 54 _alwaysRequireConfirmationInApps.asStateFlow() 55 56 /** Defaults to use when no user is specified. */ 57 object Empty : FaceUserSettingsRepository { 58 override val userId = -1 59 override val alwaysRequireConfirmationInApps = flowOf(false) 60 } 61 62 private fun watch( 63 key: String, 64 toUpdate: MutableStateFlow<Boolean>, 65 defaultValue: Boolean = false, 66 ) = secureSettings.watch(userId, mainHandler, key, defaultValue) { v -> toUpdate.value = v } 67 } 68 69 private fun SecureSettings.watch( 70 userId: Int, 71 handler: Handler, 72 key: String, 73 defaultValue: Boolean = false, 74 onChange: (Boolean) -> Unit, 75 ) { 76 fun fetch(): Boolean = getIntForUser(key, if (defaultValue) 1 else 0, userId) > 0 77 78 registerContentObserverForUser( 79 key, 80 false /* notifyForDescendants */, 81 object : ContentObserver(handler) { 82 override fun onChange(selfChange: Boolean) = onChange(fetch()) 83 }, 84 userId 85 ) 86 87 onChange(fetch()) 88 } 89