From 4b1b5a68dd4c86069b1f1f6adb2051f7dbb37b87 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Wed, 30 Jun 2021 18:19:14 -0400 Subject: [PATCH] Enforfce a minimum padding to ensure space for the privacy dot Bug: 191998138 Test: atest StatusBarContentInsetsProviderTest Change-Id: I3b28dd78f909321a54a3e196b67011d3165cbbd3 Merged-In: I3b28dd78f909321a54a3e196b67011d3165cbbd3 --- packages/SystemUI/res/values/dimens.xml | 2 + .../phone/StatusBarContentInsetsProvider.kt | 55 ++++++-- .../StatusBarContentInsetsProviderTest.kt | 125 ++++++++++++------ 3 files changed, 131 insertions(+), 51 deletions(-) diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7485ef858620a..a299a1221c9e8 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1266,6 +1266,8 @@ 76dp 6dp + + 20dp @dimen/notification_shade_content_margin_horizontal 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 edcf261115d26..fe1f63a34acd5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt @@ -19,6 +19,7 @@ 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.Pair import android.view.DisplayCutout import android.view.View.LAYOUT_DIRECTION_RTL @@ -155,13 +156,30 @@ class StatusBarContentInsetsProvider @Inject constructor( val dc = context.display.cutout val currentRotation = RotationUtils.getExactRotation(context) + val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL + val roundedCornerPadding = rotatedResources + .getDimensionPixelSize(R.dimen.rounded_corner_content_padding) + val minDotWidth = rotatedResources + .getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding) + + val minLeft: Int + val minRight: Int + if (isRtl) { + minLeft = max(minDotWidth, roundedCornerPadding) + minRight = roundedCornerPadding + } else { + minLeft = roundedCornerPadding + minRight = max(minDotWidth, roundedCornerPadding) + } + return calculateInsetsForRotationWithRotatedResources( currentRotation, targetRotation, dc, windowManager.maximumWindowMetrics, rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height), - rotatedResources.getDimensionPixelSize(R.dimen.rounded_corner_content_padding)) + minLeft, + minRight) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array) { @@ -212,9 +230,12 @@ fun getPrivacyChipBoundingRectForInsets( * Calculates the exact left and right positions for the status bar contents for the given * rotation * - * @param rot rotation for which to query the margins - * @param context systemui context - * @param rotatedResources resources constructed with the proper orientation set + * @param currentRotation current device rotation + * @param targetRotation rotation for which to calculate the status bar content rect + * @param displayCutout [DisplayCutout] for the curren display. possibly null + * @param windowMetrics [WindowMetrics] for the current window + * @param statusBarHeight height of the status bar for the target rotation + * @param roundedCornerPadding from rounded_corner_content_padding * * @see [RotationUtils#getResourcesForRotation] */ @@ -224,7 +245,8 @@ fun calculateInsetsForRotationWithRotatedResources( displayCutout: DisplayCutout?, windowMetrics: WindowMetrics, statusBarHeight: Int, - roundedCornerPadding: Int + minLeft: Int, + minRight: Int ): Rect { /* TODO: Check if this is ever used for devices with no rounded corners @@ -242,7 +264,8 @@ fun calculateInsetsForRotationWithRotatedResources( rotZeroBounds.bottom, currentBounds.width(), currentBounds.height(), - roundedCornerPadding, + minLeft, + minRight, targetRotation, currentRotation) @@ -256,7 +279,10 @@ fun calculateInsetsForRotationWithRotatedResources( * @param sbHeight appropriate status bar height for this rotation * @param width display width calculated for ROTATION_NONE * @param height display height calculated for ROTATION_NONE - * @param roundedCornerPadding rounded_corner_content_padding dimension + * @param cWidth display width in our current rotation + * @param cHeight display height in our current rotation + * @param minLeft the minimum padding to enforce on the left + * @param minRight the minimum padding to enforce on the right * @param targetRotation the rotation for which to calculate margins * @param currentRotation the rotation from which the display cutout was generated * @@ -270,7 +296,8 @@ private fun getStatusBarLeftRight( height: Int, cWidth: Int, cHeight: Int, - roundedCornerPadding: Int, + minLeft: Int, + minRight: Int, @Rotation targetRotation: Int, @Rotation currentRotation: Int ): Rect { @@ -279,9 +306,9 @@ private fun getStatusBarLeftRight( val cutoutRects = dc?.boundingRects if (cutoutRects == null || cutoutRects.isEmpty()) { - return Rect(roundedCornerPadding, + return Rect(minLeft, 0, - logicalDisplayWidth - roundedCornerPadding, + logicalDisplayWidth - minRight, sbHeight) } @@ -294,8 +321,8 @@ private fun getStatusBarLeftRight( // Size of the status bar window for the given rotation relative to our exact rotation val sbRect = sbRect(relativeRotation, sbHeight, Pair(cWidth, cHeight)) - var leftMargin = roundedCornerPadding - var rightMargin = roundedCornerPadding + var leftMargin = minLeft + var rightMargin = minRight for (cutoutRect in cutoutRects) { // There is at most one non-functional area per short edge of the device. So if the status // bar doesn't share a short edge with the cutout, we can ignore its insets because there @@ -306,11 +333,11 @@ private fun getStatusBarLeftRight( if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) { - val l = max(roundedCornerPadding, cutoutRect.logicalWidth(relativeRotation)) + val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation)) leftMargin = max(l, leftMargin) } else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) { val logicalWidth = cutoutRect.logicalWidth(relativeRotation) - rightMargin = max(roundedCornerPadding, logicalWidth) + rightMargin = max(minRight, logicalWidth) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt index 4796cd7689809..10eb71f41c1e2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt @@ -47,7 +47,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { @Test fun testGetBoundingRectForPrivacyChipForRotation_noCutout() { val screenBounds = Rect(0, 0, 1080, 2160) - val roundedCornerPadding = 20 + val minLeftPadding = 20 + val minRightPadding = 20 val sbHeightPortrait = 100 val sbHeightLandscape = 60 val currentRotation = ROTATION_NONE @@ -64,7 +65,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { null, windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) var chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl) /* 1080 - 20 (rounded corner) - 30 (chip), @@ -92,7 +94,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl) /* 2160 - 20 (rounded corner) - 30 (chip), @@ -118,7 +121,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { // GIVEN a device in portrait mode with width < height and a display cutout in the top-left val screenBounds = Rect(0, 0, 1080, 2160) val dcBounds = Rect(0, 0, 100, 100) - val roundedCornerPadding = 20 + val minLeftPadding = 20 + val minRightPadding = 20 val sbHeightPortrait = 100 val sbHeightLandscape = 60 val currentRotation = ROTATION_NONE @@ -131,7 +135,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { var targetRotation = ROTATION_NONE var expectedBounds = Rect(dcBounds.right, 0, - screenBounds.right - roundedCornerPadding, + screenBounds.right - minRightPadding, sbHeightPortrait) var bounds = calculateInsetsForRotationWithRotatedResources( @@ -140,14 +144,15 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_LANDSCAPE expectedBounds = Rect(dcBounds.height(), 0, - screenBounds.height() - roundedCornerPadding, + screenBounds.height() - minRightPadding, sbHeightLandscape) bounds = calculateInsetsForRotationWithRotatedResources( @@ -156,16 +161,17 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) // THEN the side that does NOT share a short side with the display cutout ignores the // display cutout bounds targetRotation = ROTATION_UPSIDE_DOWN - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, - screenBounds.width() - roundedCornerPadding, + screenBounds.width() - minRightPadding, sbHeightPortrait) bounds = calculateInsetsForRotationWithRotatedResources( @@ -174,13 +180,14 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) // Phone in portrait, seascape (rot_270) bounds targetRotation = ROTATION_SEASCAPE - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, screenBounds.height() - dcBounds.height(), sbHeightLandscape) @@ -191,7 +198,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) } @@ -205,7 +213,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { val screenBounds = Rect(0, 0, 1080, 2160) // cutout centered at the top val dcBounds = Rect(490, 0, 590, 100) - val roundedCornerPadding = 20 + val minLeftPadding = 20 + val minRightPadding = 20 val sbHeightPortrait = 100 val sbHeightLandscape = 60 val currentRotation = ROTATION_NONE @@ -216,9 +225,9 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { // THEN only the landscape/seascape rotations should avoid the cutout area because of the // potential letterboxing var targetRotation = ROTATION_NONE - var expectedBounds = Rect(roundedCornerPadding, + var expectedBounds = Rect(minLeftPadding, 0, - screenBounds.right - roundedCornerPadding, + screenBounds.right - minRightPadding, sbHeightPortrait) var bounds = calculateInsetsForRotationWithRotatedResources( @@ -227,14 +236,15 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_LANDSCAPE expectedBounds = Rect(dcBounds.height(), 0, - screenBounds.height() - roundedCornerPadding, + screenBounds.height() - minRightPadding, sbHeightLandscape) bounds = calculateInsetsForRotationWithRotatedResources( @@ -243,14 +253,15 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_UPSIDE_DOWN - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, - screenBounds.right - roundedCornerPadding, + screenBounds.right - minRightPadding, sbHeightPortrait) bounds = calculateInsetsForRotationWithRotatedResources( @@ -259,12 +270,13 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_SEASCAPE - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, screenBounds.height() - dcBounds.height(), sbHeightLandscape) @@ -275,7 +287,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { dc, windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) } @@ -285,7 +298,8 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { // GIVEN device in portrait mode, where width < height and no cutout val currentRotation = ROTATION_NONE val screenBounds = Rect(0, 0, 1080, 2160) - val roundedCornerPadding = 20 + val minLeftPadding = 20 + val minRightPadding = 20 val sbHeightPortrait = 100 val sbHeightLandscape = 60 @@ -293,9 +307,9 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { // THEN content insets should only use rounded corner padding var targetRotation = ROTATION_NONE - var expectedBounds = Rect(roundedCornerPadding, + var expectedBounds = Rect(minLeftPadding, 0, - screenBounds.right - roundedCornerPadding, + screenBounds.right - minRightPadding, sbHeightPortrait) var bounds = calculateInsetsForRotationWithRotatedResources( @@ -304,13 +318,14 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { null, /* no cutout */ windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_LANDSCAPE - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, - screenBounds.height() - roundedCornerPadding, + screenBounds.height() - minRightPadding, sbHeightLandscape) bounds = calculateInsetsForRotationWithRotatedResources( @@ -319,13 +334,14 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { null, /* no cutout */ windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_UPSIDE_DOWN - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, - screenBounds.width() - roundedCornerPadding, + screenBounds.width() - minRightPadding, sbHeightPortrait) bounds = calculateInsetsForRotationWithRotatedResources( @@ -334,13 +350,14 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { null, /* no cutout */ windowMetrics, sbHeightPortrait, - roundedCornerPadding) + minLeftPadding, + minRightPadding) assertRects(expectedBounds, bounds, currentRotation, targetRotation) targetRotation = ROTATION_LANDSCAPE - expectedBounds = Rect(roundedCornerPadding, + expectedBounds = Rect(minLeftPadding, 0, - screenBounds.height() - roundedCornerPadding, + screenBounds.height() - minRightPadding, sbHeightLandscape) bounds = calculateInsetsForRotationWithRotatedResources( @@ -349,7 +366,41 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() { null, /* no cutout */ windowMetrics, sbHeightLandscape, - roundedCornerPadding) + minLeftPadding, + minRightPadding) + assertRects(expectedBounds, bounds, currentRotation, targetRotation) + } + + @Test + fun testMinLeftRight_accountsForDisplayCutout() { + // GIVEN a device in portrait mode with width < height and a display cutout in the top-left + val screenBounds = Rect(0, 0, 1080, 2160) + val dcBounds = Rect(0, 0, 100, 100) + val minLeftPadding = 80 + val minRightPadding = 150 + val sbHeightPortrait = 100 + val sbHeightLandscape = 60 + val currentRotation = ROTATION_NONE + + `when`(windowMetrics.bounds).thenReturn(screenBounds) + `when`(dc.boundingRects).thenReturn(listOf(dcBounds)) + + // THEN left should be set to the display cutout width, and right should use the minRight + var targetRotation = ROTATION_NONE + var expectedBounds = Rect(dcBounds.right, + 0, + screenBounds.right - minRightPadding, + sbHeightPortrait) + + var bounds = calculateInsetsForRotationWithRotatedResources( + currentRotation, + targetRotation, + dc, + windowMetrics, + sbHeightPortrait, + minLeftPadding, + minRightPadding) + assertRects(expectedBounds, bounds, currentRotation, targetRotation) }