diff options
4 files changed, 77 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java index 8bd8098b6be9..27e6e0997c89 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java @@ -55,8 +55,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; /** * Implementation of {@link SettingsProvider} that reads the base settings provided in a display @@ -152,19 +154,35 @@ class DisplayWindowSettingsProvider implements SettingsProvider { /** * Removes display override settings that are no longer associated with active displays. - * This is necessary because displays can be dynamically added or removed during - * the system's lifecycle (e.g., user switch, system server restart). + * <p> + * This cleanup process is essential due to the dynamic nature of displays, which can + * be added or removed during various system events such as user switching or + * system server restarts. * - * @param root The root window container used to obtain the currently active displays. + * @param wms the WindowManagerService instance for retrieving all possible {@link DisplayInfo} + * for the given logical display. + * @param root the root window container used to obtain the currently active displays. */ - void removeStaleDisplaySettings(@NonNull RootWindowContainer root) { + void removeStaleDisplaySettingsLocked(@NonNull WindowManagerService wms, + @NonNull RootWindowContainer root) { if (!Flags.perUserDisplayWindowSettings()) { return; } final Set<String> displayIdentifiers = new ArraySet<>(); + final Consumer<DisplayInfo> addDisplayIdentifier = + displayInfo -> displayIdentifiers.add(mOverrideSettings.getIdentifier(displayInfo)); root.forAllDisplays(dc -> { - final String identifier = mOverrideSettings.getIdentifier(dc.getDisplayInfo()); - displayIdentifiers.add(identifier); + // Begin with the current display's information. Note that the display layout of the + // current device state might not include this display (e.g., external or virtual + // displays), resulting in empty possible display info. + addDisplayIdentifier.accept(dc.getDisplayInfo()); + + // Then, add all possible display information for this display if available. + final List<DisplayInfo> displayInfos = wms.getPossibleDisplayInfoLocked(dc.mDisplayId); + final int size = displayInfos.size(); + for (int i = 0; i < size; i++) { + addDisplayIdentifier.accept(displayInfos.get(i)); + } }); mOverrideSettings.removeStaleDisplaySettings(displayIdentifiers); } diff --git a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java index e3a2065838d1..6e8797791c97 100644 --- a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java +++ b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java @@ -57,7 +57,7 @@ public class PossibleDisplayInfoMapper { * Returns, for the given displayId, a list of unique display infos. List contains each * supported device state. * <p>List contents are guaranteed to be unique, but returned as a list rather than a set to - * minimize copies needed to make an iteraable data structure. + * minimize copies needed to make an iterable data structure. */ public List<DisplayInfo> getPossibleDisplayInfos(int displayId) { // Update display infos before returning, since any cached values would have been removed diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4db62478f76e..549c0aef2f56 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3750,7 +3750,7 @@ public class WindowManagerService extends IWindowManager.Stub } mCurrentUserId = newUserId; mDisplayWindowSettingsProvider.setOverrideSettingsForUser(newUserId); - mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); + mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); mPolicy.setCurrentUserLw(newUserId); mKeyguardDisableHandler.setCurrentUser(newUserId); @@ -5491,7 +5491,7 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked); // Per-user display settings may leave outdated settings after user switches, especially // during reboots starting with the default user without setCurrentUser called. - mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); + mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java index 3fcf3042ab94..2e0d4d46ec05 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java @@ -24,12 +24,15 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.eq; import static org.testng.Assert.assertFalse; import android.annotation.Nullable; @@ -58,6 +61,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.function.Consumer; /** @@ -352,20 +356,58 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { } @Test - public void testRemovesStaleDisplaySettings() { + public void testRemovesStaleDisplaySettings_defaultDisplay_removesStaleDisplaySettings() { assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings()); - final DisplayWindowSettingsProvider provider = - new DisplayWindowSettingsProvider(mDefaultVendorSettingsStorage, - mOverrideSettingsStorage); - final DisplayInfo displayInfo = mSecondaryDisplay.getDisplayInfo(); - updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 356); + // Write density setting for second display then remove it. + final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( + mDefaultVendorSettingsStorage, mOverrideSettingsStorage); + final DisplayInfo secDisplayInfo = mSecondaryDisplay.getDisplayInfo(); + updateOverrideSettings(provider, secDisplayInfo, setting -> setting.mForcedDensity = 356); mRootWindowContainer.removeChild(mSecondaryDisplay); - provider.removeStaleDisplaySettings(mRootWindowContainer); + // Write density setting for inner and outer default display. + final DisplayInfo innerDisplayInfo = mPrimaryDisplay.getDisplayInfo(); + final DisplayInfo outerDisplayInfo = new DisplayInfo(secDisplayInfo); + outerDisplayInfo.displayId = mPrimaryDisplay.mDisplayId; + outerDisplayInfo.uniqueId = "TEST_OUTER_DISPLAY_" + System.currentTimeMillis(); + updateOverrideSettings(provider, innerDisplayInfo, setting -> setting.mForcedDensity = 490); + updateOverrideSettings(provider, outerDisplayInfo, setting -> setting.mForcedDensity = 420); + final List<DisplayInfo> possibleDisplayInfos = List.of(innerDisplayInfo, outerDisplayInfo); + doReturn(possibleDisplayInfos) + .when(mWm).getPossibleDisplayInfoLocked(eq(innerDisplayInfo.displayId)); + + provider.removeStaleDisplaySettingsLocked(mWm, mRootWindowContainer); + + assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); + assertThat(provider.getOverrideSettingsSize()).isEqualTo(2); + assertThat(provider.getOverrideSettings(innerDisplayInfo).mForcedDensity).isEqualTo(490); + assertThat(provider.getOverrideSettings(outerDisplayInfo).mForcedDensity).isEqualTo(420); + } + + @Test + public void testRemovesStaleDisplaySettings_displayNotInLayout_keepsDisplaySettings() { + assumeTrue(com.android.window.flags.Flags.perUserDisplayWindowSettings()); + + // Write density setting for primary display. + final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( + mDefaultVendorSettingsStorage, mOverrideSettingsStorage); + final DisplayInfo primDisplayInfo = mPrimaryDisplay.getDisplayInfo(); + updateOverrideSettings(provider, primDisplayInfo, setting -> setting.mForcedDensity = 420); + + // Add a virtual display and write density setting for it. + final DisplayInfo virtDisplayInfo = new DisplayInfo(primDisplayInfo); + virtDisplayInfo.uniqueId = "TEST_VIRTUAL_DISPLAY_" + System.currentTimeMillis(); + createNewDisplay(virtDisplayInfo); + waitUntilHandlersIdle(); // Wait until unfrozen after a display is added. + updateOverrideSettings(provider, virtDisplayInfo, setting -> setting.mForcedDensity = 490); + + provider.removeStaleDisplaySettingsLocked(mWm, mRootWindowContainer); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); - assertThat(provider.getOverrideSettingsSize()).isEqualTo(0); + assertThat(provider.getOverrideSettingsSize()).isEqualTo(2); + assertThat(provider.getOverrideSettings(primDisplayInfo).mForcedDensity).isEqualTo(420); + assertThat(provider.getOverrideSettings(virtDisplayInfo).mForcedDensity).isEqualTo(490); } /** |