• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 package com.android.systemui.plugins.clocks
15 
16 import android.util.DisplayMetrics
17 import android.view.View
18 import androidx.constraintlayout.widget.ConstraintSet
19 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
20 import androidx.constraintlayout.widget.ConstraintSet.END
21 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
22 import androidx.constraintlayout.widget.ConstraintSet.START
23 import androidx.constraintlayout.widget.ConstraintSet.TOP
24 import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
25 import com.android.internal.policy.SystemBarUtils
26 import com.android.systemui.plugins.annotations.GeneratedImport
27 import com.android.systemui.plugins.annotations.ProtectedInterface
28 import com.android.systemui.plugins.annotations.ProtectedReturn
29 import com.android.systemui.plugins.clocks.ContextExt.getDimen
30 import com.android.systemui.plugins.clocks.ContextExt.getId
31 
32 /** Specifies layout information for the clock face */
33 @ProtectedInterface
34 @GeneratedImport("java.util.ArrayList")
35 @GeneratedImport("android.view.View")
36 interface ClockFaceLayout {
37     @get:ProtectedReturn("return new ArrayList<View>();")
38     /** All clock views to add to the root constraint layout before applying constraints. */
39     val views: List<View>
40 
41     @ProtectedReturn("return constraints;")
42     /** Custom constraints to apply to Lockscreen ConstraintLayout. */
43     fun applyConstraints(constraints: ConstraintSet): ConstraintSet
44 
45     @ProtectedReturn("return constraints;")
46     /** Custom constraints to apply to preview ConstraintLayout. */
47     fun applyPreviewConstraints(
48         clockPreviewConfig: ClockPreviewConfig,
49         constraints: ConstraintSet,
50     ): ConstraintSet
51 
52     /** Apply specified AOD BurnIn parameters to this layout */
53     fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel)
54 }
55 
56 /** Data class to contain AOD BurnIn information for correct aod rendering */
57 data class AodClockBurnInModel(
58     /** Scale that the clock should render at to mitigate burnin */
59     val scale: Float,
60 
61     /** X-Translation for the clock to mitigate burnin */
62     val translationX: Float,
63 
64     /** Y-Translation for the clock to mitigate burnin */
65     val translationY: Float,
66 )
67 
68 /** A ClockFaceLayout that applies the default lockscreen layout to a single view */
69 class DefaultClockFaceLayout(val view: View) : ClockFaceLayout {
70     override val views = listOf(view)
71 
applyConstraintsnull72     override fun applyConstraints(constraints: ConstraintSet): ConstraintSet {
73         if (views.size != 1) {
74             throw IllegalArgumentException(
75                 "Should have only one container view when using DefaultClockFaceLayout"
76             )
77         }
78         return constraints
79     }
80 
applyPreviewConstraintsnull81     override fun applyPreviewConstraints(
82         clockPreviewConfig: ClockPreviewConfig,
83         constraints: ConstraintSet,
84     ): ConstraintSet {
85         return applyDefaultPreviewConstraints(clockPreviewConfig, constraints)
86     }
87 
applyAodBurnInnull88     override fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) {
89         // Default clock doesn't need detailed control of view
90     }
91 
92     companion object {
applyDefaultPreviewConstraintsnull93         fun applyDefaultPreviewConstraints(
94             clockPreviewConfig: ClockPreviewConfig,
95             constraints: ConstraintSet,
96         ): ConstraintSet {
97             constraints.apply {
98                 val context = clockPreviewConfig.context
99                 val lockscreenClockViewLargeId = context.getId("lockscreen_clock_view_large")
100                 constrainWidth(lockscreenClockViewLargeId, WRAP_CONTENT)
101                 constrainHeight(lockscreenClockViewLargeId, WRAP_CONTENT)
102                 constrainMaxHeight(lockscreenClockViewLargeId, 0)
103 
104                 val largeClockTopMargin =
105                     SystemBarUtils.getStatusBarHeight(context) +
106                         context.getDimen("small_clock_padding_top") +
107                         context.getDimen("keyguard_smartspace_top_offset") +
108                         context.getDimen("date_weather_view_height") +
109                         context.getDimen("enhanced_smartspace_height")
110                 connect(lockscreenClockViewLargeId, TOP, PARENT_ID, TOP, largeClockTopMargin)
111                 connect(lockscreenClockViewLargeId, START, PARENT_ID, START)
112                 connect(lockscreenClockViewLargeId, END, PARENT_ID, END)
113 
114                 clockPreviewConfig.udfpsTop?.let {
115                     val screenHeight = context.resources.displayMetrics.heightPixels
116                     connect(
117                         lockscreenClockViewLargeId,
118                         BOTTOM,
119                         PARENT_ID,
120                         BOTTOM,
121                         (screenHeight - it).toInt(),
122                     )
123                 }
124                     ?: run {
125                         // Copied calculation codes from applyConstraints in
126                         // DefaultDeviceEntrySection
127                         clockPreviewConfig.lockId?.let { lockId ->
128                             connect(lockscreenClockViewLargeId, BOTTOM, lockId, TOP)
129                         }
130                             ?: run {
131                                 val bottomPaddingPx = context.getDimen("lock_icon_margin_bottom")
132                                 val defaultDensity =
133                                     DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() /
134                                         DisplayMetrics.DENSITY_DEFAULT.toFloat()
135                                 val lockIconRadiusPx = (defaultDensity * 36).toInt()
136                                 val clockBottomMargin = bottomPaddingPx + 2 * lockIconRadiusPx
137                                 connect(
138                                     lockscreenClockViewLargeId,
139                                     BOTTOM,
140                                     PARENT_ID,
141                                     BOTTOM,
142                                     clockBottomMargin,
143                                 )
144                             }
145                     }
146 
147                 val smallClockViewId = context.getId("lockscreen_clock_view")
148                 constrainWidth(smallClockViewId, WRAP_CONTENT)
149                 constrainHeight(smallClockViewId, context.getDimen("small_clock_height"))
150                 connect(
151                     smallClockViewId,
152                     START,
153                     PARENT_ID,
154                     START,
155                     context.getDimen("clock_padding_start") +
156                         context.getDimen("status_view_margin_horizontal"),
157                 )
158 
159                 val smallClockTopMargin = clockPreviewConfig.getSmallClockTopPadding()
160                 connect(smallClockViewId, TOP, PARENT_ID, TOP, smallClockTopMargin)
161             }
162             return constraints
163         }
164     }
165 }
166