Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 613c82b4 authored by Chris Göllner's avatar Chris Göllner
Browse files

Introduce StatusBarContentInsetsProviderStore for multiple displays

Test: Tested by parent abstract class
Test: MultiDisplayStatusBarContentInsetsProviderStoreTest
Test: StatusBarContentInsetsProviderTest
Test: Build & run
Flag: com.android.systemui.status_bar_connected_displays
Bug: 362720432
Change-Id: Ib08054879f6b714d640e22153cf7d77aae3a0ef9
parent 3d454fb1
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -6,12 +6,11 @@ import android.graphics.Rect
import android.view.DisplayCutout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.res.R
import com.android.systemui.statusbar.data.repository.fakeStatusBarContentInsetsProviderStore
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
@@ -19,6 +18,8 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnit
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -35,9 +36,12 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
        const val QS_END_FRAME = 58
    }

    private val kosmos = testKosmos()
    private val insetsProviderStore = kosmos.fakeStatusBarContentInsetsProviderStore
    private val insetsProvider = insetsProviderStore.defaultDisplay

    @JvmField @Rule val mockitoRule = MockitoJUnit.rule()!!

    @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
    @Mock private lateinit var mockedContext: Context
    @Mock private lateinit var mockedResources: Resources

@@ -49,8 +53,7 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
        whenever(mockedResources.getInteger(R.integer.fade_in_start_frame)).thenReturn(QS_END_FRAME)
        whenever(mockedResources.getInteger(R.integer.fade_out_complete_frame))
            .thenReturn(QQS_START_FRAME)

        controller = QsBatteryModeController(mockedContext, insetsProvider)
        controller = QsBatteryModeController(mockedContext, insetsProviderStore)
    }

    @Test
@@ -96,5 +99,6 @@ class QsBatteryModeControllerTest : SysuiTestCase() {
    }

    private fun Int.prevFrameToFraction(): Float = (this - 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()

    private fun Int.nextFrameToFraction(): Float = (this + 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()
}
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.statusbar.data.repository

import android.view.Display.DEFAULT_DISPLAY
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.unconfinedTestDispatcher
import com.android.systemui.testKosmos
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.never
import org.mockito.kotlin.verify

@SmallTest
@RunWith(AndroidJUnit4::class)
class MultiDisplayStatusBarContentInsetsProviderStoreTest : SysuiTestCase() {

    private val kosmos = testKosmos().also { it.testDispatcher = it.unconfinedTestDispatcher }
    private val testScope = kosmos.testScope
    private val fakeDisplayRepository = kosmos.displayRepository
    private val underTest = kosmos.multiDisplayStatusBarContentInsetsProviderStore

    @Before
    fun start() {
        underTest.start()
    }

    @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) }

    @Test
    fun forDisplay_startsInstances() =
        testScope.runTest {
            val instance = underTest.forDisplay(DEFAULT_DISPLAY)

            verify(instance).start()
        }

    @Test
    fun beforeDisplayRemoved_doesNotStopInstances() =
        testScope.runTest {
            val instance = underTest.forDisplay(DEFAULT_DISPLAY)

            verify(instance, never()).stop()
        }

    @Test
    fun displayRemoved_stopsInstance() =
        testScope.runTest {
            val instance = underTest.forDisplay(DEFAULT_DISPLAY)

            fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY)

            verify(instance).stop()
        }
}
+6 −2
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeViewStateProvider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
import com.android.systemui.statusbar.phone.ui.TintedIconManager;
@@ -119,6 +120,8 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
    @Mock
    private StatusBarContentInsetsProvider mStatusBarContentInsetsProvider;
    @Mock
    private StatusBarContentInsetsProviderStore mStatusBarContentInsetsProviderStore;
    @Mock
    private UserManager mUserManager;
    @Mock
    private StatusBarUserChipViewModel mStatusBarUserChipViewModel;
@@ -143,7 +146,8 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
        mShadeViewStateProvider = new TestShadeViewStateProvider();

        MockitoAnnotations.initMocks(this);

        when(mStatusBarContentInsetsProviderStore.getDefaultDisplay())
                .thenReturn(mStatusBarContentInsetsProvider);
        when(mIconManagerFactory.create(any(), any())).thenReturn(mIconManager);

        allowTestableLooperAsMainThread();
@@ -175,7 +179,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
                mKosmos.getKeyguardStatusBarViewModel(),
                mBiometricUnlockController,
                mStatusBarStateController,
                mStatusBarContentInsetsProvider,
                mStatusBarContentInsetsProviderStore,
                mUserManager,
                mStatusBarUserChipViewModel,
                mSecureSettings,
