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