1 /*
<lambda>null2  * Copyright (C) 2022 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.systemui.decor
18 
19 import android.annotation.ArrayRes
20 import android.annotation.DrawableRes
21 import android.content.res.Resources
22 import android.graphics.drawable.Drawable
23 import android.util.DisplayUtils
24 import android.util.Size
25 import android.view.RoundedCorners
26 import com.android.systemui.Dumpable
27 import com.android.systemui.res.R
28 import java.io.PrintWriter
29 
30 interface RoundedCornerResDelegate {
31     val hasTop: Boolean
32     val topRoundedDrawable: Drawable?
33     val topRoundedSize: Size
34 
35     val hasBottom: Boolean
36     val bottomRoundedDrawable: Drawable?
37     val bottomRoundedSize: Size
38 
39     var physicalPixelDisplaySizeRatio: Float
40 
41     fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?)
42 }
43 
44 /**
45  * Delegate for the device-default rounded corners. These will always be loaded from the config
46  * values `R.array.config_roundedCornerTopDrawableArray` and `R.drawable.rounded_corner_top`
47  */
48 class RoundedCornerResDelegateImpl(
49     private val res: Resources,
50     private var displayUniqueId: String?
51 ) : RoundedCornerResDelegate, Dumpable {
52 
53     private var reloadToken: Int = 0
54 
55     override var hasTop: Boolean = false
56         private set
57 
58     override var hasBottom: Boolean = false
59         private set
60 
61     override var topRoundedDrawable: Drawable? = null
62         private set
63 
64     override var bottomRoundedDrawable: Drawable? = null
65         private set
66 
67     override var topRoundedSize = Size(0, 0)
68         private set
69 
70     override var bottomRoundedSize = Size(0, 0)
71         private set
72 
73     override var physicalPixelDisplaySizeRatio: Float = 1f
74         set(value) {
75             if (field == value) {
76                 return
77             }
78             field = value
79             reloadMeasures()
80         }
81 
82     init {
83         reloadRes()
84         reloadMeasures()
85     }
86 
updateDisplayUniqueIdnull87     override fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
88         if (displayUniqueId != newDisplayUniqueId) {
89             displayUniqueId = newDisplayUniqueId
90             newReloadToken ?.let { reloadToken = it }
91             reloadRes()
92             reloadMeasures()
93         } else if (newReloadToken != null) {
94             if (reloadToken == newReloadToken) {
95                 return
96             }
97             reloadToken = newReloadToken
98             reloadMeasures()
99         }
100     }
101 
reloadResnull102     private fun reloadRes() {
103         val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
104 
105         val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
106         hasTop = hasDefaultRadius ||
107             (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
108         hasBottom = hasDefaultRadius ||
109             (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
110 
111         topRoundedDrawable = getDrawable(
112             displayConfigIndex = configIdx,
113             arrayResId = R.array.config_roundedCornerTopDrawableArray,
114             backupDrawableId = R.drawable.rounded_corner_top
115         )
116         bottomRoundedDrawable = getDrawable(
117             displayConfigIndex = configIdx,
118             arrayResId = R.array.config_roundedCornerBottomDrawableArray,
119             backupDrawableId = R.drawable.rounded_corner_bottom
120         )
121     }
122 
reloadMeasuresnull123     private fun reloadMeasures() {
124         topRoundedDrawable?.let {
125             topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
126         }
127         bottomRoundedDrawable?.let {
128             bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
129         }
130 
131         if (physicalPixelDisplaySizeRatio != 1f) {
132             if (topRoundedSize.width != 0) {
133                 topRoundedSize = Size(
134                     (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
135                     (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt()
136                 )
137             }
138             if (bottomRoundedSize.width != 0) {
139                 bottomRoundedSize = Size(
140                     (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
141                     (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt()
142                 )
143             }
144         }
145     }
146 
getDrawablenull147     private fun getDrawable(
148         displayConfigIndex: Int,
149         @ArrayRes arrayResId: Int,
150         @DrawableRes backupDrawableId: Int
151     ): Drawable? {
152         val drawable: Drawable?
153         res.obtainTypedArray(arrayResId).let { array ->
154             drawable = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) {
155                 array.getDrawable(displayConfigIndex)
156             } else {
157                 res.getDrawable(backupDrawableId, null)
158             }
159             array.recycle()
160         }
161         return drawable
162     }
163 
dumpnull164     override fun dump(pw: PrintWriter, args: Array<out String>) {
165         pw.println("RoundedCornerResDelegate state:")
166         pw.println("  hasTop=$hasTop")
167         pw.println("  hasBottom=$hasBottom")
168         pw.println("  topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
169         pw.println(
170             "  bottomRoundedSize(w,h)=(${bottomRoundedSize.width},${bottomRoundedSize.height})"
171         )
172         pw.println("  physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
173     }
174 }
175