• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.R
28 import java.io.PrintWriter
29 
30 class RoundedCornerResDelegate(
31     private val res: Resources,
32     private var displayUniqueId: String?
33 ) : Dumpable {
34 
35     private val density: Float
36         get() = res.displayMetrics.density
37 
38     private var reloadToken: Int = 0
39 
40     var hasTop: Boolean = false
41         private set
42 
43     var hasBottom: Boolean = false
44         private set
45 
46     var topRoundedDrawable: Drawable? = null
47         private set
48 
49     var bottomRoundedDrawable: Drawable? = null
50         private set
51 
52     var topRoundedSize = Size(0, 0)
53         private set
54 
55     var bottomRoundedSize = Size(0, 0)
56         private set
57 
58     var tuningSizeFactor: Int? = null
59         set(value) {
60             if (field == value) {
61                 return
62             }
63             field = value
64             reloadMeasures()
65         }
66 
67     var physicalPixelDisplaySizeRatio: Float = 1f
68         set(value) {
69             if (field == value) {
70                 return
71             }
72             field = value
73             reloadMeasures()
74         }
75 
76     init {
77         reloadRes()
78         reloadMeasures()
79     }
80 
81     fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
82         if (displayUniqueId != newDisplayUniqueId) {
83             displayUniqueId = newDisplayUniqueId
84             newReloadToken ?.let { reloadToken = it }
85             reloadRes()
86             reloadMeasures()
87         } else if (newReloadToken != null) {
88             if (reloadToken == newReloadToken) {
89                 return
90             }
91             reloadToken = newReloadToken
92             reloadMeasures()
93         }
94     }
95 
96     private fun reloadRes() {
97         val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
98 
99         val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
100         hasTop = hasDefaultRadius ||
101             (RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
102         hasBottom = hasDefaultRadius ||
103             (RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
104 
105         topRoundedDrawable = getDrawable(
106             displayConfigIndex = configIdx,
107             arrayResId = R.array.config_roundedCornerTopDrawableArray,
108             backupDrawableId = R.drawable.rounded_corner_top
109         )
110         bottomRoundedDrawable = getDrawable(
111             displayConfigIndex = configIdx,
112             arrayResId = R.array.config_roundedCornerBottomDrawableArray,
113             backupDrawableId = R.drawable.rounded_corner_bottom
114         )
115     }
116 
117     private fun reloadMeasures() {
118         topRoundedDrawable?.let {
119             topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
120         }
121         bottomRoundedDrawable?.let {
122             bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
123         }
124 
125         tuningSizeFactor?.let {
126             if (it <= 0) {
127                 return
128             }
129             val length: Int = (it * density).toInt()
130             if (topRoundedSize.width > 0) {
131                 topRoundedSize = Size(length, length)
132             }
133             if (bottomRoundedSize.width > 0) {
134                 bottomRoundedSize = Size(length, length)
135             }
136         }
137 
138         if (physicalPixelDisplaySizeRatio != 1f) {
139             if (topRoundedSize.width != 0) {
140                 topRoundedSize = Size(
141                     (physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
142                     (physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt()
143                 )
144             }
145             if (bottomRoundedSize.width != 0) {
146                 bottomRoundedSize = Size(
147                     (physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
148                     (physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt()
149                 )
150             }
151         }
152     }
153 
154     private fun getDrawable(
155         displayConfigIndex: Int,
156         @ArrayRes arrayResId: Int,
157         @DrawableRes backupDrawableId: Int
158     ): Drawable? {
159         val drawable: Drawable?
160         res.obtainTypedArray(arrayResId).let { array ->
161             drawable = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) {
162                 array.getDrawable(displayConfigIndex)
163             } else {
164                 res.getDrawable(backupDrawableId, null)
165             }
166             array.recycle()
167         }
168         return drawable
169     }
170 
171     override fun dump(pw: PrintWriter, args: Array<out String>) {
172         pw.println("RoundedCornerResDelegate state:")
173         pw.println("  hasTop=$hasTop")
174         pw.println("  hasBottom=$hasBottom")
175         pw.println("  topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
176         pw.println(
177             "  bottomRoundedSize(w,h)=(${bottomRoundedSize.width},${bottomRoundedSize.height})"
178         )
179         pw.println("  physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
180     }
181 }
182