Loading core/java/android/window/flags/windowing_sdk.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -181,3 +181,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { namespace: "windowing_sdk" name: "per_user_display_window_settings" description: "Whether to store display window settings per user to avoid conflicts" bug: "346668297" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +62 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.os.UserHandle.USER_SYSTEM; import static android.view.Display.TYPE_VIRTUAL; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; Loading @@ -27,6 +28,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.WindowConfiguration; import android.os.Environment; import android.util.ArrayMap; Loading @@ -42,6 +44,7 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.wm.DisplayWindowSettings.SettingsProvider; import com.android.window.flags.Flags; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading @@ -53,6 +56,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import java.util.Set; /** * Implementation of {@link SettingsProvider} that reads the base settings provided in a display Loading Loading @@ -91,11 +95,11 @@ class DisplayWindowSettingsProvider implements SettingsProvider { @NonNull private ReadableSettings mBaseSettings; @NonNull private final WritableSettings mOverrideSettings; private WritableSettings mOverrideSettings; DisplayWindowSettingsProvider() { this(new AtomicFileStorage(getVendorSettingsFile()), new AtomicFileStorage(getOverrideSettingsFile())); new AtomicFileStorage(getOverrideSettingsFileForUser(USER_SYSTEM))); } @VisibleForTesting Loading Loading @@ -133,6 +137,48 @@ class DisplayWindowSettingsProvider implements SettingsProvider { mBaseSettings = new ReadableSettings(baseSettingsStorage); } /** * Overrides the storage that should be used to save override settings for a user. * * @see #DATA_DISPLAY_SETTINGS_FILE_PATH */ void setOverrideSettingsForUser(@UserIdInt int userId) { if (!Flags.perUserDisplayWindowSettings()) { return; } final AtomicFile settingsFile = getOverrideSettingsFileForUser(userId); setOverrideSettingsStorage(new AtomicFileStorage(settingsFile)); } /** * 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). * * @param root The root window container used to obtain the currently active displays. */ void removeStaleDisplaySettings(@NonNull RootWindowContainer root) { if (!Flags.perUserDisplayWindowSettings()) { return; } final Set<String> displayIdentifiers = new ArraySet<>(); root.forAllDisplays(dc -> { final String identifier = mOverrideSettings.getIdentifier(dc.getDisplayInfo()); displayIdentifiers.add(identifier); }); mOverrideSettings.removeStaleDisplaySettings(displayIdentifiers); } /** * Overrides the storage that should be used to save override settings. * * @see #setOverrideSettingsForUser(int) */ @VisibleForTesting void setOverrideSettingsStorage(@NonNull WritableSettingsStorage overrideSettingsStorage) { mOverrideSettings = new WritableSettings(overrideSettingsStorage); } @Override @NonNull public SettingsEntry getSettings(@NonNull DisplayInfo info) { Loading Loading @@ -302,6 +348,12 @@ class DisplayWindowSettingsProvider implements SettingsProvider { mVirtualDisplayIdentifiers.remove(identifier); } void removeStaleDisplaySettings(@NonNull Set<String> currentDisplayIdentifiers) { if (mSettings.retainAll(currentDisplayIdentifiers)) { writeSettings(); } } private void writeSettings() { final FileData fileData = new FileData(); fileData.mIdentifierType = mIdentifierType; Loading Loading @@ -332,9 +384,14 @@ class DisplayWindowSettingsProvider implements SettingsProvider { } @NonNull private static AtomicFile getOverrideSettingsFile() { final File overrideSettingsFile = new File(Environment.getDataDirectory(), DATA_DISPLAY_SETTINGS_FILE_PATH); private static AtomicFile getOverrideSettingsFileForUser(@UserIdInt int userId) { final File directory; if (userId == USER_SYSTEM || !Flags.perUserDisplayWindowSettings()) { directory = Environment.getDataDirectory(); } else { directory = Environment.getDataSystemCeDirectory(userId); } final File overrideSettingsFile = new File(directory, DATA_DISPLAY_SETTINGS_FILE_PATH); return new AtomicFile(overrideSettingsFile, WM_DISPLAY_COMMIT_TAG); } Loading services/core/java/com/android/server/wm/WindowManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -3743,6 +3743,8 @@ public class WindowManagerService extends IWindowManager.Stub null /* trigger */, null /* remote */, null /* disp */); } mCurrentUserId = newUserId; mDisplayWindowSettingsProvider.setOverrideSettingsForUser(newUserId); mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); mPolicy.setCurrentUserLw(newUserId); mKeyguardDisableHandler.setCurrentUser(newUserId); Loading Loading @@ -5479,6 +5481,9 @@ public class WindowManagerService extends IWindowManager.Stub // DisplayWindowSettings are applied. In addition, wide-color/hdr/isTouchDevice also // affect the Configuration. 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); } } Loading services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +89 −33 Original line number Diff line number Diff line Loading @@ -24,9 +24,12 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 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.testng.Assert.assertFalse; import android.annotation.Nullable; Loading Loading @@ -55,6 +58,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.function.Consumer; /** * Tests for the {@link DisplayWindowSettingsProvider} class. Loading Loading @@ -128,9 +132,8 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Update settings with new value, should trigger write to injector. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(mPrimaryDisplayInfo); overrideSettings.mForcedDensity = 200; provider.updateOverrideSettings(mPrimaryDisplayInfo, overrideSettings); updateOverrideSettings(provider, mPrimaryDisplayInfo, overrideSettings -> overrideSettings.mForcedDensity = 200); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that display identifier was updated. Loading Loading @@ -167,7 +170,7 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { } @Test public void testReadingDisplaySettingsFromStorage_secondayVendorDisplaySettingsLocation() { public void testReadingDisplaySettingsFromStorage_secondaryVendorDisplaySettingsLocation() { final String displayIdentifier = mSecondaryDisplay.getDisplayInfo().uniqueId; prepareSecondaryDisplaySettings(displayIdentifier); Loading Loading @@ -216,11 +219,11 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Write some settings to storage. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { overrideSettings.mShouldShowSystemDecors = true; overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; overrideSettings.mDontMoveToTop = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that settings were stored correctly. Loading @@ -234,6 +237,29 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { getStoredDisplayAttributeValue(mOverrideSettingsStorage, "dontMoveToTop")); } @Test public void testWritingDisplaySettingsToStorage_secondaryUserDisplaySettingsLocation() { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final DisplayInfo displayInfo = mPrimaryDisplay.getDisplayInfo(); final TestStorage secondaryUserOverrideSettingsStorage = new TestStorage(); final SettingsEntry expectedSettings = new SettingsEntry(); expectedSettings.mForcedDensity = 356; // Write some settings to storage from default user. updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 356); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); // Now switch to secondary user override settings and write some settings. provider.setOverrideSettingsStorage(secondaryUserOverrideSettingsStorage); updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 420); assertThat(secondaryUserOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); // Switch back to primary and assert default user settings remain unchanged. provider.setOverrideSettingsStorage(mOverrideSettingsStorage); assertThat(provider.getOverrideSettings(displayInfo)).isEqualTo(expectedSettings); } @Test public void testDoNotWriteVirtualDisplaySettingsToStorage() throws Exception { final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); Loading @@ -242,11 +268,11 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // No write to storage on virtual display change. final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final SettingsEntry virtualSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, virtualSettings -> { virtualSettings.mShouldShowSystemDecors = true; virtualSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; virtualSettings.mDontMoveToTop = true; provider.updateOverrideSettings(secondaryDisplayInfo, virtualSettings); }); assertFalse(mOverrideSettingsStorage.wasWriteSuccessful()); } Loading @@ -263,10 +289,10 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Write some settings to storage. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { overrideSettings.mShouldShowSystemDecors = true; overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that settings were stored correctly. Loading @@ -283,16 +309,16 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final int initialSize = provider.getOverrideSettingsSize(); // Size + 1 when query for a new display. final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); final SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { // Size + 1 when query for a new display. assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); // When a display is removed, its override Settings is not removed if there is any override. // When a display is removed, its override Settings is not removed if there is any // override. overrideSettings.mShouldShowSystemDecors = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); provider.onDisplayRemoved(secondaryDisplayInfo); assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); Loading @@ -309,23 +335,53 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final int initialSize = provider.getOverrideSettingsSize(); // Size + 1 when query for a new display. final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); secondaryDisplayInfo.type = TYPE_VIRTUAL; final SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { // Size + 1 when query for a new display. assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); // When a virtual display is removed, its override Settings is removed even if it has // override. // When a virtual display is removed, its override Settings is removed // even if it has override. overrideSettings.mShouldShowSystemDecors = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); provider.onDisplayRemoved(secondaryDisplayInfo); assertEquals(initialSize, provider.getOverrideSettingsSize()); } @Test public void testRemovesStaleDisplaySettings() { 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); mRootWindowContainer.removeChild(mSecondaryDisplay); provider.removeStaleDisplaySettings(mRootWindowContainer); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); assertThat(provider.getOverrideSettingsSize()).isEqualTo(0); } /** * Updates the override settings for a specific display. * * @param provider the provider to obtain and update the settings from. * @param displayInfo the information about the display to be updated. * @param modifier a function that modifies the settings for the display. */ private static void updateOverrideSettings(DisplayWindowSettingsProvider provider, DisplayInfo displayInfo, Consumer<SettingsEntry> modifier) { final SettingsEntry settings = provider.getOverrideSettings(displayInfo); modifier.accept(settings); provider.updateOverrideSettings(displayInfo, settings); } /** * Prepares display settings and stores in {@link #mOverrideSettingsStorage}. Uses provided * display identifier and stores windowingMode=WINDOWING_MODE_PINNED. Loading Loading
core/java/android/window/flags/windowing_sdk.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -181,3 +181,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { namespace: "windowing_sdk" name: "per_user_display_window_settings" description: "Whether to store display window settings per user to avoid conflicts" bug: "346668297" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } }
services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +62 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.os.UserHandle.USER_SYSTEM; import static android.view.Display.TYPE_VIRTUAL; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; Loading @@ -27,6 +28,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.WindowConfiguration; import android.os.Environment; import android.util.ArrayMap; Loading @@ -42,6 +44,7 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.wm.DisplayWindowSettings.SettingsProvider; import com.android.window.flags.Flags; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading @@ -53,6 +56,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import java.util.Set; /** * Implementation of {@link SettingsProvider} that reads the base settings provided in a display Loading Loading @@ -91,11 +95,11 @@ class DisplayWindowSettingsProvider implements SettingsProvider { @NonNull private ReadableSettings mBaseSettings; @NonNull private final WritableSettings mOverrideSettings; private WritableSettings mOverrideSettings; DisplayWindowSettingsProvider() { this(new AtomicFileStorage(getVendorSettingsFile()), new AtomicFileStorage(getOverrideSettingsFile())); new AtomicFileStorage(getOverrideSettingsFileForUser(USER_SYSTEM))); } @VisibleForTesting Loading Loading @@ -133,6 +137,48 @@ class DisplayWindowSettingsProvider implements SettingsProvider { mBaseSettings = new ReadableSettings(baseSettingsStorage); } /** * Overrides the storage that should be used to save override settings for a user. * * @see #DATA_DISPLAY_SETTINGS_FILE_PATH */ void setOverrideSettingsForUser(@UserIdInt int userId) { if (!Flags.perUserDisplayWindowSettings()) { return; } final AtomicFile settingsFile = getOverrideSettingsFileForUser(userId); setOverrideSettingsStorage(new AtomicFileStorage(settingsFile)); } /** * 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). * * @param root The root window container used to obtain the currently active displays. */ void removeStaleDisplaySettings(@NonNull RootWindowContainer root) { if (!Flags.perUserDisplayWindowSettings()) { return; } final Set<String> displayIdentifiers = new ArraySet<>(); root.forAllDisplays(dc -> { final String identifier = mOverrideSettings.getIdentifier(dc.getDisplayInfo()); displayIdentifiers.add(identifier); }); mOverrideSettings.removeStaleDisplaySettings(displayIdentifiers); } /** * Overrides the storage that should be used to save override settings. * * @see #setOverrideSettingsForUser(int) */ @VisibleForTesting void setOverrideSettingsStorage(@NonNull WritableSettingsStorage overrideSettingsStorage) { mOverrideSettings = new WritableSettings(overrideSettingsStorage); } @Override @NonNull public SettingsEntry getSettings(@NonNull DisplayInfo info) { Loading Loading @@ -302,6 +348,12 @@ class DisplayWindowSettingsProvider implements SettingsProvider { mVirtualDisplayIdentifiers.remove(identifier); } void removeStaleDisplaySettings(@NonNull Set<String> currentDisplayIdentifiers) { if (mSettings.retainAll(currentDisplayIdentifiers)) { writeSettings(); } } private void writeSettings() { final FileData fileData = new FileData(); fileData.mIdentifierType = mIdentifierType; Loading Loading @@ -332,9 +384,14 @@ class DisplayWindowSettingsProvider implements SettingsProvider { } @NonNull private static AtomicFile getOverrideSettingsFile() { final File overrideSettingsFile = new File(Environment.getDataDirectory(), DATA_DISPLAY_SETTINGS_FILE_PATH); private static AtomicFile getOverrideSettingsFileForUser(@UserIdInt int userId) { final File directory; if (userId == USER_SYSTEM || !Flags.perUserDisplayWindowSettings()) { directory = Environment.getDataDirectory(); } else { directory = Environment.getDataSystemCeDirectory(userId); } final File overrideSettingsFile = new File(directory, DATA_DISPLAY_SETTINGS_FILE_PATH); return new AtomicFile(overrideSettingsFile, WM_DISPLAY_COMMIT_TAG); } Loading
services/core/java/com/android/server/wm/WindowManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -3743,6 +3743,8 @@ public class WindowManagerService extends IWindowManager.Stub null /* trigger */, null /* remote */, null /* disp */); } mCurrentUserId = newUserId; mDisplayWindowSettingsProvider.setOverrideSettingsForUser(newUserId); mDisplayWindowSettingsProvider.removeStaleDisplaySettings(mRoot); mPolicy.setCurrentUserLw(newUserId); mKeyguardDisableHandler.setCurrentUser(newUserId); Loading Loading @@ -5479,6 +5481,9 @@ public class WindowManagerService extends IWindowManager.Stub // DisplayWindowSettings are applied. In addition, wide-color/hdr/isTouchDevice also // affect the Configuration. 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); } } Loading
services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +89 −33 Original line number Diff line number Diff line Loading @@ -24,9 +24,12 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 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.testng.Assert.assertFalse; import android.annotation.Nullable; Loading Loading @@ -55,6 +58,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.function.Consumer; /** * Tests for the {@link DisplayWindowSettingsProvider} class. Loading Loading @@ -128,9 +132,8 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Update settings with new value, should trigger write to injector. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(mPrimaryDisplayInfo); overrideSettings.mForcedDensity = 200; provider.updateOverrideSettings(mPrimaryDisplayInfo, overrideSettings); updateOverrideSettings(provider, mPrimaryDisplayInfo, overrideSettings -> overrideSettings.mForcedDensity = 200); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that display identifier was updated. Loading Loading @@ -167,7 +170,7 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { } @Test public void testReadingDisplaySettingsFromStorage_secondayVendorDisplaySettingsLocation() { public void testReadingDisplaySettingsFromStorage_secondaryVendorDisplaySettingsLocation() { final String displayIdentifier = mSecondaryDisplay.getDisplayInfo().uniqueId; prepareSecondaryDisplaySettings(displayIdentifier); Loading Loading @@ -216,11 +219,11 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Write some settings to storage. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { overrideSettings.mShouldShowSystemDecors = true; overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; overrideSettings.mDontMoveToTop = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that settings were stored correctly. Loading @@ -234,6 +237,29 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { getStoredDisplayAttributeValue(mOverrideSettingsStorage, "dontMoveToTop")); } @Test public void testWritingDisplaySettingsToStorage_secondaryUserDisplaySettingsLocation() { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final DisplayInfo displayInfo = mPrimaryDisplay.getDisplayInfo(); final TestStorage secondaryUserOverrideSettingsStorage = new TestStorage(); final SettingsEntry expectedSettings = new SettingsEntry(); expectedSettings.mForcedDensity = 356; // Write some settings to storage from default user. updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 356); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); // Now switch to secondary user override settings and write some settings. provider.setOverrideSettingsStorage(secondaryUserOverrideSettingsStorage); updateOverrideSettings(provider, displayInfo, settings -> settings.mForcedDensity = 420); assertThat(secondaryUserOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); // Switch back to primary and assert default user settings remain unchanged. provider.setOverrideSettingsStorage(mOverrideSettingsStorage); assertThat(provider.getOverrideSettings(displayInfo)).isEqualTo(expectedSettings); } @Test public void testDoNotWriteVirtualDisplaySettingsToStorage() throws Exception { final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); Loading @@ -242,11 +268,11 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // No write to storage on virtual display change. final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final SettingsEntry virtualSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, virtualSettings -> { virtualSettings.mShouldShowSystemDecors = true; virtualSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; virtualSettings.mDontMoveToTop = true; provider.updateOverrideSettings(secondaryDisplayInfo, virtualSettings); }); assertFalse(mOverrideSettingsStorage.wasWriteSuccessful()); } Loading @@ -263,10 +289,10 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { // Write some settings to storage. DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { overrideSettings.mShouldShowSystemDecors = true; overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); // Verify that settings were stored correctly. Loading @@ -283,16 +309,16 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final int initialSize = provider.getOverrideSettingsSize(); // Size + 1 when query for a new display. final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); final SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { // Size + 1 when query for a new display. assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); // When a display is removed, its override Settings is not removed if there is any override. // When a display is removed, its override Settings is not removed if there is any // override. overrideSettings.mShouldShowSystemDecors = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); provider.onDisplayRemoved(secondaryDisplayInfo); assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); Loading @@ -309,23 +335,53 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { final DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider( mDefaultVendorSettingsStorage, mOverrideSettingsStorage); final int initialSize = provider.getOverrideSettingsSize(); // Size + 1 when query for a new display. final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo(); secondaryDisplayInfo.type = TYPE_VIRTUAL; final SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); updateOverrideSettings(provider, secondaryDisplayInfo, overrideSettings -> { // Size + 1 when query for a new display. assertEquals(initialSize + 1, provider.getOverrideSettingsSize()); // When a virtual display is removed, its override Settings is removed even if it has // override. // When a virtual display is removed, its override Settings is removed // even if it has override. overrideSettings.mShouldShowSystemDecors = true; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); }); provider.onDisplayRemoved(secondaryDisplayInfo); assertEquals(initialSize, provider.getOverrideSettingsSize()); } @Test public void testRemovesStaleDisplaySettings() { 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); mRootWindowContainer.removeChild(mSecondaryDisplay); provider.removeStaleDisplaySettings(mRootWindowContainer); assertThat(mOverrideSettingsStorage.wasWriteSuccessful()).isTrue(); assertThat(provider.getOverrideSettingsSize()).isEqualTo(0); } /** * Updates the override settings for a specific display. * * @param provider the provider to obtain and update the settings from. * @param displayInfo the information about the display to be updated. * @param modifier a function that modifies the settings for the display. */ private static void updateOverrideSettings(DisplayWindowSettingsProvider provider, DisplayInfo displayInfo, Consumer<SettingsEntry> modifier) { final SettingsEntry settings = provider.getOverrideSettings(displayInfo); modifier.accept(settings); provider.updateOverrideSettings(displayInfo, settings); } /** * Prepares display settings and stores in {@link #mOverrideSettingsStorage}. Uses provided * display identifier and stores windowingMode=WINDOWING_MODE_PINNED. Loading