1 /* <lambda>null2 * Copyright (C) 2024 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.settings.biometrics.fingerprint2.domain.interactor 18 19 import android.content.Context 20 import android.graphics.PointF 21 import android.util.TypedValue 22 import kotlinx.coroutines.flow.Flow 23 import kotlinx.coroutines.flow.MutableStateFlow 24 import kotlinx.coroutines.flow.combine 25 import kotlinx.coroutines.flow.update 26 27 /** 28 * This interactor provides information about the current offset of the sensor for guided enrollment 29 * on UDFPS devices. 30 */ 31 interface UdfpsEnrollInteractor { 32 /** Indicates at which step a UDFPS enrollment is in. */ 33 fun onEnrollmentStep(stepsRemaining: Int, totalStep: Int) 34 35 /** Indicates if guided enrollment should be enabled or not. */ 36 fun updateGuidedEnrollment(enabled: Boolean) 37 38 /** 39 * A flow indicating how much the sensor image drawable should be offset for guided enrollment. A 40 * null point indicates that the icon should be in its default position. 41 */ 42 val guidedEnrollmentOffset: Flow<PointF> 43 } 44 45 /** Keeps track of which guided enrollment point we should be using */ 46 class UdfpsEnrollInteractorImpl( 47 applicationContext: Context, 48 accessibilityInteractor: AccessibilityInteractor, 49 ) : UdfpsEnrollInteractor { 50 51 private var isGuidedEnrollment = MutableStateFlow(false) 52 // Number of pixels per mm 53 val px = 54 TypedValue.applyDimension( 55 TypedValue.COMPLEX_UNIT_MM, 56 1f, 57 applicationContext.resources.displayMetrics, 58 ) 59 private val guidedEnrollmentPoints: MutableList<PointF> = 60 mutableListOf( 61 PointF(2.00f * px, 0.00f * px), 62 PointF(0.87f * px, -2.70f * px), 63 PointF(-1.80f * px, -1.31f * px), 64 PointF(-1.80f * px, 1.31f * px), 65 PointF(0.88f * px, 2.70f * px), 66 PointF(3.94f * px, -1.06f * px), 67 PointF(2.90f * px, -4.14f * px), 68 PointF(-0.52f * px, -5.95f * px), 69 PointF(-3.33f * px, -3.33f * px), 70 PointF(-3.99f * px, -0.35f * px), 71 PointF(-3.62f * px, 2.54f * px), 72 PointF(-1.49f * px, 5.57f * px), 73 PointF(2.29f * px, 4.92f * px), 74 PointF(3.82f * px, 1.78f * px), 75 ) 76 onEnrollmentStepnull77 override fun onEnrollmentStep(stepsRemaining: Int, totalStep: Int) { 78 val index = (totalStep - stepsRemaining) % guidedEnrollmentPoints.size 79 _guidedEnrollment.update { guidedEnrollmentPoints[index] } 80 } 81 updateGuidedEnrollmentnull82 override fun updateGuidedEnrollment(enabled: Boolean) { 83 isGuidedEnrollment.update { enabled } 84 } 85 86 private val _guidedEnrollment = MutableStateFlow(PointF(0f, 0f)) 87 override val guidedEnrollmentOffset: Flow<PointF> = 88 combine( 89 _guidedEnrollment, 90 accessibilityInteractor.isAccessibilityEnabled, 91 isGuidedEnrollment, guidedEnrollmentEnablednull92 ) { point, accessibilityEnabled, guidedEnrollmentEnabled -> 93 if (accessibilityEnabled || !guidedEnrollmentEnabled) { 94 return@combine PointF(0f, 0f) 95 } else { 96 return@combine PointF(point.x * SCALE, point.y * SCALE) 97 } 98 } 99 100 companion object { 101 private const val SCALE = 0.5f 102 } 103 } 104