1 /*
2  * Copyright (C) 2019 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 package com.android.systemui.biometrics
17 
18 import android.content.Context
19 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
20 import android.util.AttributeSet
21 import android.util.Log
22 import android.widget.FrameLayout
23 import android.widget.TextView
24 import com.android.systemui.R
25 import com.android.systemui.biometrics.AuthController.ScaleFactorProvider
26 
27 private const val TAG = "AuthBiometricFingerprintView"
28 
29 /** Fingerprint only view for BiometricPrompt.  */
30 open class AuthBiometricFingerprintView(
31     context: Context,
32     attrs: AttributeSet? = null
33 ) : AuthBiometricView(context, attrs) {
34     /** If this view is for a SFPS sensor.  */
35     var isSfps = false
36         private set
37 
38     /** If this view is for a UDFPS sensor.  */
39     var isUdfps = false
40         private set
41 
42     private var udfpsAdapter: UdfpsDialogMeasureAdapter? = null
43     private var scaleFactorProvider: ScaleFactorProvider? = null
44 
45     /** Set the [sensorProps] of this sensor so the view can be customized prior to layout. */
46     fun setSensorProperties(sensorProps: FingerprintSensorPropertiesInternal) {
47         isSfps = sensorProps.isAnySidefpsType
48         isUdfps = sensorProps.isAnyUdfpsType
49         udfpsAdapter = if (isUdfps) UdfpsDialogMeasureAdapter(this, sensorProps) else null
50     }
51 
52     fun setScaleFactorProvider(scaleProvider: ScaleFactorProvider?) {
53         scaleFactorProvider = scaleProvider
54     }
55 
56     override fun onMeasureInternal(width: Int, height: Int): AuthDialog.LayoutParams {
57         val layoutParams = super.onMeasureInternal(width, height)
58         val scale = scaleFactorProvider?.provide() ?: 1.0f
59         return udfpsAdapter?.onMeasureInternal(width, height, layoutParams,
60             scale) ?: layoutParams
61     }
62 
63     override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
64         super.onLayout(changed, left, top, right, bottom)
65 
66         val adapter = udfpsAdapter
67         if (adapter != null) {
68             // Move the UDFPS icon and indicator text if necessary. This probably only needs to happen
69             // for devices where the UDFPS sensor is too low.
70             // TODO(b/201510778): Update this logic to support cases where the sensor or text overlap
71             //  the button bar area.
72             val bottomSpacerHeight = adapter.bottomSpacerHeight
73             Log.w(TAG, "bottomSpacerHeight: $bottomSpacerHeight")
74             if (bottomSpacerHeight < 0) {
75                 val iconFrame = findViewById<FrameLayout>(R.id.biometric_icon_frame)!!
76                 iconFrame.translationY = -bottomSpacerHeight.toFloat()
77                 val indicator = findViewById<TextView>(R.id.indicator)!!
78                 indicator.translationY = -bottomSpacerHeight.toFloat()
79             }
80         }
81     }
82 
83     override fun getDelayAfterAuthenticatedDurationMs() = 500
84 
85     override fun getStateForAfterError() = STATE_AUTHENTICATING
86 
87     override fun handleResetAfterError() = showTouchSensorString()
88 
89     override fun handleResetAfterHelp() = showTouchSensorString()
90 
91     override fun supportsSmallDialog() = false
92 
93     override fun createIconController(): AuthIconController =
94         AuthBiometricFingerprintIconController(mContext, mIconView, mIconViewOverlay)
95 
96     fun updateOverrideIconLayoutParamsSize() {
97         udfpsAdapter?.let {
98             val sensorDiameter = it.getSensorDiameter(scaleFactorProvider?.provide() ?: 1.0f)
99             (mIconController as? AuthBiometricFingerprintIconController)?.iconLayoutParamSize =
100                     Pair(sensorDiameter, sensorDiameter)
101         }
102     }
103 
104     override fun onAttachedToWindow() {
105         super.onAttachedToWindow()
106         showTouchSensorString()
107     }
108 
109     private fun showTouchSensorString() {
110         mIndicatorView.setText(R.string.fingerprint_dialog_touch_sensor)
111         mIndicatorView.setTextColor(mTextColorHint)
112     }
113 }
114