1 /*
<lambda>null2 * 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. */
startnull45 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
watchnull62 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
watchnull69 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 registerContentObserverForUserSync(
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