SystemUI: Add FingerprintInteractiveToAuthProvider implementation

This is required for the "touch to unlock anytime" setting on devices
with side mounted fingerprint sensor.

Ref: 66a048d646fd816e7757e300c62fa5cebf04761d

Co-authored-by: Anay Wadhera <anay1018@gmail.com>
Co-authored-by: Michael Bestas <mkbestas@lineageos.org>
Change-Id: If3308860a428d9966f2b0a0024764df95f8f9a8b
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProviderImpl.kt
new file mode 100644
index 0000000..cc0109d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintInteractiveToAuthProviderImpl.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 ArrowOS
+ *
+ * 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
+
+import android.content.Context
+import android.database.ContentObserver
+import android.hardware.biometrics.common.AuthenticateReason
+import android.provider.Settings
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import com.android.systemui.util.settings.SecureSettings
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import com.android.internal.R.bool.config_performantAuthDefault
+
+class FingerprintInteractiveToAuthProviderImpl @Inject constructor(
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val context: Context,
+    private val secureSettings: SecureSettings,
+    private val selectedUserInteractor: SelectedUserInteractor,
+) : FingerprintInteractiveToAuthProvider {
+    private val defaultValue = if (context.resources.getBoolean(config_performantAuthDefault)) {
+        1
+    } else {
+        0
+    }
+
+    override val enabledForCurrentUser =
+        selectedUserInteractor.selectedUser.flatMapLatest { currentUserId ->
+            conflatedCallbackFlow {
+                val callback = object : ContentObserver(null) {
+                    override fun onChange(selfChange: Boolean) {
+                        trySend(isEnabled(currentUserId))
+                    }
+                }
+                secureSettings.registerContentObserver(
+                    Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED, true, callback
+                )
+                trySend(isEnabled(currentUserId))
+                awaitClose { secureSettings.unregisterContentObserver(callback) }
+            }
+        }
+        .flowOn(backgroundDispatcher)
+
+    override fun getVendorExtension(userId: Int): AuthenticateReason.Vendor? = null
+
+    private fun isEnabled(userId: Int): Boolean {
+        var value = Settings.Secure.getIntForUser(
+            context.contentResolver,
+            Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
+            -1,
+            userId,
+        )
+        if (value == -1) {
+            value = defaultValue
+            Settings.Secure.putIntForUser(
+                context.contentResolver,
+                Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
+                value,
+                userId,
+            )
+        }
+        return value == 0
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
index 8ae6f87..bb95396 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -16,10 +16,14 @@
 
 package com.android.systemui.biometrics.dagger
 
+import android.content.Context
+
 import android.content.res.Resources
 import com.android.internal.R
 import com.android.systemui.CoreStartable
 import com.android.systemui.biometrics.EllipseOverlapDetectorParams
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProviderImpl
 import com.android.systemui.biometrics.UdfpsUtils
 import com.android.systemui.biometrics.data.repository.BiometricStatusRepository
 import com.android.systemui.biometrics.data.repository.BiometricStatusRepositoryImpl
@@ -38,7 +42,10 @@
 import com.android.systemui.biometrics.udfps.OverlapDetector
 import com.android.systemui.biometrics.ui.binder.SideFpsOverlayViewBinder
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.ThreadFactory
+import com.android.systemui.util.settings.SecureSettings
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -46,6 +53,7 @@
 import dagger.multibindings.IntoMap
 import java.util.concurrent.Executor
 import javax.inject.Qualifier
+import kotlinx.coroutines.CoroutineDispatcher
 
 /** Dagger module for all things biometric. */
 @Module
@@ -114,6 +122,20 @@
                 BoundingBoxOverlapDetector(values[2])
             }
         }
+
+        @Provides
+        fun providesFingerprintInteractiveToAuth(
+            @Background backgroundDispatcher: CoroutineDispatcher,
+            context: Context,
+            secureSettings: SecureSettings,
+            selectedUserInteractor: SelectedUserInteractor,
+        ): FingerprintInteractiveToAuthProvider =
+            FingerprintInteractiveToAuthProviderImpl(
+                backgroundDispatcher,
+                context,
+                secureSettings,
+                selectedUserInteractor,
+            )
     }
 }