/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui import android.content.Context import android.graphics.Insets import android.graphics.PixelFormat import android.graphics.Rect import android.graphics.RectF import android.hardware.graphics.common.DisplayDecorationSupport import android.view.Display import android.view.DisplayCutout import android.view.DisplayInfo import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.R import com.android.systemui.util.mockito.eq import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) @SmallTest class ScreenDecorHwcLayerTest : SysuiTestCase() { @Mock private lateinit var mockDisplay: Display @Mock private lateinit var mockRootView: View @Mock private lateinit var mockContext: Context private val displayWidth = 100 private val displayHeight = 200 private val cutoutSize = 10 private val roundedSizeTop = 15 private val roundedSizeBottom = 20 private lateinit var decorHwcLayer: ScreenDecorHwcLayer private val cutoutTop: DisplayCutout = DisplayCutout.Builder() .setSafeInsets(Insets.of(0, cutoutSize, 0, 0)) .setBoundingRectTop(Rect(1, 0, 2, cutoutSize)) .build() private val cutoutRight: DisplayCutout = DisplayCutout.Builder() .setSafeInsets(Insets.of(0, 0, cutoutSize, 0)) .setBoundingRectRight(Rect(displayWidth - cutoutSize, 50, displayWidth, 52)) .build() @Before fun setUp() { MockitoAnnotations.initMocks(this) mContext.orCreateTestableResources.addOverride( R.array.config_displayUniqueIdArray, arrayOf()) mContext.orCreateTestableResources.addOverride( R.bool.config_fillMainBuiltInDisplayCutout, true) val decorationSupport = DisplayDecorationSupport() decorationSupport.format = PixelFormat.R_8 decorHwcLayer = Mockito.spy(ScreenDecorHwcLayer(mContext, decorationSupport, /* debug */ false)) whenever(decorHwcLayer.width).thenReturn(displayWidth) whenever(decorHwcLayer.height).thenReturn(displayHeight) whenever(decorHwcLayer.context).thenReturn(mockContext) whenever(mockContext.display).thenReturn(mockDisplay) whenever(decorHwcLayer.rootView).thenReturn(mockRootView) whenever(mockRootView.left).thenReturn(0) whenever(mockRootView.top).thenReturn(0) whenever(mockRootView.right).thenReturn(displayWidth) whenever(mockRootView.bottom).thenReturn(displayHeight) } @Test fun testTransparentRegion_noCutout_noRoundedCorner_noProtection() { setupConfigs(null, false, false, 0, 0, RectF(), 0f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, 0, decorHwcLayer.width, decorHwcLayer.height)) } @Test fun testTransparentRegion_onlyShortEdgeCutout() { setupConfigs(cutoutTop, false, false, 0, 0, RectF(), 0f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, cutoutSize, decorHwcLayer.width, decorHwcLayer.height)) } @Test fun testTransparentRegion_onlyLongEdgeCutout() { setupConfigs(cutoutRight, false, false, 0, 0, RectF(), 0f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, 0, decorHwcLayer.width - cutoutSize, decorHwcLayer.height)) } @Test fun testTransparentRegion_onlyRoundedCorners() { setupConfigs(null, true, true, roundedSizeTop, roundedSizeBottom, RectF(), 0f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, roundedSizeTop, decorHwcLayer.width, decorHwcLayer.height - roundedSizeBottom)) } @Test fun testTransparentRegion_onlyCutoutProtection() { setupConfigs(null, false, false, 0, 0, RectF(48f, 1f, 52f, 5f), 0.5f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, 4, decorHwcLayer.width, decorHwcLayer.height)) decorHwcLayer.cameraProtectionProgress = 1f decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, 5, decorHwcLayer.width, decorHwcLayer.height)) } @Test fun testTransparentRegion_hasShortEdgeCutout_hasRoundedCorner_hasCutoutProtection() { setupConfigs(cutoutTop, true, true, roundedSizeTop, roundedSizeBottom, RectF(48f, 1f, 52f, 5f), 1f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(0, 15, decorHwcLayer.width, decorHwcLayer.height - 20)) } @Test fun testTransparentRegion_hasLongEdgeCutout_hasRoundedCorner_hasCutoutProtection() { setupConfigs(cutoutRight, true, true, roundedSizeTop, roundedSizeBottom, RectF(48f, 1f, 52f, 5f), 1f) decorHwcLayer.calculateTransparentRect() assertThat(decorHwcLayer.transparentRect) .isEqualTo(Rect(20, 5, decorHwcLayer.width - 20, decorHwcLayer.height)) } private fun setupConfigs( cutout: DisplayCutout?, hasRoundedTop: Boolean, hasRoundedBottom: Boolean, roundedTop: Int, roundedBottom: Int, protectionRect: RectF, protectionProgress: Float ) { whenever(mockDisplay.getDisplayInfo(eq(decorHwcLayer.displayInfo)) ).then { val info = it.getArgument(0) info.displayCutout = cutout return@then true } decorHwcLayer.updateRoundedCornerExistenceAndSize(hasRoundedTop, hasRoundedBottom, roundedTop, roundedBottom) decorHwcLayer.protectionRect.set(protectionRect) decorHwcLayer.cameraProtectionProgress = protectionProgress decorHwcLayer.updateCutout() } }