diff options
| author | 2022-12-06 18:57:47 +0000 | |
|---|---|---|
| committer | 2023-01-17 17:30:03 +0000 | |
| commit | bc04d3cf0d2b8a16d39b12267cd95009f8e85ada (patch) | |
| tree | 4d794a0f84dcc3561a7ad2a08ecfd617e0708fbb | |
| parent | f1f50ee221a3cdb296493d652059a27a1683553d (diff) | |
Set display size to all displays
- get all displays from display manager
- loop and store the density values indexed by unique ID
- if DisplayContent isn't available for a display, fall back to DisplayInfo
Bug: 197730930
Test: Open Settings, go to Display -> Display size and text -> Display size, change the value, fold/unfold the device, see that the value persists.
Test: atest DisplayContentTests
Test: atest DisplayWindowSettingsTests
Test: atest WindowManagerServiceTests
Change-Id: I3d6858a9b20798c2ad3b12a66db3484491682691
Merged-In: I3d6858a9b20798c2ad3b12a66db3484491682691
7 files changed, 217 insertions, 116 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java index 44a37f4ccaca..d4d2b48fcc04 100644 --- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java @@ -18,6 +18,7 @@ package com.android.settingslib.display; import android.content.Context; import android.content.res.Resources; +import android.hardware.display.DisplayManager; import android.os.AsyncTask; import android.os.RemoteException; import android.os.UserHandle; @@ -32,6 +33,9 @@ import android.view.WindowManagerGlobal; import com.android.settingslib.R; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; /** * Utility methods for working with display density. @@ -70,120 +74,169 @@ public class DisplayDensityUtils { */ private static final int MIN_DIMENSION_DP = 320; - private final String[] mEntries; - private final int[] mValues; + private static final Predicate<DisplayInfo> INTERNAL_ONLY = + (info) -> info.type == Display.TYPE_INTERNAL; - private final int mDefaultDensity; - private final int mCurrentIndex; + private final Predicate<DisplayInfo> mPredicate; + + private final DisplayManager mDisplayManager; + + /** + * The text description of the density values of the default display. + */ + private String[] mDefaultDisplayDensityEntries; + + /** + * The density values of the default display. + */ + private int[] mDefaultDisplayDensityValues; + + /** + * The density values, indexed by display unique ID. + */ + private final Map<String, int[]> mValuesPerDisplay = new HashMap(); + + private int mDefaultDensityForDefaultDisplay; + private int mCurrentIndex = -1; public DisplayDensityUtils(Context context) { - final int defaultDensity = DisplayDensityUtils.getDefaultDisplayDensity( - Display.DEFAULT_DISPLAY); - if (defaultDensity <= 0) { - mEntries = null; - mValues = null; - mDefaultDensity = 0; - mCurrentIndex = -1; - return; - } + this(context, INTERNAL_ONLY); + } + + /** + * Creates an instance that stores the density values for the displays that satisfy + * the predicate. + * @param context The context + * @param predicate Determines what displays the density should be set for. The default display + * must satisfy this predicate. + */ + public DisplayDensityUtils(Context context, Predicate predicate) { + mPredicate = predicate; + mDisplayManager = context.getSystemService(DisplayManager.class); - final Resources res = context.getResources(); - DisplayInfo info = new DisplayInfo(); - context.getDisplayNoVerify().getDisplayInfo(info); - - final int currentDensity = info.logicalDensityDpi; - int currentDensityIndex = -1; - - // Compute number of "larger" and "smaller" scales for this display. - final int minDimensionPx = Math.min(info.logicalWidth, info.logicalHeight); - final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP; - final float maxScaleDimen = context.getResources().getFraction( - R.fraction.display_density_max_scale, 1, 1); - final float maxScale = Math.min(maxScaleDimen, maxDensity / (float) defaultDensity); - final float minScale = context.getResources().getFraction( - R.fraction.display_density_min_scale, 1, 1); - final float minScaleInterval = context.getResources().getFraction( - R.fraction.display_density_min_scale_interval, 1, 1); - final int numLarger = (int) MathUtils.constrain((maxScale - 1) / minScaleInterval, - 0, SUMMARIES_LARGER.length); - final int numSmaller = (int) MathUtils.constrain((1 - minScale) / minScaleInterval, - 0, SUMMARIES_SMALLER.length); - - String[] entries = new String[1 + numSmaller + numLarger]; - int[] values = new int[entries.length]; - int curIndex = 0; - - if (numSmaller > 0) { - final float interval = (1 - minScale) / numSmaller; - for (int i = numSmaller - 1; i >= 0; i--) { - // Round down to a multiple of 2 by truncating the low bit. - final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1; - if (currentDensity == density) { - currentDensityIndex = curIndex; + for (Display display : mDisplayManager.getDisplays( + DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) { + DisplayInfo info = new DisplayInfo(); + if (!display.getDisplayInfo(info)) { + Log.w(LOG_TAG, "Cannot fetch display info for display " + display.getDisplayId()); + continue; + } + if (!mPredicate.test(info)) { + if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { + throw new IllegalArgumentException("Predicate must not filter out the default " + + "display."); } - entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]); - values[curIndex] = density; - curIndex++; + continue; } - } - if (currentDensity == defaultDensity) { - currentDensityIndex = curIndex; - } - values[curIndex] = defaultDensity; - entries[curIndex] = res.getString(SUMMARY_DEFAULT); - curIndex++; - - if (numLarger > 0) { - final float interval = (maxScale - 1) / numLarger; - for (int i = 0; i < numLarger; i++) { - // Round down to a multiple of 2 by truncating the low bit. - final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1; - if (currentDensity == density) { - currentDensityIndex = curIndex; + final int defaultDensity = DisplayDensityUtils.getDefaultDensityForDisplay( + display.getDisplayId()); + if (defaultDensity <= 0) { + Log.w(LOG_TAG, "Cannot fetch default density for display " + + display.getDisplayId()); + continue; + } + + final Resources res = context.getResources(); + + final int currentDensity = info.logicalDensityDpi; + int currentDensityIndex = -1; + + // Compute number of "larger" and "smaller" scales for this display. + final int minDimensionPx = Math.min(info.logicalWidth, info.logicalHeight); + final int maxDensity = + DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP; + final float maxScaleDimen = context.getResources().getFraction( + R.fraction.display_density_max_scale, 1, 1); + final float maxScale = Math.min(maxScaleDimen, maxDensity / (float) defaultDensity); + final float minScale = context.getResources().getFraction( + R.fraction.display_density_min_scale, 1, 1); + final float minScaleInterval = context.getResources().getFraction( + R.fraction.display_density_min_scale_interval, 1, 1); + final int numLarger = (int) MathUtils.constrain((maxScale - 1) / minScaleInterval, + 0, SUMMARIES_LARGER.length); + final int numSmaller = (int) MathUtils.constrain((1 - minScale) / minScaleInterval, + 0, SUMMARIES_SMALLER.length); + + String[] entries = new String[1 + numSmaller + numLarger]; + int[] values = new int[entries.length]; + int curIndex = 0; + + if (numSmaller > 0) { + final float interval = (1 - minScale) / numSmaller; + for (int i = numSmaller - 1; i >= 0; i--) { + // Round down to a multiple of 2 by truncating the low bit. + final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1; + if (currentDensity == density) { + currentDensityIndex = curIndex; + } + entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]); + values[curIndex] = density; + curIndex++; } - values[curIndex] = density; - entries[curIndex] = res.getString(SUMMARIES_LARGER[i]); - curIndex++; } - } - final int displayIndex; - if (currentDensityIndex >= 0) { - displayIndex = currentDensityIndex; - } else { - // We don't understand the current density. Must have been set by - // someone else. Make room for another entry... - int newLength = values.length + 1; - values = Arrays.copyOf(values, newLength); - values[curIndex] = currentDensity; + if (currentDensity == defaultDensity) { + currentDensityIndex = curIndex; + } + values[curIndex] = defaultDensity; + entries[curIndex] = res.getString(SUMMARY_DEFAULT); + curIndex++; - entries = Arrays.copyOf(entries, newLength); - entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity); + if (numLarger > 0) { + final float interval = (maxScale - 1) / numLarger; + for (int i = 0; i < numLarger; i++) { + // Round down to a multiple of 2 by truncating the low bit. + final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1; + if (currentDensity == density) { + currentDensityIndex = curIndex; + } + values[curIndex] = density; + entries[curIndex] = res.getString(SUMMARIES_LARGER[i]); + curIndex++; + } + } - displayIndex = curIndex; - } + final int displayIndex; + if (currentDensityIndex >= 0) { + displayIndex = currentDensityIndex; + } else { + // We don't understand the current density. Must have been set by + // someone else. Make room for another entry... + int newLength = values.length + 1; + values = Arrays.copyOf(values, newLength); + values[curIndex] = currentDensity; - mDefaultDensity = defaultDensity; - mCurrentIndex = displayIndex; - mEntries = entries; - mValues = values; + entries = Arrays.copyOf(entries, newLength); + entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity); + + displayIndex = curIndex; + } + + if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { + mDefaultDensityForDefaultDisplay = defaultDensity; + mCurrentIndex = displayIndex; + mDefaultDisplayDensityEntries = entries; + mDefaultDisplayDensityValues = values; + } + mValuesPerDisplay.put(info.uniqueId, values); + } } - public String[] getEntries() { - return mEntries; + public String[] getDefaultDisplayDensityEntries() { + return mDefaultDisplayDensityEntries; } - public int[] getValues() { - return mValues; + public int[] getDefaultDisplayDensityValues() { + return mDefaultDisplayDensityValues; } - public int getCurrentIndex() { + public int getCurrentIndexForDefaultDisplay() { return mCurrentIndex; } - public int getDefaultDensity() { - return mDefaultDensity; + public int getDefaultDensityForDefaultDisplay() { + return mDefaultDensityForDefaultDisplay; } /** @@ -193,7 +246,7 @@ public class DisplayDensityUtils { * @return the default density of the specified display, or {@code -1} if * the display does not exist or the density could not be obtained */ - private static int getDefaultDisplayDensity(int displayId) { + private static int getDefaultDensityForDisplay(int displayId) { try { final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); return wm.getInitialDisplayDensity(displayId); @@ -203,19 +256,31 @@ public class DisplayDensityUtils { } /** - * Asynchronously applies display density changes to the specified display. + * Asynchronously applies display density changes to the displays that satisfy the predicate. * <p> * The change will be applied to the user specified by the value of * {@link UserHandle#myUserId()} at the time the method is called. - * - * @param displayId the identifier of the display to modify */ - public static void clearForcedDisplayDensity(final int displayId) { + public void clearForcedDisplayDensity() { final int userId = UserHandle.myUserId(); AsyncTask.execute(() -> { try { - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - wm.clearForcedDisplayDensityForUser(displayId, userId); + for (Display display : mDisplayManager.getDisplays( + DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) { + int displayId = display.getDisplayId(); + DisplayInfo info = new DisplayInfo(); + if (!display.getDisplayInfo(info)) { + Log.w(LOG_TAG, "Unable to clear forced display density setting " + + "for display " + displayId); + continue; + } + if (!mPredicate.test(info)) { + continue; + } + + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.clearForcedDisplayDensityForUser(displayId, userId); + } } catch (RemoteException exc) { Log.w(LOG_TAG, "Unable to clear forced display density setting"); } @@ -223,20 +288,39 @@ public class DisplayDensityUtils { } /** - * Asynchronously applies display density changes to the specified display. + * Asynchronously applies display density changes to the displays that satisfy the predicate. * <p> * The change will be applied to the user specified by the value of * {@link UserHandle#myUserId()} at the time the method is called. * - * @param displayId the identifier of the display to modify - * @param density the density to force for the specified display + * @param index The index of the density value */ - public static void setForcedDisplayDensity(final int displayId, final int density) { + public void setForcedDisplayDensity(final int index) { final int userId = UserHandle.myUserId(); AsyncTask.execute(() -> { try { - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - wm.setForcedDisplayDensityForUser(displayId, density, userId); + for (Display display : mDisplayManager.getDisplays( + DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) { + int displayId = display.getDisplayId(); + DisplayInfo info = new DisplayInfo(); + if (!display.getDisplayInfo(info)) { + Log.w(LOG_TAG, "Unable to save forced display density setting " + + "for display " + displayId); + continue; + } + if (!mPredicate.test(info)) { + continue; + } + if (!mValuesPerDisplay.containsKey(info.uniqueId)) { + Log.w(LOG_TAG, "Unable to save forced display density setting " + + "for display " + info.uniqueId); + continue; + } + + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.setForcedDisplayDensityForUser(displayId, + mValuesPerDisplay.get(info.uniqueId)[index], userId); + } } catch (RemoteException exc) { Log.w(LOG_TAG, "Unable to save forced display density setting"); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 36f86d10e2c5..98063809df15 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2974,7 +2974,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (density == mInitialDisplayDensity) { density = 0; } - mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId); + mWmService.mDisplayWindowSettings.setForcedDensity(getDisplayInfo(), density, userId); } /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */ diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index c1b6496338a4..d87532afa5bf 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -77,14 +77,14 @@ class DisplayWindowSettings { mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } - void setForcedDensity(DisplayContent displayContent, int density, int userId) { - if (displayContent.isDefaultDisplay) { + void setForcedDensity(DisplayInfo info, int density, int userId) { + if (info.displayId == Display.DEFAULT_DISPLAY) { final String densityString = density == 0 ? "" : Integer.toString(density); Settings.Secure.putStringForUser(mService.mContext.getContentResolver(), Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId); } - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final DisplayInfo displayInfo = info; final SettingsProvider.SettingsEntry overrideSettings = mSettingsProvider.getOverrideSettings(displayInfo); overrideSettings.mForcedDensity = density; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b3a7754bc2d5..b152a8c4640a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -167,7 +167,6 @@ import android.app.IActivityManager; import android.app.IAssistDataReceiver; import android.app.WindowConfiguration; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -177,7 +176,6 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.TestUtilityService; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -5845,6 +5843,11 @@ public class WindowManagerService extends IWindowManager.Stub if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { return displayContent.mInitialDisplayDensity; } + + DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); + if (info != null && info.hasAccess(Binder.getCallingUid())) { + return info.logicalDensityDpi; + } } return -1; } @@ -5876,6 +5879,11 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (displayContent != null) { displayContent.setForcedDensity(density, targetUserId); + } else { + DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); + if (info != null) { + mDisplayWindowSettings.setForcedDensity(info, density, userId); + } } } } finally { @@ -5900,6 +5908,12 @@ public class WindowManagerService extends IWindowManager.Stub if (displayContent != null) { displayContent.setForcedDensity(displayContent.mInitialDisplayDensity, callingUserId); + } else { + DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); + if (info != null) { + mDisplayWindowSettings.setForcedDensity(info, info.logicalDensityDpi, + userId); + } } } } finally { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 98e68ca99720..b0639bffe694 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -2064,7 +2064,8 @@ public class DisplayContentTests extends WindowTestsBase { // Update the forced size and density in settings and the unique id to simualate a display // remap. dc.mWmService.mDisplayWindowSettings.setForcedSize(dc, forcedWidth, forcedHeight); - dc.mWmService.mDisplayWindowSettings.setForcedDensity(dc, forcedDensity, 0 /* userId */); + dc.mWmService.mDisplayWindowSettings.setForcedDensity(displayInfo, forcedDensity, + 0 /* userId */); dc.mCurrentUniqueDisplayId = mDisplayInfo.uniqueId + "-test"; // Trigger display changed. dc.onDisplayChanged(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index c398a0a26016..fb4f2ee77521 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -236,8 +236,8 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { @Test public void testSetForcedDensity() { - mDisplayWindowSettings.setForcedDensity(mSecondaryDisplay, 600 /* density */, - 0 /* userId */); + mDisplayWindowSettings.setForcedDensity(mSecondaryDisplay.getDisplayInfo(), + 600 /* density */, 0 /* userId */); mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); assertEquals(600 /* density */, mSecondaryDisplay.mBaseDisplayDensity); @@ -439,8 +439,9 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { public void testDisplayWindowSettingsAppliedOnDisplayReady() { // Set forced densities for two displays in DisplayWindowSettings final DisplayContent dc = createMockSimulatedDisplay(); - mDisplayWindowSettings.setForcedDensity(mPrimaryDisplay, 123, 0 /* userId */); - mDisplayWindowSettings.setForcedDensity(dc, 456, 0 /* userId */); + mDisplayWindowSettings.setForcedDensity(mPrimaryDisplay.getDisplayInfo(), 123, + 0 /* userId */); + mDisplayWindowSettings.setForcedDensity(dc.getDisplayInfo(), 456, 0 /* userId */); // Apply settings to displays - the settings will be stored, but config will not be // recalculated immediately. diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index bf1d1fa98249..d31ae6aeb42a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -203,6 +203,7 @@ class TestDisplayContent extends DisplayContent { } final int displayId = SystemServicesTestRule.sNextDisplayId++; + mInfo.displayId = displayId; final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId, mInfo, DEFAULT_DISPLAY_ADJUSTMENTS); final TestDisplayContent newDisplay = createInternal(display); |