+104 −14
Original line number Diff line number Diff line
@@ -36,14 +36,15 @@ 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.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertTrue
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@RunWith(AndroidJUnit4::class)
@SmallTest
@@ -1018,7 +1019,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {

    // Regression test for b/245799099
    @Test
    fun onMaxBoundsChanged_listenerNotified() {
    fun onMaxBoundsChanged_afterStart_listenerNotified() {
        // Start out with an existing configuration with bounds
        configuration.windowConfiguration.setMaxBounds(0, 0, 100, 100)
        configurationController.onConfigurationChanged(configuration)
@@ -1038,6 +1039,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
                    triggered = true
                }
            }
        provider.start()
        provider.addCallback(listener)

        // WHEN the config is updated with new bounds
@@ -1049,7 +1051,68 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    }

    @Test
    fun onDensityOrFontScaleChanged_listenerNotified() {
    fun onMaxBoundsChanged_beforeStart_listenerNotNotified() {
        // Start out with an existing configuration with bounds
        configuration.windowConfiguration.setMaxBounds(0, 0, 100, 100)
        configurationController.onConfigurationChanged(configuration)
        val provider =
            StatusBarContentInsetsProviderImpl(
                contextMock,
                configurationController,
                mock<DumpManager>(),
                mock<CommandRegistry>(),
                mock<SysUICutoutProvider>(),
            )
        val listener =
            object : StatusBarContentInsetsChangedListener {
                var triggered = false

                override fun onStatusBarContentInsetsChanged() {
                    triggered = true
                }
            }
        provider.addCallback(listener)

        // WHEN the config is updated with new bounds
        // but provider is not started
        configuration.windowConfiguration.setMaxBounds(0, 0, 456, 789)
        configurationController.onConfigurationChanged(configuration)

        // THEN the listener is not notified
        assertThat(listener.triggered).isFalse()
    }

    @Test
    fun onDensityOrFontScaleChanged_beforeStart_listenerNotNotified() {
        configuration.densityDpi = 12
        val provider =
            StatusBarContentInsetsProviderImpl(
                contextMock,
                configurationController,
                mock<DumpManager>(),
                mock<CommandRegistry>(),
                mock<SysUICutoutProvider>(),
            )
        val listener =
            object : StatusBarContentInsetsChangedListener {
                var triggered = false

                override fun onStatusBarContentInsetsChanged() {
                    triggered = true
                }
            }
        provider.addCallback(listener)

        // WHEN the config is updated, but the provider is not started
        configuration.densityDpi = 20
        configurationController.onConfigurationChanged(configuration)

        // THEN the listener is NOT notified
        assertThat(listener.triggered).isFalse()
    }

    @Test
    fun onDensityOrFontScaleChanged_afterStart_listenerNotified() {
        configuration.densityDpi = 12
        val provider =
            StatusBarContentInsetsProviderImpl(
@@ -1067,6 +1130,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
                    triggered = true
                }
            }
        provider.start()
        provider.addCallback(listener)

        // WHEN the config is updated
@@ -1078,7 +1142,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    }

    @Test
    fun onThemeChanged_listenerNotified() {
    fun onThemeChanged_afterStart_listenerNotified() {
        val provider =
            StatusBarContentInsetsProviderImpl(
                contextMock,
@@ -1095,6 +1159,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
                    triggered = true
                }
            }
        provider.start()
        provider.addCallback(listener)

        configurationController.notifyThemeChanged()
@@ -1103,18 +1168,44 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
        assertThat(listener.triggered).isTrue()
    }

    @Test
    fun onThemeChanged_beforeStart_listenerNotNotified() {
        val provider =
            StatusBarContentInsetsProviderImpl(
                contextMock,
                configurationController,
                mock<DumpManager>(),
                mock<CommandRegistry>(),
                mock<SysUICutoutProvider>(),
            )
        val listener =
            object : StatusBarContentInsetsChangedListener {
                var triggered = false

                override fun onStatusBarContentInsetsChanged() {
                    triggered = true
                }
            }
        provider.addCallback(listener)

        configurationController.notifyThemeChanged()

        assertThat(listener.triggered).isFalse()
    }

    private fun assertRects(
        expected: Rect,
        actual: Rect,
        @Rotation currentRotation: Int,
        @Rotation targetRotation: Int,
    ) {
        assertTrue(
        assertWithMessage(
                "Rects must match. currentRotation=${RotationUtils.toString(currentRotation)}" +
                    " targetRotation=${RotationUtils.toString(targetRotation)}" +
                " expected=$expected actual=$actual",
            expected.equals(actual),
                    " expected=$expected actual=$actual"
            )
            .that(actual)
            .isEqualTo(expected)
    }

    private fun setNoCutout() {
@@ -1136,8 +1227,7 @@ class StatusBarContentInsetsProviderTest : SysuiTestCase() {
    }

    private fun setCameraProtectionBounds(protectionBounds: Rect) {
        val protectionInfo =
            mock<CameraProtectionInfo> { whenever(this.bounds).thenReturn(protectionBounds) }
        val protectionInfo = mock<CameraProtectionInfo> { on { bounds } doReturn protectionBounds }
        whenever(sysUICutout.cameraProtection).thenReturn(protectionInfo)
    }

+1 −1
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ abstract class PerDisplayStoreImpl<T>(
        }
    }

    abstract fun createInstanceForDisplay(displayId: Int): T
    protected abstract fun createInstanceForDisplay(displayId: Int): T

    override fun start() {
        val instanceType = instanceClass.simpleName
Loading