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