Loading packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +70 −0 Original line number Diff line number Diff line Loading @@ -29,17 +29,21 @@ import android.view.IDisplayWindowListener import android.view.mockIWindowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.app.displaylib.DisplayDecorationListener import com.android.app.displaylib.DisplayRepository.PendingDisplay import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.mockCommandQueue import com.android.systemui.testKosmos import com.android.systemui.util.mockito.kotlinArgumentCaptor import com.android.systemui.util.mockito.mock import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.TestScope Loading Loading @@ -73,6 +77,7 @@ class DisplayRepositoryTest : SysuiTestCase() { private val testHandler = kosmos.fakeHandler private val testScope = kosmos.testScope private val testDispacher = kosmos.testDispatcher private val defaultDisplay = display(type = TYPE_INTERNAL, id = DEFAULT_DISPLAY, state = Display.STATE_ON) Loading @@ -87,6 +92,10 @@ class DisplayRepositoryTest : SysuiTestCase() { } } private val displayRepositoryCompat: DisplaysWithDecorationsRepositoryCompat by lazy { kosmos.displaysWithDecorationsRepositoryCompat } @Before fun setup() { setDisplays(listOf(defaultDisplay)) Loading Loading @@ -734,6 +743,67 @@ class DisplayRepositoryTest : SysuiTestCase() { assertThat(lastDisplayIdsWithSystemDecorations).containsExactly(1) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyAddSystemDecor() = testScope.runTest { val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayAddSystemDecorations(1) verify(listener).onDisplayAddSystemDecorations(1) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyInitialDisplaysWithSysDecor() = testScope.runTest { setDisplays(0) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() verify(listener).onDisplayAddSystemDecorations(0) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyRemoveSystemDecor() = testScope.runTest { setDisplays(0) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayRemoveSystemDecorations(0) verify(listener).onDisplayAddSystemDecorations(0) verify(listener).onDisplayRemoveSystemDecorations(0) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyAllDisplaysWithSysDecor() = testScope.runTest { setDisplays(0, 2) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) whenever(windowManager.shouldShowSystemDecors(2)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayAddSystemDecorations(3) verify(listener).onDisplayAddSystemDecorations(0) verify(listener).onDisplayAddSystemDecorations(2) verify(listener).onDisplayAddSystemDecorations(3) } @Test fun getDisplay_slowMappingToDisplay_returnsRegardless() = testScope.runTest { Loading packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt +9 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.view.IWindowManager import com.android.app.displaylib.DisplayLibBackground import com.android.app.displaylib.DisplayLibComponent import com.android.app.displaylib.DisplaysWithDecorationsRepository import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.app.displaylib.PerDisplayRepository import com.android.app.displaylib.createDisplayLibComponent import com.android.systemui.CoreStartable Loading Loading @@ -159,4 +160,12 @@ object DisplayLibModule { ): DisplaysWithDecorationsRepository { return displayLibComponent.displaysWithDecorationsRepository } @Provides @SysUISingleton fun providesDisplaysWithDecorationsRepositoryCompatFromLib( displayLibComponent: DisplayLibComponent ): DisplaysWithDecorationsRepositoryCompat { return displayLibComponent.displaysWithDecorationsRepositoryCompat } } packages/SystemUI/src/com/android/systemui/display/flags/WmCallbackForSysDecorFlag.kt 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.display.flags import android.window.DesktopExperienceFlags import com.android.systemui.flags.RefactorFlagUtils import com.android.window.flags.Flags /** Helper for reading or using the enable wm callback for system decor changes flag state. */ object WmCallbackForSysDecorFlag { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM /** * When true, this is defined as [DesktopExperienceFlags] to make it possible to enable it * together with all the other desktop experience flags from the dev settings. * * Alternatively, using adb: * ```bash * adb shell setprop persist.wm.debug.desktop_experience_devopts 1 * ``` */ private const val ENABLED_BY_DESKTOP_EXPERIENCE_DEV_OPTION = false val FLAG = DesktopExperienceFlags.DesktopExperienceFlag( Flags::enableSysDecorsCallbacksViaWm, /* shouldOverrideByDevOption= */ ENABLED_BY_DESKTOP_EXPERIENCE_DEV_OPTION, Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM, ) /** Is the refactor enabled */ @JvmStatic inline val isEnabled: Boolean get() = FLAG.isTrue /** * Called to ensure code is only run when the flag is enabled. This protects users from the * unintended behaviors caused by accidentally running new logic, while also crashing on an eng * build to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun isUnexpectedlyInLegacyMode() = RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) /** * Called to ensure code is only run when the flag is disabled. This will throw an exception if * the flag is enabled to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) } packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java +42 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen; import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification; import static com.android.wm.shell.Flags.enableTaskbarOnPhones; import static com.android.window.flags.Flags.enableSysDecorsCallbacksViaWm; import android.content.Context; import android.content.pm.ActivityInfo; Loading @@ -41,6 +42,8 @@ import android.window.DesktopExperienceFlags; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.app.displaylib.DisplayDecorationListener; import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.RegisterStatusBarResult; Loading @@ -49,6 +52,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.LauncherProxyService; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.display.flags.WmCallbackForSysDecorFlag; import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.views.NavigationBar; Loading @@ -67,6 +71,8 @@ import com.android.wm.shell.pip.Pip; import dalvik.annotation.optimization.NeverCompile; import kotlinx.coroutines.CoroutineDispatcher; import java.io.PrintWriter; import java.util.Optional; import java.util.concurrent.Executor; Loading Loading @@ -132,7 +138,9 @@ public class NavigationBarControllerImpl implements Optional<BackAnimation> backAnimation, SecureSettings secureSettings, DisplayTracker displayTracker, DeviceStateManager deviceStateManager) { DeviceStateManager deviceStateManager, DisplaysWithDecorationsRepositoryCompat displaysWithDecorationsRepositoryCompat, @Main CoroutineDispatcher mainCoroutineDispatcher) { mContext = context; mExecutor = mainExecutor; mNavigationBarComponentFactory = navigationBarComponentFactory; Loading @@ -140,6 +148,10 @@ public class NavigationBarControllerImpl implements mDisplayTracker = displayTracker; mDisplayManager = mContext.getSystemService(DisplayManager.class); commandQueue.addCallback(mCommandQueueCallbacks); if (enableSysDecorsCallbacksViaWm()) { displaysWithDecorationsRepositoryCompat.registerDisplayDecorationListener( mDisplayDecorationListener, mainCoroutineDispatcher); } configurationController.addCallback(this); mConfigChanges.applyNewConfig(mContext.getResources()); mNavMode = navigationModeController.addListener(this); Loading Loading @@ -271,26 +283,23 @@ public class NavigationBarControllerImpl implements return mIsLargeScreen || (foldedOrPhone && enableTaskbarNavbarUnification()); } // TODO: b/408503553 - Remove system decor callbacks once the flag is cleaned up. private final CommandQueue.Callbacks mCommandQueueCallbacks = new CommandQueue.Callbacks() { @Override public void onDisplayRemoved(int displayId) { onDisplayRemoveSystemDecorations(displayId); mDisplayDecorationListener.onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayRemoveSystemDecorations(int displayId) { removeNavigationBar(displayId); mHasNavBar.delete(displayId); WmCallbackForSysDecorFlag.assertInLegacyMode(); mDisplayDecorationListener.onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayAddSystemDecorations(int displayId) { if (DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { mHasNavBar.put(displayId, true); } Display display = mDisplayManager.getDisplay(displayId); mIsLargeScreen = isLargeScreen(mContext); createNavigationBar(display, null /* savedState */, null /* result */); WmCallbackForSysDecorFlag.assertInLegacyMode(); mDisplayDecorationListener.onDisplayAddSystemDecorations(displayId); } @Override Loading Loading @@ -320,6 +329,29 @@ public class NavigationBarControllerImpl implements } }; private final DisplayDecorationListener mDisplayDecorationListener = new DisplayDecorationListener() { @Override public void onDisplayRemoved(int displayId) { onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayRemoveSystemDecorations(int displayId) { removeNavigationBar(displayId); mHasNavBar.delete(displayId); } @Override public void onDisplayAddSystemDecorations(int displayId) { if (DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { mHasNavBar.put(displayId, true); } Display display = mDisplayManager.getDisplay(displayId); mIsLargeScreen = isLargeScreen(mContext); createNavigationBar(display, null /* savedState */, null /* result */); }}; /** * Recreates the navigation bar for the given display. */ Loading packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java +6 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.util.SparseArray; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.systemui.LauncherProxyService; import com.android.systemui.SysuiTestCase; Loading @@ -66,6 +67,8 @@ import com.android.systemui.util.time.FakeSystemClock; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; import kotlinx.coroutines.CoroutineDispatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; Loading Loading @@ -126,7 +129,9 @@ public class NavigationBarControllerImplTest extends SysuiTestCase { Optional.of(mock(BackAnimation.class)), mock(SecureSettings.class), mDisplayTracker, mDeviceStateManager)); mDeviceStateManager, mock(DisplaysWithDecorationsRepositoryCompat.class), mock(CoroutineDispatcher.class))); initializeNavigationBars(); mMockitoSession = mockitoSession().mockStatic(Utilities.class).startMocking(); } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +70 −0 Original line number Diff line number Diff line Loading @@ -29,17 +29,21 @@ import android.view.IDisplayWindowListener import android.view.mockIWindowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.app.displaylib.DisplayDecorationListener import com.android.app.displaylib.DisplayRepository.PendingDisplay import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.mockCommandQueue import com.android.systemui.testKosmos import com.android.systemui.util.mockito.kotlinArgumentCaptor import com.android.systemui.util.mockito.mock import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.TestScope Loading Loading @@ -73,6 +77,7 @@ class DisplayRepositoryTest : SysuiTestCase() { private val testHandler = kosmos.fakeHandler private val testScope = kosmos.testScope private val testDispacher = kosmos.testDispatcher private val defaultDisplay = display(type = TYPE_INTERNAL, id = DEFAULT_DISPLAY, state = Display.STATE_ON) Loading @@ -87,6 +92,10 @@ class DisplayRepositoryTest : SysuiTestCase() { } } private val displayRepositoryCompat: DisplaysWithDecorationsRepositoryCompat by lazy { kosmos.displaysWithDecorationsRepositoryCompat } @Before fun setup() { setDisplays(listOf(defaultDisplay)) Loading Loading @@ -734,6 +743,67 @@ class DisplayRepositoryTest : SysuiTestCase() { assertThat(lastDisplayIdsWithSystemDecorations).containsExactly(1) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyAddSystemDecor() = testScope.runTest { val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayAddSystemDecorations(1) verify(listener).onDisplayAddSystemDecorations(1) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyInitialDisplaysWithSysDecor() = testScope.runTest { setDisplays(0) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() verify(listener).onDisplayAddSystemDecorations(0) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyRemoveSystemDecor() = testScope.runTest { setDisplays(0) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayRemoveSystemDecorations(0) verify(listener).onDisplayAddSystemDecorations(0) verify(listener).onDisplayRemoveSystemDecorations(0) } @Test @EnableFlags(Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM) fun displaysWithSystemDecorationsCompat_registerListener_notifyAllDisplaysWithSysDecor() = testScope.runTest { setDisplays(0, 2) whenever(windowManager.shouldShowSystemDecors(0)).thenReturn(true) whenever(windowManager.shouldShowSystemDecors(2)).thenReturn(true) val listener = mock<DisplayDecorationListener>() displayRepositoryCompat.registerDisplayDecorationListener(listener, testDispacher) captureWmListener() wmListener.onDisplayAddSystemDecorations(3) verify(listener).onDisplayAddSystemDecorations(0) verify(listener).onDisplayAddSystemDecorations(2) verify(listener).onDisplayAddSystemDecorations(3) } @Test fun getDisplay_slowMappingToDisplay_returnsRegardless() = testScope.runTest { Loading
packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt +9 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.view.IWindowManager import com.android.app.displaylib.DisplayLibBackground import com.android.app.displaylib.DisplayLibComponent import com.android.app.displaylib.DisplaysWithDecorationsRepository import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat import com.android.app.displaylib.PerDisplayRepository import com.android.app.displaylib.createDisplayLibComponent import com.android.systemui.CoreStartable Loading Loading @@ -159,4 +160,12 @@ object DisplayLibModule { ): DisplaysWithDecorationsRepository { return displayLibComponent.displaysWithDecorationsRepository } @Provides @SysUISingleton fun providesDisplaysWithDecorationsRepositoryCompatFromLib( displayLibComponent: DisplayLibComponent ): DisplaysWithDecorationsRepositoryCompat { return displayLibComponent.displaysWithDecorationsRepositoryCompat } }
packages/SystemUI/src/com/android/systemui/display/flags/WmCallbackForSysDecorFlag.kt 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.display.flags import android.window.DesktopExperienceFlags import com.android.systemui.flags.RefactorFlagUtils import com.android.window.flags.Flags /** Helper for reading or using the enable wm callback for system decor changes flag state. */ object WmCallbackForSysDecorFlag { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM /** * When true, this is defined as [DesktopExperienceFlags] to make it possible to enable it * together with all the other desktop experience flags from the dev settings. * * Alternatively, using adb: * ```bash * adb shell setprop persist.wm.debug.desktop_experience_devopts 1 * ``` */ private const val ENABLED_BY_DESKTOP_EXPERIENCE_DEV_OPTION = false val FLAG = DesktopExperienceFlags.DesktopExperienceFlag( Flags::enableSysDecorsCallbacksViaWm, /* shouldOverrideByDevOption= */ ENABLED_BY_DESKTOP_EXPERIENCE_DEV_OPTION, Flags.FLAG_ENABLE_SYS_DECORS_CALLBACKS_VIA_WM, ) /** Is the refactor enabled */ @JvmStatic inline val isEnabled: Boolean get() = FLAG.isTrue /** * Called to ensure code is only run when the flag is enabled. This protects users from the * unintended behaviors caused by accidentally running new logic, while also crashing on an eng * build to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun isUnexpectedlyInLegacyMode() = RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) /** * Called to ensure code is only run when the flag is disabled. This will throw an exception if * the flag is enabled to ensure that the refactor author catches issues in testing. */ @JvmStatic inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) }
packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java +42 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen; import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification; import static com.android.wm.shell.Flags.enableTaskbarOnPhones; import static com.android.window.flags.Flags.enableSysDecorsCallbacksViaWm; import android.content.Context; import android.content.pm.ActivityInfo; Loading @@ -41,6 +42,8 @@ import android.window.DesktopExperienceFlags; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.app.displaylib.DisplayDecorationListener; import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.RegisterStatusBarResult; Loading @@ -49,6 +52,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.LauncherProxyService; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.display.flags.WmCallbackForSysDecorFlag; import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.views.NavigationBar; Loading @@ -67,6 +71,8 @@ import com.android.wm.shell.pip.Pip; import dalvik.annotation.optimization.NeverCompile; import kotlinx.coroutines.CoroutineDispatcher; import java.io.PrintWriter; import java.util.Optional; import java.util.concurrent.Executor; Loading Loading @@ -132,7 +138,9 @@ public class NavigationBarControllerImpl implements Optional<BackAnimation> backAnimation, SecureSettings secureSettings, DisplayTracker displayTracker, DeviceStateManager deviceStateManager) { DeviceStateManager deviceStateManager, DisplaysWithDecorationsRepositoryCompat displaysWithDecorationsRepositoryCompat, @Main CoroutineDispatcher mainCoroutineDispatcher) { mContext = context; mExecutor = mainExecutor; mNavigationBarComponentFactory = navigationBarComponentFactory; Loading @@ -140,6 +148,10 @@ public class NavigationBarControllerImpl implements mDisplayTracker = displayTracker; mDisplayManager = mContext.getSystemService(DisplayManager.class); commandQueue.addCallback(mCommandQueueCallbacks); if (enableSysDecorsCallbacksViaWm()) { displaysWithDecorationsRepositoryCompat.registerDisplayDecorationListener( mDisplayDecorationListener, mainCoroutineDispatcher); } configurationController.addCallback(this); mConfigChanges.applyNewConfig(mContext.getResources()); mNavMode = navigationModeController.addListener(this); Loading Loading @@ -271,26 +283,23 @@ public class NavigationBarControllerImpl implements return mIsLargeScreen || (foldedOrPhone && enableTaskbarNavbarUnification()); } // TODO: b/408503553 - Remove system decor callbacks once the flag is cleaned up. private final CommandQueue.Callbacks mCommandQueueCallbacks = new CommandQueue.Callbacks() { @Override public void onDisplayRemoved(int displayId) { onDisplayRemoveSystemDecorations(displayId); mDisplayDecorationListener.onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayRemoveSystemDecorations(int displayId) { removeNavigationBar(displayId); mHasNavBar.delete(displayId); WmCallbackForSysDecorFlag.assertInLegacyMode(); mDisplayDecorationListener.onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayAddSystemDecorations(int displayId) { if (DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { mHasNavBar.put(displayId, true); } Display display = mDisplayManager.getDisplay(displayId); mIsLargeScreen = isLargeScreen(mContext); createNavigationBar(display, null /* savedState */, null /* result */); WmCallbackForSysDecorFlag.assertInLegacyMode(); mDisplayDecorationListener.onDisplayAddSystemDecorations(displayId); } @Override Loading Loading @@ -320,6 +329,29 @@ public class NavigationBarControllerImpl implements } }; private final DisplayDecorationListener mDisplayDecorationListener = new DisplayDecorationListener() { @Override public void onDisplayRemoved(int displayId) { onDisplayRemoveSystemDecorations(displayId); } @Override public void onDisplayRemoveSystemDecorations(int displayId) { removeNavigationBar(displayId); mHasNavBar.delete(displayId); } @Override public void onDisplayAddSystemDecorations(int displayId) { if (DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { mHasNavBar.put(displayId, true); } Display display = mDisplayManager.getDisplay(displayId); mIsLargeScreen = isLargeScreen(mContext); createNavigationBar(display, null /* savedState */, null /* result */); }}; /** * Recreates the navigation bar for the given display. */ Loading
packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java +6 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.util.SparseArray; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.app.displaylib.DisplaysWithDecorationsRepositoryCompat; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.systemui.LauncherProxyService; import com.android.systemui.SysuiTestCase; Loading @@ -66,6 +67,8 @@ import com.android.systemui.util.time.FakeSystemClock; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; import kotlinx.coroutines.CoroutineDispatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; Loading Loading @@ -126,7 +129,9 @@ public class NavigationBarControllerImplTest extends SysuiTestCase { Optional.of(mock(BackAnimation.class)), mock(SecureSettings.class), mDisplayTracker, mDeviceStateManager)); mDeviceStateManager, mock(DisplaysWithDecorationsRepositoryCompat.class), mock(CoroutineDispatcher.class))); initializeNavigationBars(); mMockitoSession = mockitoSession().mockStatic(Utilities.class).startMocking(); } Loading