Merge "Update statusbar insets when switching displays" into sc-v2-dev am: 2c5de36476
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15640805 Change-Id: Idb4673e1e16d6cfe36aad1b36df3764b93ae1f8e
This commit is contained in:
@@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Rect
|
||||||
import android.os.LocaleList
|
import android.os.LocaleList
|
||||||
import android.view.View.LAYOUT_DIRECTION_RTL
|
import android.view.View.LAYOUT_DIRECTION_RTL
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
@@ -29,6 +30,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
|
|||||||
private val lastConfig = Configuration()
|
private val lastConfig = Configuration()
|
||||||
private var density: Int = 0
|
private var density: Int = 0
|
||||||
private var smallestScreenWidth: Int = 0
|
private var smallestScreenWidth: Int = 0
|
||||||
|
private var maxBounds: Rect? = null
|
||||||
private var fontScale: Float = 0.toFloat()
|
private var fontScale: Float = 0.toFloat()
|
||||||
private val inCarMode: Boolean
|
private val inCarMode: Boolean
|
||||||
private var uiMode: Int = 0
|
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
|
val localeList = newConfig.locales
|
||||||
if (localeList != this.localeList) {
|
if (localeList != this.localeList) {
|
||||||
this.localeList = localeList
|
this.localeList = localeList
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ package com.android.systemui.statusbar.phone
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.util.Log
|
import android.util.LruCache
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.View.LAYOUT_DIRECTION_RTL
|
import android.view.View.LAYOUT_DIRECTION_RTL
|
||||||
import android.view.WindowManager
|
|
||||||
import android.view.WindowMetrics
|
import android.view.WindowMetrics
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.android.systemui.Dumpable
|
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_SEASCAPE
|
||||||
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
|
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.Rotation
|
||||||
|
import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation
|
||||||
import java.io.FileDescriptor
|
import java.io.FileDescriptor
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.lang.Math.max
|
import java.lang.Math.max
|
||||||
@@ -61,13 +61,14 @@ import javax.inject.Inject
|
|||||||
class StatusBarContentInsetsProvider @Inject constructor(
|
class StatusBarContentInsetsProvider @Inject constructor(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
val configurationController: ConfigurationController,
|
val configurationController: ConfigurationController,
|
||||||
val windowManager: WindowManager,
|
|
||||||
val dumpManager: DumpManager
|
val dumpManager: DumpManager
|
||||||
) : CallbackController<StatusBarContentInsetsChangedListener>,
|
) : CallbackController<StatusBarContentInsetsChangedListener>,
|
||||||
ConfigurationController.ConfigurationListener,
|
ConfigurationController.ConfigurationListener,
|
||||||
Dumpable {
|
Dumpable {
|
||||||
// Indexed by @Rotation
|
|
||||||
private val insetsByCorner = arrayOfNulls<Rect>(4)
|
// Limit cache size as potentially we may connect large number of displays
|
||||||
|
// (e.g. network displays)
|
||||||
|
private val insetsCache = LruCache<CacheKey, Rect>(MAX_CACHE_SIZE)
|
||||||
private val listeners = mutableSetOf<StatusBarContentInsetsChangedListener>()
|
private val listeners = mutableSetOf<StatusBarContentInsetsChangedListener>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -91,12 +92,12 @@ class StatusBarContentInsetsProvider @Inject constructor(
|
|||||||
clearCachedInsets()
|
clearCachedInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearCachedInsets() {
|
override fun onMaxBoundsChanged() {
|
||||||
insetsByCorner[0] = null
|
notifyInsetsChanged()
|
||||||
insetsByCorner[1] = null
|
}
|
||||||
insetsByCorner[2] = null
|
|
||||||
insetsByCorner[3] = null
|
|
||||||
|
|
||||||
|
private fun clearCachedInsets() {
|
||||||
|
insetsCache.evictAll()
|
||||||
notifyInsetsChanged()
|
notifyInsetsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,10 +112,10 @@ class StatusBarContentInsetsProvider @Inject constructor(
|
|||||||
* dot in the coordinates relative to the given rotation.
|
* dot in the coordinates relative to the given rotation.
|
||||||
*/
|
*/
|
||||||
fun getBoundingRectForPrivacyChipForRotation(@Rotation rotation: Int): Rect {
|
fun getBoundingRectForPrivacyChipForRotation(@Rotation rotation: Int): Rect {
|
||||||
var insets = insetsByCorner[rotation]
|
var insets = insetsCache[getCacheKey(rotation = rotation)]
|
||||||
val rotatedResources = RotationUtils.getResourcesForRotation(rotation, context)
|
val rotatedResources = getResourcesForRotation(rotation, context)
|
||||||
if (insets == null) {
|
if (insets == null) {
|
||||||
insets = getAndSetInsetsForRotation(rotation, rotatedResources)
|
insets = getStatusBarContentInsetsForRotation(rotation, rotatedResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dotWidth = rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_diameter)
|
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
|
* Calculates the necessary left and right locations for the status bar contents invariant of
|
||||||
* the current device rotation, in the target rotation's coordinates
|
* the current device rotation, in the target rotation's coordinates
|
||||||
*/
|
*/
|
||||||
fun getStatusBarContentInsetsForRotation(@Rotation rotation: Int): Rect {
|
@JvmOverloads
|
||||||
var insets = insetsByCorner[rotation]
|
fun getStatusBarContentInsetsForRotation(
|
||||||
if (insets == null) {
|
@Rotation rotation: Int,
|
||||||
val rotatedResources = RotationUtils.getResourcesForRotation(rotation, context)
|
rotatedResources: Resources = getResourcesForRotation(rotation, context)
|
||||||
insets = getAndSetInsetsForRotation(rotation, rotatedResources)
|
|
||||||
}
|
|
||||||
|
|
||||||
return insets
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAndSetInsetsForRotation(
|
|
||||||
@Rotation rot: Int,
|
|
||||||
rotatedResources: Resources
|
|
||||||
): Rect {
|
): Rect {
|
||||||
val insets = getCalculatedInsetsForRotation(rot, rotatedResources)
|
val key = getCacheKey(rotation = rotation)
|
||||||
insetsByCorner[rot] = insets
|
return insetsCache[key] ?: getCalculatedInsetsForRotation(rotation, rotatedResources)
|
||||||
|
.also {
|
||||||
return insets
|
insetsCache.put(key, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCalculatedInsetsForRotation(
|
private fun getCalculatedInsetsForRotation(
|
||||||
@@ -176,17 +169,29 @@ class StatusBarContentInsetsProvider @Inject constructor(
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowManager.maximumWindowMetrics,
|
context.resources.configuration.windowConfiguration.maxBounds,
|
||||||
rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
|
rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
|
||||||
minLeft,
|
minLeft,
|
||||||
minRight)
|
minRight)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
|
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
|
||||||
insetsByCorner.forEachIndexed { index, rect ->
|
insetsCache.snapshot().forEach { (key, rect) ->
|
||||||
pw.println("${RotationUtils.toString(index)} -> $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 {
|
interface StatusBarContentInsetsChangedListener {
|
||||||
@@ -194,10 +199,9 @@ interface StatusBarContentInsetsChangedListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private const val TAG = "StatusBarInsetsProvider"
|
private const val TAG = "StatusBarInsetsProvider"
|
||||||
|
private const val MAX_CACHE_SIZE = 16
|
||||||
|
|
||||||
private fun getRotationZeroDisplayBounds(wm: WindowMetrics, @Rotation exactRotation: Int): Rect {
|
private fun getRotationZeroDisplayBounds(bounds: Rect, @Rotation exactRotation: Int): Rect {
|
||||||
val bounds = wm.bounds
|
|
||||||
|
|
||||||
if (exactRotation == ROTATION_NONE || exactRotation == ROTATION_UPSIDE_DOWN) {
|
if (exactRotation == ROTATION_NONE || exactRotation == ROTATION_UPSIDE_DOWN) {
|
||||||
return bounds
|
return bounds
|
||||||
}
|
}
|
||||||
@@ -243,7 +247,7 @@ fun calculateInsetsForRotationWithRotatedResources(
|
|||||||
@Rotation currentRotation: Int,
|
@Rotation currentRotation: Int,
|
||||||
@Rotation targetRotation: Int,
|
@Rotation targetRotation: Int,
|
||||||
displayCutout: DisplayCutout?,
|
displayCutout: DisplayCutout?,
|
||||||
windowMetrics: WindowMetrics,
|
maxBounds: Rect,
|
||||||
statusBarHeight: Int,
|
statusBarHeight: Int,
|
||||||
minLeft: Int,
|
minLeft: Int,
|
||||||
minRight: Int
|
minRight: Int
|
||||||
@@ -254,16 +258,15 @@ fun calculateInsetsForRotationWithRotatedResources(
|
|||||||
val right = if (isRtl) paddingStart else paddingEnd
|
val right = if (isRtl) paddingStart else paddingEnd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val rotZeroBounds = getRotationZeroDisplayBounds(windowMetrics, currentRotation)
|
val rotZeroBounds = getRotationZeroDisplayBounds(maxBounds, currentRotation)
|
||||||
val currentBounds = windowMetrics.bounds
|
|
||||||
|
|
||||||
val sbLeftRight = getStatusBarLeftRight(
|
val sbLeftRight = getStatusBarLeftRight(
|
||||||
displayCutout,
|
displayCutout,
|
||||||
statusBarHeight,
|
statusBarHeight,
|
||||||
rotZeroBounds.right,
|
rotZeroBounds.right,
|
||||||
rotZeroBounds.bottom,
|
rotZeroBounds.bottom,
|
||||||
currentBounds.width(),
|
maxBounds.width(),
|
||||||
currentBounds.height(),
|
maxBounds.height(),
|
||||||
minLeft,
|
minLeft,
|
||||||
minRight,
|
minRight,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public interface ConfigurationController extends CallbackController<Configuratio
|
|||||||
default void onConfigChanged(Configuration newConfig) {}
|
default void onConfigChanged(Configuration newConfig) {}
|
||||||
default void onDensityOrFontScaleChanged() {}
|
default void onDensityOrFontScaleChanged() {}
|
||||||
default void onSmallestScreenWidthChanged() {}
|
default void onSmallestScreenWidthChanged() {}
|
||||||
|
default void onMaxBoundsChanged() {}
|
||||||
default void onOverlayChanged() {}
|
default void onOverlayChanged() {}
|
||||||
default void onUiModeChanged() {}
|
default void onUiModeChanged() {}
|
||||||
default void onThemeChanged() {}
|
default void onThemeChanged() {}
|
||||||
|
|||||||
@@ -16,32 +16,54 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.phone
|
package com.android.systemui.statusbar.phone
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.test.suitebuilder.annotation.SmallTest
|
import android.test.suitebuilder.annotation.SmallTest
|
||||||
|
import android.view.Display
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.WindowMetrics
|
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.util.leak.RotationUtils
|
import com.android.systemui.util.leak.RotationUtils
|
||||||
import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
|
import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
|
||||||
import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
|
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_SEASCAPE
|
||||||
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
|
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.Rotation
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
import junit.framework.Assert.assertTrue
|
import junit.framework.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.mockito.ArgumentMatchers.any
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.`when`
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
||||||
|
|
||||||
@Mock private lateinit var dc: DisplayCutout
|
@Mock private lateinit var dc: DisplayCutout
|
||||||
@Mock private lateinit var windowMetrics: WindowMetrics
|
@Mock private lateinit var contextMock: Context
|
||||||
|
@Mock private lateinit var display: Display
|
||||||
|
private lateinit var configurationController: ConfigurationController
|
||||||
|
|
||||||
|
private val configuration = Configuration()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
`when`(contextMock.display).thenReturn(display)
|
||||||
|
|
||||||
|
context.ensureTestableResources()
|
||||||
|
`when`(contextMock.resources).thenReturn(context.resources)
|
||||||
|
`when`(contextMock.resources.configuration).thenReturn(configuration)
|
||||||
|
`when`(contextMock.createConfigurationContext(any())).thenAnswer {
|
||||||
|
context.createConfigurationContext(it.arguments[0] as Configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
configurationController = ConfigurationControllerImpl(contextMock)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -55,15 +77,13 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
val chipWidth = 30
|
val chipWidth = 30
|
||||||
val dotWidth = 10
|
val dotWidth = 10
|
||||||
|
|
||||||
`when`(windowMetrics.bounds).thenReturn(screenBounds)
|
|
||||||
|
|
||||||
var isRtl = false
|
var isRtl = false
|
||||||
var targetRotation = ROTATION_NONE
|
var targetRotation = ROTATION_NONE
|
||||||
var bounds = calculateInsetsForRotationWithRotatedResources(
|
var bounds = calculateInsetsForRotationWithRotatedResources(
|
||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
null,
|
null,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -92,7 +112,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -127,7 +147,6 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
val sbHeightLandscape = 60
|
val sbHeightLandscape = 60
|
||||||
val currentRotation = ROTATION_NONE
|
val currentRotation = ROTATION_NONE
|
||||||
|
|
||||||
`when`(windowMetrics.bounds).thenReturn(screenBounds)
|
|
||||||
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
||||||
|
|
||||||
// THEN rotations which share a short side should use the greater value between rounded
|
// THEN rotations which share a short side should use the greater value between rounded
|
||||||
@@ -142,7 +161,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -159,7 +178,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -178,7 +197,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -196,7 +215,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -219,7 +238,6 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
val sbHeightLandscape = 60
|
val sbHeightLandscape = 60
|
||||||
val currentRotation = ROTATION_NONE
|
val currentRotation = ROTATION_NONE
|
||||||
|
|
||||||
`when`(windowMetrics.bounds).thenReturn(screenBounds)
|
|
||||||
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
||||||
|
|
||||||
// THEN only the landscape/seascape rotations should avoid the cutout area because of the
|
// THEN only the landscape/seascape rotations should avoid the cutout area because of the
|
||||||
@@ -234,7 +252,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -251,7 +269,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -268,7 +286,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -285,7 +303,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -303,8 +321,6 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
val sbHeightPortrait = 100
|
val sbHeightPortrait = 100
|
||||||
val sbHeightLandscape = 60
|
val sbHeightLandscape = 60
|
||||||
|
|
||||||
`when`(windowMetrics.bounds).thenReturn(screenBounds)
|
|
||||||
|
|
||||||
// THEN content insets should only use rounded corner padding
|
// THEN content insets should only use rounded corner padding
|
||||||
var targetRotation = ROTATION_NONE
|
var targetRotation = ROTATION_NONE
|
||||||
var expectedBounds = Rect(minLeftPadding,
|
var expectedBounds = Rect(minLeftPadding,
|
||||||
@@ -316,7 +332,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
null, /* no cutout */
|
null, /* no cutout */
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -332,7 +348,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
null, /* no cutout */
|
null, /* no cutout */
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -348,7 +364,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
null, /* no cutout */
|
null, /* no cutout */
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -364,7 +380,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
null, /* no cutout */
|
null, /* no cutout */
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightLandscape,
|
sbHeightLandscape,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -382,7 +398,6 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
val sbHeightLandscape = 60
|
val sbHeightLandscape = 60
|
||||||
val currentRotation = ROTATION_NONE
|
val currentRotation = ROTATION_NONE
|
||||||
|
|
||||||
`when`(windowMetrics.bounds).thenReturn(screenBounds)
|
|
||||||
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
`when`(dc.boundingRects).thenReturn(listOf(dcBounds))
|
||||||
|
|
||||||
// THEN left should be set to the display cutout width, and right should use the minRight
|
// THEN left should be set to the display cutout width, and right should use the minRight
|
||||||
@@ -396,7 +411,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
currentRotation,
|
currentRotation,
|
||||||
targetRotation,
|
targetRotation,
|
||||||
dc,
|
dc,
|
||||||
windowMetrics,
|
screenBounds,
|
||||||
sbHeightPortrait,
|
sbHeightPortrait,
|
||||||
minLeftPadding,
|
minLeftPadding,
|
||||||
minRightPadding)
|
minRightPadding)
|
||||||
@@ -404,6 +419,67 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
|
|||||||
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
|
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDisplayChanged_returnsUpdatedInsets() {
|
||||||
|
// GIVEN: get insets on the first display and switch to the second display
|
||||||
|
val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
|
||||||
|
mock(DumpManager::class.java))
|
||||||
|
|
||||||
|
givenDisplay(
|
||||||
|
screenBounds = Rect(0, 0, 1080, 2160),
|
||||||
|
displayUniqueId = "1"
|
||||||
|
)
|
||||||
|
val firstDisplayInsets = provider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
|
||||||
|
givenDisplay(
|
||||||
|
screenBounds = Rect(0, 0, 800, 600),
|
||||||
|
displayUniqueId = "2"
|
||||||
|
)
|
||||||
|
configurationController.onConfigurationChanged(configuration)
|
||||||
|
|
||||||
|
// WHEN: get insets on the second display
|
||||||
|
val secondDisplayInsets = provider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
|
||||||
|
|
||||||
|
// THEN: insets are updated
|
||||||
|
assertThat(firstDisplayInsets).isNotEqualTo(secondDisplayInsets)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDisplayChangedAndReturnedBack_returnsTheSameInsets() {
|
||||||
|
// GIVEN: get insets on the first display, switch to the second display,
|
||||||
|
// get insets and switch back
|
||||||
|
val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
|
||||||
|
mock(DumpManager::class.java))
|
||||||
|
givenDisplay(
|
||||||
|
screenBounds = Rect(0, 0, 1080, 2160),
|
||||||
|
displayUniqueId = "1"
|
||||||
|
)
|
||||||
|
val firstDisplayInsetsFirstCall = provider
|
||||||
|
.getStatusBarContentInsetsForRotation(ROTATION_NONE)
|
||||||
|
givenDisplay(
|
||||||
|
screenBounds = Rect(0, 0, 800, 600),
|
||||||
|
displayUniqueId = "2"
|
||||||
|
)
|
||||||
|
configurationController.onConfigurationChanged(configuration)
|
||||||
|
provider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
|
||||||
|
givenDisplay(
|
||||||
|
screenBounds = Rect(0, 0, 1080, 2160),
|
||||||
|
displayUniqueId = "1"
|
||||||
|
)
|
||||||
|
configurationController.onConfigurationChanged(configuration)
|
||||||
|
|
||||||
|
// WHEN: get insets on the first display again
|
||||||
|
val firstDisplayInsetsSecondCall = provider
|
||||||
|
.getStatusBarContentInsetsForRotation(ROTATION_NONE)
|
||||||
|
|
||||||
|
// THEN: insets for the first and second calls for the first display are the same
|
||||||
|
assertThat(firstDisplayInsetsFirstCall).isEqualTo(firstDisplayInsetsSecondCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenDisplay(screenBounds: Rect, displayUniqueId: String) {
|
||||||
|
`when`(display.uniqueId).thenReturn(displayUniqueId)
|
||||||
|
configuration.windowConfiguration.maxBounds = screenBounds
|
||||||
|
}
|
||||||
|
|
||||||
private fun assertRects(
|
private fun assertRects(
|
||||||
expected: Rect,
|
expected: Rect,
|
||||||
actual: Rect,
|
actual: Rect,
|
||||||
|
|||||||
Reference in New Issue
Block a user