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

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

Set the same density to all displays

It's better user experience to have the same density on all internal displays.

The density calculation uses the display size to come up with density values. We can use the size of one of the displays to calculate the values and then use the same values on the density slider for all displays. We use the size of the smallest display to make sure that the largest/smallest values aren't too extreme for the smallest display.

Bug: 324439718
Test: Change the density and see that the density has been applied to all displays.
Test: atest DisplaySizeDataTest
Test: atest ScreenResolutionFragmentTest
Flag: EXEMPT bugfix
Change-Id: Ie138c53b5042b78e3f32a133c5c1ba368c7b2b50
parent 43cb7dd4
Loading
Loading
Loading
Loading
+131 −117
Original line number Diff line number Diff line
@@ -30,11 +30,12 @@ import android.view.DisplayInfo;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.settingslib.R;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

/**
@@ -82,38 +83,55 @@ public class DisplayDensityUtils {
    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.
     * The text description of the density values.
     */
    private int[] mDefaultDisplayDensityValues;
    @Nullable
    private final String[] mEntries;

    /**
     * The density values, indexed by display unique ID.
     * The density values.
     */
    private final Map<String, int[]> mValuesPerDisplay = new HashMap();
    @Nullable
    private final int[] mValues;

    private int mDefaultDensityForDefaultDisplay;
    private int mCurrentIndex = -1;
    private final int mDefaultDensity;
    private final int mCurrentIndex;

    public DisplayDensityUtils(Context context) {
    public DisplayDensityUtils(@NonNull Context context) {
        this(context, INTERNAL_ONLY);
    }

    /**
     * Creates an instance that stores the density values for the displays that satisfy
     * the predicate.
     * Creates an instance that stores the density values for the smallest display that satisfies
     * the predicate. It is enough to store the values for one display because the same density
     * should be set to all 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) {
    public DisplayDensityUtils(@NonNull Context context,
            @NonNull Predicate<DisplayInfo> predicate) {
        mPredicate = predicate;
        mDisplayManager = context.getSystemService(DisplayManager.class);

        Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
        DisplayInfo defaultDisplayInfo = new DisplayInfo();
        if (!defaultDisplay.getDisplayInfo(defaultDisplayInfo)) {
            Log.w(LOG_TAG, "Cannot fetch display info for the default display");
            mEntries = null;
            mValues = null;
            mDefaultDensity = 0;
            mCurrentIndex = -1;
            return;
        }
        if (!mPredicate.test(defaultDisplayInfo)) {
            throw new IllegalArgumentException(
                    "Predicate must not filter out the default display.");
        }

        int idOfSmallestDisplay = Display.DEFAULT_DISPLAY;
        int minDimensionPx = Math.min(defaultDisplayInfo.logicalWidth,
                defaultDisplayInfo.logicalHeight);
        for (Display display : mDisplayManager.getDisplays(
                DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) {
            DisplayInfo info = new DisplayInfo();
@@ -122,28 +140,32 @@ public class DisplayDensityUtils {
                continue;
            }
            if (!mPredicate.test(info)) {
                if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
                    throw new IllegalArgumentException("Predicate must not filter out the default "
                            + "display.");
                }
                continue;
            }
            int minDimension = Math.min(info.logicalWidth, info.logicalHeight);
            if (minDimension < minDimensionPx) {
                minDimensionPx = minDimension;
                idOfSmallestDisplay = display.getDisplayId();
            }
        }

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

        final Resources res = context.getResources();

            final int currentDensity = info.logicalDensityDpi;
        final int currentDensity = defaultDisplayInfo.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(
@@ -213,30 +235,28 @@ public class DisplayDensityUtils {
            displayIndex = curIndex;
        }

            if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
                mDefaultDensityForDefaultDisplay = defaultDensity;
        mDefaultDensity = defaultDensity;
        mCurrentIndex = displayIndex;
                mDefaultDisplayDensityEntries = entries;
                mDefaultDisplayDensityValues = values;
            }
            mValuesPerDisplay.put(info.uniqueId, values);
        }
        mEntries = entries;
        mValues = values;
    }

    public String[] getDefaultDisplayDensityEntries() {
        return mDefaultDisplayDensityEntries;
    @Nullable
    public String[] getEntries() {
        return mEntries;
    }

    public int[] getDefaultDisplayDensityValues() {
        return mDefaultDisplayDensityValues;
    @Nullable
    public int[] getValues() {
        return mValues;
    }

    public int getCurrentIndexForDefaultDisplay() {
    public int getCurrentIndex() {
        return mCurrentIndex;
    }

    public int getDefaultDensityForDefaultDisplay() {
        return mDefaultDensityForDefaultDisplay;
    public int getDefaultDensity() {
        return mDefaultDensity;
    }

    /**
@@ -311,15 +331,9 @@ public class DisplayDensityUtils {
                    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);
                    wm.setForcedDisplayDensityForUser(displayId, mValues[index], userId);
                }
            } catch (RemoteException exc) {
                Log.w(LOG_TAG, "Unable to save forced display density setting");