From 696250a4ecf4e716ddbf2769d09ef4441ffec34e Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Mon, 23 Aug 2021 14:16:00 +0100 Subject: [PATCH] Update statusbar insets when switching displays Caches statusbar insets for each display and notifies about changes if the insets has changed Fixes: 195087279 Test: checked statusbar size on foldable devices in different rotations on both screens atest: com.android.systemui.statusbar.phone.StatusBarContentInsetsProviderTest Change-Id: I6c3ee7eeafd1940902d9b17cbb749ba525ebf97f Merged-In: I6c3ee7eeafd1940902d9b17cbb749ba525ebf97f --- .../phone/ConfigurationControllerImpl.kt | 10 ++ .../phone/StatusBarContentInsetsProvider.kt | 85 ++++++------ .../policy/ConfigurationController.java | 1 + .../StatusBarContentInsetsProviderTest.kt | 124 ++++++++++++++---- 4 files changed, 155 insertions(+), 65 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt index 07618da4451a4..12ae3f1d66cbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone import android.content.Context import android.content.pm.ActivityInfo import android.content.res.Configuration +import android.graphics.Rect import android.os.LocaleList import android.view.View.LAYOUT_DIRECTION_RTL import com.android.systemui.statusbar.policy.ConfigurationController @@ -29,6 +30,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController { private val lastConfig = Configuration() private var density: Int = 0 private var smallestScreenWidth: Int = 0 + private var maxBounds: Rect? = null private var fontScale: Float = 0.toFloat() private val inCarMode: Boolean private var uiMode: Int = 0 @@ -85,6 +87,14 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController { } } + val maxBounds = newConfig.windowConfiguration.maxBounds + if (maxBounds != this.maxBounds) { + this.maxBounds = maxBounds + listeners.filterForEach({ this.listeners.contains(it) }) { + it.onMaxBoundsChanged() + } + } + val localeList = newConfig.locales if (localeList != this.localeList) { this.localeList = localeList diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt index fe1f63a34acd5..515094bd6ec01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt @@ -19,11 +19,10 @@ package com.android.systemui.statusbar.phone import android.content.Context import android.content.res.Resources import android.graphics.Rect -import android.util.Log +import android.util.LruCache import android.util.Pair import android.view.DisplayCutout import android.view.View.LAYOUT_DIRECTION_RTL -import android.view.WindowManager import android.view.WindowMetrics import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable @@ -38,6 +37,7 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN import com.android.systemui.util.leak.RotationUtils.Rotation +import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation import java.io.FileDescriptor import java.io.PrintWriter import java.lang.Math.max @@ -61,13 +61,14 @@ import javax.inject.Inject class StatusBarContentInsetsProvider @Inject constructor( val context: Context, val configurationController: ConfigurationController, - val windowManager: WindowManager, val dumpManager: DumpManager ) : CallbackController, ConfigurationController.ConfigurationListener, Dumpable { - // Indexed by @Rotation - private val insetsByCorner = arrayOfNulls(4) + + // Limit cache size as potentially we may connect large number of displays + // (e.g. network displays) + private val insetsCache = LruCache(MAX_CACHE_SIZE) private val listeners = mutableSetOf() init { @@ -91,12 +92,12 @@ class StatusBarContentInsetsProvider @Inject constructor( clearCachedInsets() } - private fun clearCachedInsets() { - insetsByCorner[0] = null - insetsByCorner[1] = null - insetsByCorner[2] = null - insetsByCorner[3] = null + override fun onMaxBoundsChanged() { + notifyInsetsChanged() + } + private fun clearCachedInsets() { + insetsCache.evictAll() notifyInsetsChanged() } @@ -111,10 +112,10 @@ class StatusBarContentInsetsProvider @Inject constructor( * dot in the coordinates relative to the given rotation. */ fun getBoundingRectForPrivacyChipForRotation(@Rotation rotation: Int): Rect { - var insets = insetsByCorner[rotation] - val rotatedResources = RotationUtils.getResourcesForRotation(rotation, context) + var insets = insetsCache[getCacheKey(rotation = rotation)] + val rotatedResources = getResourcesForRotation(rotation, context) if (insets == null) { - insets = getAndSetInsetsForRotation(rotation, rotatedResources) + insets = getStatusBarContentInsetsForRotation(rotation, rotatedResources) } val dotWidth = rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_diameter) @@ -129,24 +130,16 @@ class StatusBarContentInsetsProvider @Inject constructor( * Calculates the necessary left and right locations for the status bar contents invariant of * the current device rotation, in the target rotation's coordinates */ - fun getStatusBarContentInsetsForRotation(@Rotation rotation: Int): Rect { - var insets = insetsByCorner[rotation] - if (insets == null) { - val rotatedResources = RotationUtils.getResourcesForRotation(rotation, context) - insets = getAndSetInsetsForRotation(rotation, rotatedResources) - } - - return insets - } - - private fun getAndSetInsetsForRotation( - @Rotation rot: Int, - rotatedResources: Resources + @JvmOverloads + fun getStatusBarContentInsetsForRotation( + @Rotation rotation: Int, + rotatedResources: Resources = getResourcesForRotation(rotation, context) ): Rect { - val insets = getCalculatedInsetsForRotation(rot, rotatedResources) - insetsByCorner[rot] = insets - - return insets + val key = getCacheKey(rotation = rotation) + return insetsCache[key] ?: getCalculatedInsetsForRotation(rotation, rotatedResources) + .also { + insetsCache.put(key, it) + } } private fun getCalculatedInsetsForRotation( @@ -176,17 +169,29 @@ class StatusBarContentInsetsProvider @Inject constructor( currentRotation, targetRotation, dc, - windowManager.maximumWindowMetrics, + context.resources.configuration.windowConfiguration.maxBounds, rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height), minLeft, minRight) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array) { - insetsByCorner.forEachIndexed { index, rect -> - pw.println("${RotationUtils.toString(index)} -> $rect") + insetsCache.snapshot().forEach { (key, rect) -> + pw.println("$key -> $rect") } + pw.println(insetsCache) } + + private fun getCacheKey(@Rotation rotation: Int): CacheKey = + CacheKey( + uniqueDisplayId = context.display.uniqueId, + rotation = rotation + ) + + private data class CacheKey( + val uniqueDisplayId: String, + @Rotation val rotation: Int + ) } interface StatusBarContentInsetsChangedListener { @@ -194,10 +199,9 @@ interface StatusBarContentInsetsChangedListener { } private const val TAG = "StatusBarInsetsProvider" +private const val MAX_CACHE_SIZE = 16 -private fun getRotationZeroDisplayBounds(wm: WindowMetrics, @Rotation exactRotation: Int): Rect { - val bounds = wm.bounds - +private fun getRotationZeroDisplayBounds(bounds: Rect, @Rotation exactRotation: Int): Rect { if (exactRotation == ROTATION_NONE || exactRotation == ROTATION_UPSIDE_DOWN) { return bounds } @@ -243,7 +247,7 @@ fun calculateInsetsForRotationWithRotatedResources( @Rotation currentRotation: Int, @Rotation targetRotation: Int, displayCutout: DisplayCutout?, - windowMetrics: WindowMetrics, + maxBounds: Rect, statusBarHeight: Int, minLeft: Int, minRight: Int @@ -254,16 +258,15 @@ fun calculateInsetsForRotationWithRotatedResources( val right = if (isRtl) paddingStart else paddingEnd */ - val rotZeroBounds = getRotationZeroDisplayBounds(windowMetrics, currentRotation) - val currentBounds = windowMetrics.bounds + val rotZeroBounds = getRotationZeroDisplayBounds(maxBounds, currentRotation) val sbLeftRight = getStatusBarLeftRight( displayCutout, statusBarHeight, rotZeroBounds.right, rotZeroBounds.bottom, - currentBounds.width(), - currentBounds.height(), + maxBounds.width(), + maxBounds.height(), minLeft, minRight, targetRotation, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java index 3a05ec78a8b0b..e679c4c97f18d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java @@ -37,6 +37,7 @@ public interface ConfigurationController extends CallbackController