1 /*
2  * 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 
18 package com.android.systemui.keyguard.ui.view.layout.sections
19 
20 import android.content.Context
21 import android.graphics.Point
22 import android.graphics.Rect
23 import android.util.DisplayMetrics
24 import android.view.WindowManager
25 import androidx.annotation.VisibleForTesting
26 import androidx.constraintlayout.widget.ConstraintSet
27 import com.android.keyguard.KeyguardUpdateMonitor
28 import com.android.systemui.R
29 import com.android.systemui.biometrics.AuthController
30 import com.android.systemui.keyguard.data.repository.KeyguardSection
31 import javax.inject.Inject
32 
33 class DefaultLockIconSection
34 @Inject
35 constructor(
36     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
37     private val authController: AuthController,
38     private val windowManager: WindowManager,
39     private val context: Context,
40 ) : KeyguardSection {
41     private val lockIconViewId = R.id.lock_icon_view
42 
43     override fun apply(constraintSet: ConstraintSet) {
44         val isUdfpsSupported = keyguardUpdateMonitor.isUdfpsSupported
45         val scaleFactor: Float = authController.scaleFactor
46         val mBottomPaddingPx =
47             context.resources.getDimensionPixelSize(R.dimen.lock_icon_margin_bottom)
48         val mDefaultPaddingPx = context.resources.getDimensionPixelSize(R.dimen.lock_icon_padding)
49         val scaledPadding: Int = (mDefaultPaddingPx * scaleFactor).toInt()
50         val bounds = windowManager.currentWindowMetrics.bounds
51         val widthPixels = bounds.right.toFloat()
52         val heightPixels = bounds.bottom.toFloat()
53         val defaultDensity =
54             DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() /
55                 DisplayMetrics.DENSITY_DEFAULT.toFloat()
56         val lockIconRadiusPx = (defaultDensity * 36).toInt()
57 
58         if (isUdfpsSupported) {
59             authController.udfpsLocation?.let { udfpsLocation ->
60                 centerLockIcon(
61                     udfpsLocation,
62                     authController.udfpsRadius,
63                     scaledPadding,
64                     constraintSet
65                 )
66             }
67         } else {
68             centerLockIcon(
69                 Point(
70                     (widthPixels / 2).toInt(),
71                     (heightPixels - ((mBottomPaddingPx + lockIconRadiusPx) * scaleFactor)).toInt()
72                 ),
73                 lockIconRadiusPx * scaleFactor,
74                 scaledPadding,
75                 constraintSet,
76             )
77         }
78     }
79 
80     @VisibleForTesting
81     internal fun centerLockIcon(
82         center: Point,
83         radius: Float,
84         drawablePadding: Int,
85         constraintSet: ConstraintSet
86     ) {
87         val sensorRect =
88             Rect().apply {
89                 set(
90                     center.x - radius.toInt(),
91                     center.y - radius.toInt(),
92                     center.x + radius.toInt(),
93                     center.y + radius.toInt(),
94                 )
95             }
96 
97         constraintSet.apply {
98             constrainWidth(lockIconViewId, sensorRect.right - sensorRect.left)
99             constrainHeight(lockIconViewId, sensorRect.bottom - sensorRect.top)
100             connect(
101                 lockIconViewId,
102                 ConstraintSet.TOP,
103                 ConstraintSet.PARENT_ID,
104                 ConstraintSet.TOP,
105                 sensorRect.top
106             )
107             connect(
108                 lockIconViewId,
109                 ConstraintSet.START,
110                 ConstraintSet.PARENT_ID,
111                 ConstraintSet.START,
112                 sensorRect.left
113             )
114         }
115     }
116 }
117