Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt +54 −9 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.systemui.statusbar.core import android.platform.test.annotations.EnableFlags import android.view.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.testScope import com.android.systemui.statusbar.data.repository.fakePrivacyDotWindowControllerStore import com.android.systemui.testKosmos import com.google.common.truth.Expect import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -30,6 +32,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.never import org.mockito.kotlin.verify @OptIn(ExperimentalCoroutinesApi::class) Loading @@ -39,16 +42,12 @@ import org.mockito.kotlin.verify class MultiDisplayStatusBarStarterTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() private val kosmos = testKosmos().also { it.statusBarOrchestratorFactory = it.fakeStatusBarOrchestratorFactory it.statusBarInitializerStore = it.fakeStatusBarInitializerStore } private val kosmos = testKosmos() private val testScope = kosmos.testScope private val fakeDisplayRepository = kosmos.displayRepository private val fakeOrchestratorFactory = kosmos.fakeStatusBarOrchestratorFactory private val fakeInitializerStore = kosmos.fakeStatusBarInitializerStore private val fakePrivacyDotStore = kosmos.fakePrivacyDotWindowControllerStore // Lazy, so that @EnableFlags is set before initializer is instantiated. private val underTest by lazy { kosmos.multiDisplayStatusBarStarter } Loading Loading @@ -82,6 +81,31 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 2)!!).start() } @Test fun start_startsPrivacyDotForCurrentDisplays() = testScope.runTest { fakeDisplayRepository.addDisplay(displayId = 1) fakeDisplayRepository.addDisplay(displayId = 2) underTest.start() runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 1)).start() verify(fakePrivacyDotStore.forDisplay(displayId = 2)).start() } @Test fun start_doesNotStartPrivacyDotForDefaultDisplay() = testScope.runTest { fakeDisplayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY) underTest.start() runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = Display.DEFAULT_DISPLAY), never()) .start() } @Test fun displayAdded_orchestratorForNewDisplayIsStarted() = testScope.runTest { Loading @@ -108,6 +132,18 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { .isTrue() } @Test fun displayAdded_privacyDotForNewDisplayIsStarted() = testScope.runTest { underTest.start() runCurrent() fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start() } @Test fun displayAddedDuringStart_initializerForNewDisplayIsStarted() = testScope.runTest { Loading @@ -129,8 +165,17 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() expect .that(fakeInitializerStore.forDisplay(displayId = 3).startedByCoreStartable) .isTrue() verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 3)!!).start() } @Test fun displayAddedDuringStart_privacyDotForNewDisplayIsStarted() = testScope.runTest { underTest.start() fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start() } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStoreImplTest.kt 0 → 100644 +54 −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.platform.test.annotations.EnableFlags import android.view.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.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.testKosmos import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class PrivacyDotWindowControllerStoreImplTest : SysuiTestCase() { private val kosmos = testKosmos() private val underTest by lazy { kosmos.privacyDotWindowControllerStoreImpl } @Before fun installDisplays() = runBlocking { kosmos.displayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY) kosmos.displayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY + 1) } @Test(expected = IllegalArgumentException::class) fun forDisplay_defaultDisplay_throws() { underTest.forDisplay(displayId = Display.DEFAULT_DISPLAY) } @Test fun forDisplay_nonDefaultDisplay_doesNotThrow() { underTest.forDisplay(displayId = Display.DEFAULT_DISPLAY + 1) } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt 0 → 100644 +73 −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.platform.test.annotations.EnableFlags 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.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.core.StatusBarConnectedDisplays 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) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class SystemEventChipAnimationControllerStoreImplTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val fakeDisplayRepository = kosmos.displayRepository // Lazy so that @EnableFlags has time to run before underTest is instantiated. private val underTest by lazy { kosmos.systemEventChipAnimationControllerStoreImpl } @Before fun start() { underTest.start() } @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) } @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() } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationControllerTest.kt 0 → 100644 +108 −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.events import android.platform.test.annotations.EnableFlags import androidx.core.animation.AnimatorSet import androidx.core.animation.ValueAnimator 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.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.statusbar.data.repository.systemEventChipAnimationControllerStore import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class MultiDisplaySystemEventChipAnimationControllerTest : SysuiTestCase() { private val kosmos = testKosmos() private val displayRepository = kosmos.displayRepository private val store = kosmos.systemEventChipAnimationControllerStore // Lazy so that @EnableFlags has time to switch the flags before the instance is created. private val underTest by lazy { kosmos.multiDisplaySystemEventChipAnimationController } @Before fun installDisplays() = runBlocking { INSTALLED_DISPLAY_IDS.forEach { displayRepository.addDisplay(displayId = it) } } @Test fun init_forwardsToAllControllers() { underTest.init() INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).init() } } @Test fun stop_forwardsToAllControllers() { underTest.stop() INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).stop() } } @Test fun announceForAccessibility_forwardsToAllControllers() { val contentDescription = "test content description" underTest.announceForAccessibility(contentDescription) INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).announceForAccessibility(contentDescription) } } @Test fun onSystemEventAnimationBegin_returnsAnimatorSetWithOneAnimatorPerDisplay() { INSTALLED_DISPLAY_IDS.forEach { val controller = store.forDisplay(it) whenever(controller.onSystemEventAnimationBegin()).thenReturn(ValueAnimator.ofInt(0, 1)) } val animator = underTest.onSystemEventAnimationBegin() as AnimatorSet assertThat(animator.childAnimations).hasSize(INSTALLED_DISPLAY_IDS.size) } @Test fun onSystemEventAnimationFinish_returnsAnimatorSetWithOneAnimatorPerDisplay() { INSTALLED_DISPLAY_IDS.forEach { val controller = store.forDisplay(it) whenever(controller.onSystemEventAnimationFinish(any())) .thenReturn(ValueAnimator.ofInt(0, 1)) } val animator = underTest.onSystemEventAnimationFinish(hasPersistentDot = true) as AnimatorSet assertThat(animator.childAnimations).hasSize(INSTALLED_DISPLAY_IDS.size) } companion object { private const val DISPLAY_ID_1 = 123 private const val DISPLAY_ID_2 = 456 private val INSTALLED_DISPLAY_IDS = listOf(DISPLAY_ID_1, DISPLAY_ID_2) } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotWindowControllerTest.kt 0 → 100644 +185 −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.events import android.view.Gravity.BOTTOM import android.view.Gravity.LEFT import android.view.Gravity.RIGHT import android.view.Gravity.TOP import android.view.Surface import android.view.View import android.view.WindowManager import android.view.fakeWindowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.res.R import com.android.systemui.testKosmos import com.google.common.truth.Expect import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) class PrivacyDotWindowControllerTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() private val kosmos = testKosmos() private val underTest = kosmos.privacyDotWindowController private val viewController = kosmos.privacyDotViewController private val windowManager = kosmos.fakeWindowManager private val executor = kosmos.fakeExecutor @After fun cleanUpCustomDisplay() { context.display = null } @Test fun start_beforeUiThreadExecutes_doesNotAddWindows() { underTest.start() assertThat(windowManager.addedViews).isEmpty() } @Test fun start_beforeUiThreadExecutes_doesNotInitializeViewController() { underTest.start() assertThat(viewController.isInitialized).isFalse() } @Test fun start_afterUiThreadExecutes_addsWindowsOnUiThread() { underTest.start() executor.runAllReady() assertThat(windowManager.addedViews).hasSize(4) } @Test fun start_afterUiThreadExecutes_initializesViewController() { underTest.start() executor.runAllReady() assertThat(viewController.isInitialized).isTrue() } @Test fun start_initializesTopLeft() { underTest.start() executor.runAllReady() assertThat(viewController.topLeft?.id).isEqualTo(R.id.privacy_dot_top_left_container) } @Test fun start_initializesTopRight() { underTest.start() executor.runAllReady() assertThat(viewController.topRight?.id).isEqualTo(R.id.privacy_dot_top_right_container) } @Test fun start_initializesTopBottomLeft() { underTest.start() executor.runAllReady() assertThat(viewController.bottomLeft?.id).isEqualTo(R.id.privacy_dot_bottom_left_container) } @Test fun start_initializesBottomRight() { underTest.start() executor.runAllReady() assertThat(viewController.bottomRight?.id) .isEqualTo(R.id.privacy_dot_bottom_right_container) } @Test fun start_viewsAddedInRespectiveCorners() { context.display = mock { on { rotation } doReturn Surface.ROTATION_0 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(BOTTOM or RIGHT) } @Test fun start_rotation90_viewsPositionIsShifted90degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_90 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(TOP or RIGHT) } @Test fun start_rotation180_viewsPositionIsShifted180degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_180 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(TOP or LEFT) } @Test fun start_rotation270_viewsPositionIsShifted270degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_270 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(BOTTOM or LEFT) } private fun paramsForView(view: View): WindowManager.LayoutParams { return windowManager.addedViews.entries .first { it.key == view || it.key.findViewById<View>(view.id) != null } .value } private fun gravityForView(view: View): Int { return paramsForView(view).gravity } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarterTest.kt +54 −9 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.systemui.statusbar.core import android.platform.test.annotations.EnableFlags import android.view.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.testScope import com.android.systemui.statusbar.data.repository.fakePrivacyDotWindowControllerStore import com.android.systemui.testKosmos import com.google.common.truth.Expect import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -30,6 +32,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.never import org.mockito.kotlin.verify @OptIn(ExperimentalCoroutinesApi::class) Loading @@ -39,16 +42,12 @@ import org.mockito.kotlin.verify class MultiDisplayStatusBarStarterTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() private val kosmos = testKosmos().also { it.statusBarOrchestratorFactory = it.fakeStatusBarOrchestratorFactory it.statusBarInitializerStore = it.fakeStatusBarInitializerStore } private val kosmos = testKosmos() private val testScope = kosmos.testScope private val fakeDisplayRepository = kosmos.displayRepository private val fakeOrchestratorFactory = kosmos.fakeStatusBarOrchestratorFactory private val fakeInitializerStore = kosmos.fakeStatusBarInitializerStore private val fakePrivacyDotStore = kosmos.fakePrivacyDotWindowControllerStore // Lazy, so that @EnableFlags is set before initializer is instantiated. private val underTest by lazy { kosmos.multiDisplayStatusBarStarter } Loading Loading @@ -82,6 +81,31 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 2)!!).start() } @Test fun start_startsPrivacyDotForCurrentDisplays() = testScope.runTest { fakeDisplayRepository.addDisplay(displayId = 1) fakeDisplayRepository.addDisplay(displayId = 2) underTest.start() runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 1)).start() verify(fakePrivacyDotStore.forDisplay(displayId = 2)).start() } @Test fun start_doesNotStartPrivacyDotForDefaultDisplay() = testScope.runTest { fakeDisplayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY) underTest.start() runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = Display.DEFAULT_DISPLAY), never()) .start() } @Test fun displayAdded_orchestratorForNewDisplayIsStarted() = testScope.runTest { Loading @@ -108,6 +132,18 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { .isTrue() } @Test fun displayAdded_privacyDotForNewDisplayIsStarted() = testScope.runTest { underTest.start() runCurrent() fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start() } @Test fun displayAddedDuringStart_initializerForNewDisplayIsStarted() = testScope.runTest { Loading @@ -129,8 +165,17 @@ class MultiDisplayStatusBarStarterTest : SysuiTestCase() { fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() expect .that(fakeInitializerStore.forDisplay(displayId = 3).startedByCoreStartable) .isTrue() verify(fakeOrchestratorFactory.createdOrchestratorForDisplay(displayId = 3)!!).start() } @Test fun displayAddedDuringStart_privacyDotForNewDisplayIsStarted() = testScope.runTest { underTest.start() fakeDisplayRepository.addDisplay(displayId = 3) runCurrent() verify(fakePrivacyDotStore.forDisplay(displayId = 3)).start() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStoreImplTest.kt 0 → 100644 +54 −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.platform.test.annotations.EnableFlags import android.view.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.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.testKosmos import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class PrivacyDotWindowControllerStoreImplTest : SysuiTestCase() { private val kosmos = testKosmos() private val underTest by lazy { kosmos.privacyDotWindowControllerStoreImpl } @Before fun installDisplays() = runBlocking { kosmos.displayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY) kosmos.displayRepository.addDisplay(displayId = Display.DEFAULT_DISPLAY + 1) } @Test(expected = IllegalArgumentException::class) fun forDisplay_defaultDisplay_throws() { underTest.forDisplay(displayId = Display.DEFAULT_DISPLAY) } @Test fun forDisplay_nonDefaultDisplay_doesNotThrow() { underTest.forDisplay(displayId = Display.DEFAULT_DISPLAY + 1) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt 0 → 100644 +73 −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.platform.test.annotations.EnableFlags 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.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.core.StatusBarConnectedDisplays 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) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class SystemEventChipAnimationControllerStoreImplTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val fakeDisplayRepository = kosmos.displayRepository // Lazy so that @EnableFlags has time to run before underTest is instantiated. private val underTest by lazy { kosmos.systemEventChipAnimationControllerStoreImpl } @Before fun start() { underTest.start() } @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) } @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() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationControllerTest.kt 0 → 100644 +108 −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.events import android.platform.test.annotations.EnableFlags import androidx.core.animation.AnimatorSet import androidx.core.animation.ValueAnimator 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.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.statusbar.data.repository.systemEventChipAnimationControllerStore import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) class MultiDisplaySystemEventChipAnimationControllerTest : SysuiTestCase() { private val kosmos = testKosmos() private val displayRepository = kosmos.displayRepository private val store = kosmos.systemEventChipAnimationControllerStore // Lazy so that @EnableFlags has time to switch the flags before the instance is created. private val underTest by lazy { kosmos.multiDisplaySystemEventChipAnimationController } @Before fun installDisplays() = runBlocking { INSTALLED_DISPLAY_IDS.forEach { displayRepository.addDisplay(displayId = it) } } @Test fun init_forwardsToAllControllers() { underTest.init() INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).init() } } @Test fun stop_forwardsToAllControllers() { underTest.stop() INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).stop() } } @Test fun announceForAccessibility_forwardsToAllControllers() { val contentDescription = "test content description" underTest.announceForAccessibility(contentDescription) INSTALLED_DISPLAY_IDS.forEach { verify(store.forDisplay(it)).announceForAccessibility(contentDescription) } } @Test fun onSystemEventAnimationBegin_returnsAnimatorSetWithOneAnimatorPerDisplay() { INSTALLED_DISPLAY_IDS.forEach { val controller = store.forDisplay(it) whenever(controller.onSystemEventAnimationBegin()).thenReturn(ValueAnimator.ofInt(0, 1)) } val animator = underTest.onSystemEventAnimationBegin() as AnimatorSet assertThat(animator.childAnimations).hasSize(INSTALLED_DISPLAY_IDS.size) } @Test fun onSystemEventAnimationFinish_returnsAnimatorSetWithOneAnimatorPerDisplay() { INSTALLED_DISPLAY_IDS.forEach { val controller = store.forDisplay(it) whenever(controller.onSystemEventAnimationFinish(any())) .thenReturn(ValueAnimator.ofInt(0, 1)) } val animator = underTest.onSystemEventAnimationFinish(hasPersistentDot = true) as AnimatorSet assertThat(animator.childAnimations).hasSize(INSTALLED_DISPLAY_IDS.size) } companion object { private const val DISPLAY_ID_1 = 123 private const val DISPLAY_ID_2 = 456 private val INSTALLED_DISPLAY_IDS = listOf(DISPLAY_ID_1, DISPLAY_ID_2) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotWindowControllerTest.kt 0 → 100644 +185 −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.events import android.view.Gravity.BOTTOM import android.view.Gravity.LEFT import android.view.Gravity.RIGHT import android.view.Gravity.TOP import android.view.Surface import android.view.View import android.view.WindowManager import android.view.fakeWindowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.res.R import com.android.systemui.testKosmos import com.google.common.truth.Expect import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) class PrivacyDotWindowControllerTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() private val kosmos = testKosmos() private val underTest = kosmos.privacyDotWindowController private val viewController = kosmos.privacyDotViewController private val windowManager = kosmos.fakeWindowManager private val executor = kosmos.fakeExecutor @After fun cleanUpCustomDisplay() { context.display = null } @Test fun start_beforeUiThreadExecutes_doesNotAddWindows() { underTest.start() assertThat(windowManager.addedViews).isEmpty() } @Test fun start_beforeUiThreadExecutes_doesNotInitializeViewController() { underTest.start() assertThat(viewController.isInitialized).isFalse() } @Test fun start_afterUiThreadExecutes_addsWindowsOnUiThread() { underTest.start() executor.runAllReady() assertThat(windowManager.addedViews).hasSize(4) } @Test fun start_afterUiThreadExecutes_initializesViewController() { underTest.start() executor.runAllReady() assertThat(viewController.isInitialized).isTrue() } @Test fun start_initializesTopLeft() { underTest.start() executor.runAllReady() assertThat(viewController.topLeft?.id).isEqualTo(R.id.privacy_dot_top_left_container) } @Test fun start_initializesTopRight() { underTest.start() executor.runAllReady() assertThat(viewController.topRight?.id).isEqualTo(R.id.privacy_dot_top_right_container) } @Test fun start_initializesTopBottomLeft() { underTest.start() executor.runAllReady() assertThat(viewController.bottomLeft?.id).isEqualTo(R.id.privacy_dot_bottom_left_container) } @Test fun start_initializesBottomRight() { underTest.start() executor.runAllReady() assertThat(viewController.bottomRight?.id) .isEqualTo(R.id.privacy_dot_bottom_right_container) } @Test fun start_viewsAddedInRespectiveCorners() { context.display = mock { on { rotation } doReturn Surface.ROTATION_0 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(BOTTOM or RIGHT) } @Test fun start_rotation90_viewsPositionIsShifted90degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_90 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(TOP or RIGHT) } @Test fun start_rotation180_viewsPositionIsShifted180degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_180 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(BOTTOM or LEFT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(TOP or LEFT) } @Test fun start_rotation270_viewsPositionIsShifted270degrees() { context.display = mock { on { rotation } doReturn Surface.ROTATION_270 } underTest.start() executor.runAllReady() expect.that(gravityForView(viewController.topLeft!!)).isEqualTo(TOP or RIGHT) expect.that(gravityForView(viewController.topRight!!)).isEqualTo(BOTTOM or RIGHT) expect.that(gravityForView(viewController.bottomLeft!!)).isEqualTo(TOP or LEFT) expect.that(gravityForView(viewController.bottomRight!!)).isEqualTo(BOTTOM or LEFT) } private fun paramsForView(view: View): WindowManager.LayoutParams { return windowManager.addedViews.entries .first { it.key == view || it.key.findViewById<View>(view.id) != null } .value } private fun gravityForView(view: View): Int { return paramsForView(view).gravity } }