Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt 0 → 100644 +70 −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.window 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.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 MultiDisplayStatusBarWindowControllerStoreTest : SysuiTestCase() { private val kosmos = testKosmos() private val fakeDisplayRepository = kosmos.displayRepository private val testScope = kosmos.testScope private val underTest by lazy { kosmos.multiDisplayStatusBarWindowControllerStore } @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/window/StatusBarWindowControllerImplTest.kt +68 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.systemui.statusbar.window import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags 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.fragments.fragmentService import com.android.systemui.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.statusbar.core.StatusBarRootModernization import com.android.systemui.statusbar.policy.statusBarConfigurationController import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any Loading @@ -37,6 +42,9 @@ class StatusBarWindowControllerImplTest : SysuiTestCase() { testKosmos().also { it.statusBarWindowViewInflater = it.fakeStatusBarWindowViewInflater } private val underTest = kosmos.statusBarWindowControllerImpl private val fakeExecutor = kosmos.fakeExecutor private val fakeWindowManager = kosmos.fakeWindowManager private val mockFragmentService = kosmos.fragmentService private val fakeStatusBarWindowViewInflater = kosmos.fakeStatusBarWindowViewInflater private val statusBarConfigurationController = kosmos.statusBarConfigurationController Loading @@ -59,4 +67,64 @@ class StatusBarWindowControllerImplTest : SysuiTestCase() { verify(mockWindowView, never()).setStatusBarConfigurationController(any()) } @Test @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagEnabled_doesNotRemoveFragment() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() fakeExecutor.runAllReady() verify(mockFragmentService, never()).removeAndDestroy(windowView) } @Test @DisableFlags(StatusBarRootModernization.FLAG_NAME) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagDisabled_removesFragment() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() fakeExecutor.runAllReady() verify(mockFragmentService).removeAndDestroy(windowView) } @Test @DisableFlags(StatusBarRootModernization.FLAG_NAME) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagDisabled_removesFragmentOnExecutor() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() verify(mockFragmentService, never()).removeAndDestroy(windowView) fakeExecutor.runAllReady() verify(mockFragmentService).removeAndDestroy(windowView) } @Test @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_removesWindowViewFromWindowManager() { underTest.attach() underTest.stop() assertThat(fakeWindowManager.addedViews).isEmpty() } @Test(expected = IllegalStateException::class) @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_connectedDisplaysFlagDisabled_crashes() { underTest.stop() } @Test fun attach_windowViewAddedToWindowManager() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.attach() assertThat(fakeWindowManager.addedViews.keys).containsExactly(windowView) } } packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.kt +4 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ interface StatusBarWindowController { /** Adds the status bar view to the window manager. */ fun attach() /** Called when work should stop and resources should be released. */ fun stop() /** Adds the given view to the status bar window view. */ fun addViewToWindow(view: View, layoutParams: ViewGroup.LayoutParams) Loading Loading @@ -78,7 +81,7 @@ interface StatusBarWindowController { */ fun setOngoingProcessRequiresStatusBarVisible(visible: Boolean) interface Factory { fun interface Factory { fun create( context: Context, viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager, Loading packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java +20 −1 Original line number Diff line number Diff line Loading @@ -51,10 +51,12 @@ import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.animation.ActivityTransitionAnimator; import com.android.systemui.animation.DelegateTransitionAnimatorController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.res.R; import com.android.systemui.statusbar.core.StatusBarConnectedDisplays; import com.android.systemui.statusbar.core.StatusBarRootModernization; import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider; import com.android.systemui.statusbar.window.StatusBarWindowModule.InternalWindowViewInflater; Loading @@ -66,6 +68,7 @@ import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import java.util.Optional; import java.util.concurrent.Executor; /** * Encapsulates all logic for the status bar window state management. Loading @@ -79,6 +82,7 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController private final StatusBarConfigurationController mStatusBarConfigurationController; private final IWindowManager mIWindowManager; private final StatusBarContentInsetsProvider mContentInsetsProvider; private final Executor mMainExecutor; private int mBarHeight = -1; private final State mCurrentState = new State(); private boolean mIsAttached; Loading @@ -101,12 +105,14 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController IWindowManager iWindowManager, @Assisted StatusBarContentInsetsProvider contentInsetsProvider, FragmentService fragmentService, Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider) { Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider, @Main Executor mainExecutor) { mContext = context; mWindowManager = viewCaptureAwareWindowManager; mStatusBarConfigurationController = statusBarConfigurationController; mIWindowManager = iWindowManager; mContentInsetsProvider = contentInsetsProvider; mMainExecutor = mainExecutor; mStatusBarWindowView = statusBarWindowViewInflater.inflate(context); mFragmentService = fragmentService; mLaunchAnimationContainer = mStatusBarWindowView.findViewById( Loading Loading @@ -166,6 +172,19 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController apply(mCurrentState); } @Override public void stop() { StatusBarConnectedDisplays.assertInNewMode(); mWindowManager.removeView(mStatusBarWindowView); if (StatusBarRootModernization.isEnabled()) { return; } // Fragment transactions need to happen on the main thread. mMainExecutor.execute(() -> mFragmentService.removeAndDestroy(mStatusBarWindowView)); } @Override public void addViewToWindow(@NonNull View view, @NonNull ViewGroup.LayoutParams layoutParams) { mStatusBarWindowView.addView(view, layoutParams); Loading packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt +4 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,10 @@ constructor( ) } override suspend fun onDisplayRemovalAction(instance: StatusBarWindowController) { instance.stop() } override val instanceClass = StatusBarWindowController::class.java } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt 0 → 100644 +70 −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.window 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.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 MultiDisplayStatusBarWindowControllerStoreTest : SysuiTestCase() { private val kosmos = testKosmos() private val fakeDisplayRepository = kosmos.displayRepository private val testScope = kosmos.testScope private val underTest by lazy { kosmos.multiDisplayStatusBarWindowControllerStore } @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/window/StatusBarWindowControllerImplTest.kt +68 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.systemui.statusbar.window import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags 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.fragments.fragmentService import com.android.systemui.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.statusbar.core.StatusBarRootModernization import com.android.systemui.statusbar.policy.statusBarConfigurationController import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any Loading @@ -37,6 +42,9 @@ class StatusBarWindowControllerImplTest : SysuiTestCase() { testKosmos().also { it.statusBarWindowViewInflater = it.fakeStatusBarWindowViewInflater } private val underTest = kosmos.statusBarWindowControllerImpl private val fakeExecutor = kosmos.fakeExecutor private val fakeWindowManager = kosmos.fakeWindowManager private val mockFragmentService = kosmos.fragmentService private val fakeStatusBarWindowViewInflater = kosmos.fakeStatusBarWindowViewInflater private val statusBarConfigurationController = kosmos.statusBarConfigurationController Loading @@ -59,4 +67,64 @@ class StatusBarWindowControllerImplTest : SysuiTestCase() { verify(mockWindowView, never()).setStatusBarConfigurationController(any()) } @Test @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagEnabled_doesNotRemoveFragment() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() fakeExecutor.runAllReady() verify(mockFragmentService, never()).removeAndDestroy(windowView) } @Test @DisableFlags(StatusBarRootModernization.FLAG_NAME) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagDisabled_removesFragment() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() fakeExecutor.runAllReady() verify(mockFragmentService).removeAndDestroy(windowView) } @Test @DisableFlags(StatusBarRootModernization.FLAG_NAME) @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_statusBarModernizationFlagDisabled_removesFragmentOnExecutor() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.stop() verify(mockFragmentService, never()).removeAndDestroy(windowView) fakeExecutor.runAllReady() verify(mockFragmentService).removeAndDestroy(windowView) } @Test @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_removesWindowViewFromWindowManager() { underTest.attach() underTest.stop() assertThat(fakeWindowManager.addedViews).isEmpty() } @Test(expected = IllegalStateException::class) @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME) fun stop_connectedDisplaysFlagDisabled_crashes() { underTest.stop() } @Test fun attach_windowViewAddedToWindowManager() { val windowView = fakeStatusBarWindowViewInflater.inflatedMockViews.first() underTest.attach() assertThat(fakeWindowManager.addedViews.keys).containsExactly(windowView) } }
packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.kt +4 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ interface StatusBarWindowController { /** Adds the status bar view to the window manager. */ fun attach() /** Called when work should stop and resources should be released. */ fun stop() /** Adds the given view to the status bar window view. */ fun addViewToWindow(view: View, layoutParams: ViewGroup.LayoutParams) Loading Loading @@ -78,7 +81,7 @@ interface StatusBarWindowController { */ fun setOngoingProcessRequiresStatusBarVisible(visible: Boolean) interface Factory { fun interface Factory { fun create( context: Context, viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager, Loading
packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java +20 −1 Original line number Diff line number Diff line Loading @@ -51,10 +51,12 @@ import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.animation.ActivityTransitionAnimator; import com.android.systemui.animation.DelegateTransitionAnimatorController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.res.R; import com.android.systemui.statusbar.core.StatusBarConnectedDisplays; import com.android.systemui.statusbar.core.StatusBarRootModernization; import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider; import com.android.systemui.statusbar.window.StatusBarWindowModule.InternalWindowViewInflater; Loading @@ -66,6 +68,7 @@ import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import java.util.Optional; import java.util.concurrent.Executor; /** * Encapsulates all logic for the status bar window state management. Loading @@ -79,6 +82,7 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController private final StatusBarConfigurationController mStatusBarConfigurationController; private final IWindowManager mIWindowManager; private final StatusBarContentInsetsProvider mContentInsetsProvider; private final Executor mMainExecutor; private int mBarHeight = -1; private final State mCurrentState = new State(); private boolean mIsAttached; Loading @@ -101,12 +105,14 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController IWindowManager iWindowManager, @Assisted StatusBarContentInsetsProvider contentInsetsProvider, FragmentService fragmentService, Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider) { Optional<UnfoldTransitionProgressProvider> unfoldTransitionProgressProvider, @Main Executor mainExecutor) { mContext = context; mWindowManager = viewCaptureAwareWindowManager; mStatusBarConfigurationController = statusBarConfigurationController; mIWindowManager = iWindowManager; mContentInsetsProvider = contentInsetsProvider; mMainExecutor = mainExecutor; mStatusBarWindowView = statusBarWindowViewInflater.inflate(context); mFragmentService = fragmentService; mLaunchAnimationContainer = mStatusBarWindowView.findViewById( Loading Loading @@ -166,6 +172,19 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController apply(mCurrentState); } @Override public void stop() { StatusBarConnectedDisplays.assertInNewMode(); mWindowManager.removeView(mStatusBarWindowView); if (StatusBarRootModernization.isEnabled()) { return; } // Fragment transactions need to happen on the main thread. mMainExecutor.execute(() -> mFragmentService.removeAndDestroy(mStatusBarWindowView)); } @Override public void addViewToWindow(@NonNull View view, @NonNull ViewGroup.LayoutParams layoutParams) { mStatusBarWindowView.addView(view, layoutParams); Loading
packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt +4 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,10 @@ constructor( ) } override suspend fun onDisplayRemovalAction(instance: StatusBarWindowController) { instance.stop() } override val instanceClass = StatusBarWindowController::class.java } Loading