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

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

Display topology util methods

- getCoordinates
- toDp, toPx

Bug: 376858743
Test: DisplayTopologyTest, DisplayTopologyCoordinatorTest
Flag: com.android.server.display.feature.flags.display_topology
Change-Id: Ie3cafc13825c081220593c8c29707305a2926a7b
parent 2022fc79
Loading
Loading
Loading
Loading
+55 −9
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@ import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.util.IndentingPrintWriter;
import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;

import androidx.annotation.NonNull;
@@ -74,6 +76,24 @@ public final class DisplayTopology implements Parcelable {
                }
            };

    /**
     * @param px The value in logical pixels
     * @param dpi The logical density of the display
     * @return The value in density-independent pixels
     */
    public static float pxToDp(float px, int dpi) {
        return px * DisplayMetrics.DENSITY_DEFAULT / dpi;
    }

    /**
     * @param dp The value in density-independent pixels
     * @param dpi The logical density of the display
     * @return The value in logical pixels
     */
    public static float dpToPx(float dp, int dpi) {
        return dp * dpi / DisplayMetrics.DENSITY_DEFAULT;
    }

    /**
     * The topology tree
     */
@@ -474,6 +494,22 @@ public final class DisplayTopology implements Parcelable {
        return new DisplayTopology(rootCopy, mPrimaryDisplayId);
    }

    /**
     * Assign absolute bounds to each display. The top-left corner of the root is at position
     * (0, 0).
     * @return Map from logical display ID to the display's absolute bounds
     */
    public SparseArray<RectF> getAbsoluteBounds() {
        Map<TreeNode, RectF> bounds = new HashMap<>();
        getInfo(bounds, /* depths= */ null, /* parents= */ null, mRoot, /* x= */ 0, /* y= */ 0,
                /* depth= */ 0);
        SparseArray<RectF> boundsById = new SparseArray<>();
        for (Map.Entry<TreeNode, RectF> entry : bounds.entrySet()) {
            boundsById.append(entry.getKey().mDisplayId, entry.getValue());
        }
        return boundsById;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -575,7 +611,7 @@ public final class DisplayTopology implements Parcelable {
    }

    @Nullable
    private static TreeNode findDisplay(int displayId, TreeNode startingNode) {
    private static TreeNode findDisplay(int displayId, @Nullable TreeNode startingNode) {
        if (startingNode == null) {
            return null;
        }
@@ -592,8 +628,8 @@ public final class DisplayTopology implements Parcelable {
    }

    /**
     * Get information about the topology that will be used for the normalization algorithm.
     * Assigns origins to each display to compute the bounds.
     * Get information about the topology.
     * Assigns positions to each display to compute the bounds. The root is at position (0, 0).
     * @param bounds The map where the bounds of each display will be put
     * @param depths The map where the depths of each display in the tree will be put
     * @param parents The map where the parent of each display will be put
@@ -602,12 +638,22 @@ public final class DisplayTopology implements Parcelable {
     * @param y The starting y position
     * @param depth The starting depth
     */
    private static void getInfo(Map<TreeNode, RectF> bounds, Map<TreeNode, Integer> depths,
            Map<TreeNode, TreeNode> parents, TreeNode display, float x, float y, int depth) {
    private static void getInfo(@Nullable Map<TreeNode, RectF> bounds,
            @Nullable Map<TreeNode, Integer> depths, @Nullable Map<TreeNode, TreeNode> parents,
            @Nullable TreeNode display, float x, float y, int depth) {
        if (display == null) {
            return;
        }
        if (bounds != null) {
            bounds.put(display, new RectF(x, y, x + display.mWidth, y + display.mHeight));
        }
        if (depths != null) {
            depths.put(display, depth);
        }
        for (TreeNode child : display.mChildren) {
            if (parents != null) {
                parents.put(child, display);
            }
            if (child.mPosition == POSITION_LEFT) {
                getInfo(bounds, depths, parents, child, x - child.mWidth, y + child.mOffset,
                        depth + 1);
@@ -662,7 +708,7 @@ public final class DisplayTopology implements Parcelable {
     * Ensure that the offsets of all displays within the given tree are within bounds.
     * @param display The starting node
     */
    private void clampOffsets(TreeNode display) {
    private void clampOffsets(@Nullable TreeNode display) {
        if (display == null) {
            return;
        }
+29 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
import android.util.SparseArray
import android.view.Display
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -687,6 +688,34 @@ class DisplayTopologyTest {
            offset = 0f, noOfChildren = 0)
    }

    @Test
    fun coordinates() {
        val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f,
            /* height= */ 600f, /* position= */ 0, /* offset= */ 0f)

        val display2 = DisplayTopology.TreeNode(/* displayId= */ 2, /* width= */ 600f,
            /* height= */ 200f, POSITION_RIGHT, /* offset= */ 0f)
        display1.addChild(display2)

        val display3 = DisplayTopology.TreeNode(/* displayId= */ 3, /* width= */ 600f,
            /* height= */ 200f, POSITION_RIGHT, /* offset= */ 400f)
        display1.addChild(display3)

        val display4 = DisplayTopology.TreeNode(/* displayId= */ 4, /* width= */ 200f,
            /* height= */ 600f, POSITION_RIGHT, /* offset= */ 0f)
        display2.addChild(display4)

        topology = DisplayTopology(display1, /* primaryDisplayId= */ 1)
        val coords = topology.absoluteBounds

        val expectedCoords = SparseArray<RectF>()
        expectedCoords.append(1, RectF(0f, 0f, 200f, 600f))
        expectedCoords.append(2, RectF(200f, 0f, 800f, 200f))
        expectedCoords.append(3, RectF(200f, 400f, 800f, 600f))
        expectedCoords.append(4, RectF(800f, 0f, 1000f, 600f))
        assertThat(coords.contentEquals(expectedCoords)).isTrue()
    }

    /**
     * Runs the rearrange algorithm and returns the resulting tree as a list of nodes, with the
     * root at index 0. The number of nodes is inferred from the number of positions passed.
+4 −5
Original line number Diff line number Diff line
@@ -16,8 +16,9 @@

package com.android.server.display;

import static android.hardware.display.DisplayTopology.pxToDp;

import android.hardware.display.DisplayTopology;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.DisplayInfo;

@@ -140,8 +141,7 @@ class DisplayTopologyCoordinator {
     * @return The width of the display in dp
     */
    private float getWidth(DisplayInfo info) {
        return info.logicalWidth * (float) DisplayMetrics.DENSITY_DEFAULT
                / info.logicalDensityDpi;
        return pxToDp(info.logicalWidth, info.logicalDensityDpi);
    }

    /**
@@ -149,8 +149,7 @@ class DisplayTopologyCoordinator {
     * @return The height of the display in dp
     */
    private float getHeight(DisplayInfo info) {
        return info.logicalHeight * (float) DisplayMetrics.DENSITY_DEFAULT
                / info.logicalDensityDpi;
        return pxToDp(info.logicalHeight, info.logicalDensityDpi);
    }

    private boolean isDisplayAllowedInTopology(DisplayInfo info) {
+3 −5
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
package com.android.server.display

import android.hardware.display.DisplayTopology
import android.util.DisplayMetrics
import android.hardware.display.DisplayTopology.pxToDp
import android.view.Display
import android.view.DisplayInfo
import com.google.common.truth.Truth.assertThat
@@ -62,10 +62,8 @@ class DisplayTopologyCoordinatorTest {
    fun addDisplay() {
        coordinator.onDisplayAdded(displayInfo)

        val widthDp = displayInfo.logicalWidth * (DisplayMetrics.DENSITY_DEFAULT.toFloat()
                / displayInfo.logicalDensityDpi)
        val heightDp = displayInfo.logicalHeight * (DisplayMetrics.DENSITY_DEFAULT.toFloat()
                / displayInfo.logicalDensityDpi)
        val widthDp = pxToDp(displayInfo.logicalWidth.toFloat(), displayInfo.logicalDensityDpi)
        val heightDp = pxToDp(displayInfo.logicalHeight.toFloat(), displayInfo.logicalDensityDpi)
        verify(mockTopology).addDisplay(displayInfo.displayId, widthDp, heightDp)
        verify(mockTopologyChangedCallback).invoke(mockTopologyCopy)
    }