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