Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc04d3cf authored by Piotr Wilczyński's avatar Piotr Wilczyński
Browse files

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
parent f1f50ee2
Loading
Loading
Loading
Loading
+189 −105
Original line number Diff line number Diff line
@@ -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,33 +74,78 @@ 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);
        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);

        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.");
                }
                continue;
            }

            final int defaultDensity = DisplayDensityUtils.getDefaultDensityForDisplay(
                    display.getDisplayId());
            if (defaultDensity <= 0) {
            mEntries = null;
            mValues = null;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            return;
                Log.w(LOG_TAG, "Cannot fetch default density for display "
                        + display.getDisplayId());
                continue;
            }

            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 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);
@@ -164,26 +213,30 @@ public class DisplayDensityUtils {
                displayIndex = curIndex;
            }

        mDefaultDensity = defaultDensity;
            if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
                mDefaultDensityForDefaultDisplay = defaultDensity;
                mCurrentIndex = displayIndex;
        mEntries = entries;
        mValues = values;
                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 {
                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 {
                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, density, userId);
                    wm.setForcedDisplayDensityForUser(displayId,
                            mValuesPerDisplay.get(info.uniqueId)[index], userId);
                }
            } catch (RemoteException exc) {
                Log.w(LOG_TAG, "Unable to save forced display density setting");
            }
+1 −1
Original line number Diff line number Diff line
@@ -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}. */
+3 −3
Original line number Diff line number Diff line
@@ -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;
+16 −2
Original line number Diff line number Diff line
@@ -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 {
+2 −1
Original line number Diff line number Diff line
@@ -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();
Loading