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

Commit d3f9d21f authored by nergi's avatar nergi Committed by Nergi Rahardi
Browse files

Expose getGraph() and DisplayTopologyGraph as TestApi

- Refactored AdjacentDisplay -> AdjacentEdge
- Modified displayId -> displayNode
- Refactored getGraph to build DisplayTopologyGraph in multiple steps
- Updated tests to create DisplayTopology and use getGraph() directly
instead of creating AdjacentDisplay manually

Bug: 412528980
Test: atest DisplayTopologyTest
Test: atest VisualIndicatorUpdateSchedulerTest
Test: atest DesktopMouseTestRuleTest
Flag: com.android.server.display.feature.flags.display_topology
Change-Id: I4913cdc7226836e92a79c81879b02f5b0a38f759
parent b75a0b47
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -1803,6 +1803,28 @@ package android.hardware.display {
    field public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 64; // 0x40
  }

  @FlaggedApi("com.android.server.display.feature.flags.display_topology_api") public final class DisplayTopology implements android.os.Parcelable {
    method @NonNull public android.hardware.display.DisplayTopologyGraph getGraph();
    field public static final int POSITION_BOTTOM = 3; // 0x3
    field public static final int POSITION_LEFT = 0; // 0x0
    field public static final int POSITION_RIGHT = 2; // 0x2
    field public static final int POSITION_TOP = 1; // 0x1
  }

  @FlaggedApi("com.android.server.display.feature.flags.display_topology_api") public class DisplayTopologyGraph {
    method @NonNull public android.util.SparseArray<android.hardware.display.DisplayTopologyGraph.DisplayNode> getDisplayNodes();
  }

  public static final class DisplayTopologyGraph.AdjacentEdge {
    method @NonNull public android.hardware.display.DisplayTopologyGraph.DisplayNode getDisplayNode();
    method public int getPosition();
  }

  public static class DisplayTopologyGraph.DisplayNode {
    method @NonNull public java.util.List<android.hardware.display.DisplayTopologyGraph.AdjacentEdge> getAdjacentEdges();
    method public int getDisplayId();
  }

}

package android.hardware.fingerprint {
+46 −40
Original line number Diff line number Diff line
@@ -16,14 +16,10 @@

package android.hardware.display;

import static android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM;
import static android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT;
import static android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT;
import static android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Parcel;
@@ -63,6 +59,27 @@ public final class DisplayTopology implements Parcelable {
    private static final float EPSILON = 0.0001f;
    private static final float MAX_GAP = 5;

    // Constants denoting position of a display relative to another display.
    /** @hide */
    @TestApi
    public static final int POSITION_LEFT = 0;
    /** @hide */
    @TestApi
    public static final int POSITION_TOP = 1;
    /** @hide */
    @TestApi
    public static final int POSITION_RIGHT = 2;
    /** @hide */
    @TestApi
    public static final int POSITION_BOTTOM = 3;

    /** @hide */
    @IntDef(prefix = { "POSITION_" }, value = {
            POSITION_LEFT, POSITION_TOP, POSITION_RIGHT, POSITION_BOTTOM
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Position{}

    @android.annotation.NonNull
    public static final Creator<DisplayTopology> CREATOR =
            new Creator<>() {
@@ -748,11 +765,10 @@ public final class DisplayTopology implements Parcelable {
    }

    /**
     * @return The graph representation of the topology. If there is a corner adjacency, the same
     * display will appear twice in the list of adjacent displays with both possible placements.
     * @hide
     */
    public DisplayTopologyGraph getGraph() {
    @TestApi
    public @NonNull DisplayTopologyGraph getGraph() {
        // Sort the displays by position
        List<NodeDerivedInfo> infoList = getInfo();
        Comparator<NodeDerivedInfo> byPosition = (display1, display2) -> {
@@ -764,32 +780,37 @@ public final class DisplayTopology implements Parcelable {
        };
        infoList.sort(byPosition);

        List<DisplayTopologyGraph.AdjacentDisplay>[] adjacentDisplays = new List[infoList.size()];
        // DisplayNode objects are not final yet, adjacentEdges will be populated at a later stage
        DisplayTopologyGraph.DisplayNode[] nodes =
                new DisplayTopologyGraph.DisplayNode[infoList.size()];
        for (int i = 0; i < infoList.size(); i++) {
            NodeDerivedInfo info = infoList.get(i);
            nodes[i] = new DisplayTopologyGraph.DisplayNode(info.node.mDisplayId,
                    info.node.mLogicalDensity, info.absoluteBounds());
        }

        List<DisplayTopologyGraph.AdjacentEdge>[] adjacentEdges = new List[infoList.size()];
        for (int i = 0; i < infoList.size(); i++) {
            adjacentDisplays[i] = new ArrayList<>(Math.min(10, infoList.size()));
            adjacentEdges[i] = new ArrayList<>(Math.min(10, infoList.size()));
        }

        // Find touching displays
        for (int i = 0; i < infoList.size(); i++) {
            int displayId1 = infoList.get(i).node.mDisplayId;
            DisplayTopologyGraph.DisplayNode node1 = nodes[i];
            RectF bounds1 = infoList.get(i).absoluteBounds();
            List<DisplayTopologyGraph.AdjacentDisplay> adjacentDisplays1 = adjacentDisplays[i];

            List<DisplayTopologyGraph.AdjacentEdge> adjacentEdges1 = adjacentEdges[i];
            for (int j = i + 1; j < infoList.size(); j++) {
                int displayId2 = infoList.get(j).node.mDisplayId;
                DisplayTopologyGraph.DisplayNode node2 = nodes[j];
                RectF bounds2 = infoList.get(j).absoluteBounds();
                List<DisplayTopologyGraph.AdjacentDisplay> adjacentDisplays2 = adjacentDisplays[j];
                List<DisplayTopologyGraph.AdjacentEdge> adjacentEdges2 = adjacentEdges[j];

                List<Pair<Integer, Float>> placements1 = findDisplayPlacements(bounds1, bounds2);
                List<Pair<Integer, Float>> placements2 = findDisplayPlacements(bounds2, bounds1);
                for (Pair<Integer, Float> placement : placements1) {
                    adjacentDisplays1.add(new DisplayTopologyGraph.AdjacentDisplay(displayId2,
                            /* position= */ placement.first, /* offsetDp= */ placement.second));
                for (Pair<Integer, Float> placement : findDisplayPlacements(bounds1, bounds2)) {
                    adjacentEdges1.add(new DisplayTopologyGraph.AdjacentEdge(node2, /* position= */
                            placement.first, /* offsetDp= */ placement.second));
                }
                for (Pair<Integer, Float> placement : placements2) {
                    adjacentDisplays2.add(new DisplayTopologyGraph.AdjacentDisplay(displayId1,
                            /* position= */ placement.first, /* offsetDp= */ placement.second));
                for (Pair<Integer, Float> placement : findDisplayPlacements(bounds2, bounds1)) {
                    adjacentEdges2.add(new DisplayTopologyGraph.AdjacentEdge(node1, /* position= */
                            placement.first, /* offsetDp= */ placement.second));
                }
                if (bounds2.left >= bounds1.right + EPSILON) {
                    // This and the subsequent displays are already too far away
@@ -798,14 +819,9 @@ public final class DisplayTopology implements Parcelable {
            }
        }

        DisplayTopologyGraph.DisplayNode[] nodes =
                new DisplayTopologyGraph.DisplayNode[infoList.size()];
        for (int i = 0; i < nodes.length; i++) {
            final NodeDerivedInfo nodeDerivedInfo = infoList.get(i);
            nodes[i] = new DisplayTopologyGraph.DisplayNode(
                    nodeDerivedInfo.node.mDisplayId, nodeDerivedInfo.node.mLogicalDensity,
                    nodeDerivedInfo.absoluteBounds(),
                    adjacentDisplays[i].toArray(new DisplayTopologyGraph.AdjacentDisplay[0]));
            nodes[i].setAdjacentEdges(
                    adjacentEdges[i].toArray(new DisplayTopologyGraph.AdjacentEdge[0]));
        }
        return new DisplayTopologyGraph(mPrimaryDisplayId, nodes);
    }
@@ -869,16 +885,6 @@ public final class DisplayTopology implements Parcelable {
     * @hide
     */
    public static final class TreeNode implements Parcelable {
        public static final int POSITION_LEFT = 0;
        public static final int POSITION_TOP = 1;
        public static final int POSITION_RIGHT = 2;
        public static final int POSITION_BOTTOM = 3;

        @IntDef(prefix = { "POSITION_" }, value = {
                POSITION_LEFT, POSITION_TOP, POSITION_RIGHT, POSITION_BOTTOM
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface Position{}

        @android.annotation.NonNull
        public static final Creator<TreeNode> CREATOR =
+67 −35
Original line number Diff line number Diff line
@@ -16,81 +16,112 @@

package android.hardware.display;

import android.annotation.FlaggedApi;
import android.annotation.TestApi;
import android.graphics.RectF;
import android.util.SparseArray;

import androidx.annotation.NonNull;

import com.android.server.display.feature.flags.Flags;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * Graph of the displays in {@link android.hardware.display.DisplayTopology} tree.
 *
 * <p>If there is a corner adjacency, the same display will appear twice in the list of adjacent
 * displays with both possible placements.
 *
 * @hide
 */
@TestApi
@FlaggedApi(Flags.FLAG_DISPLAY_TOPOLOGY_API)
public class DisplayTopologyGraph {

    private final int mPrimaryDisplayId;
    private final DisplayNode[] mDisplayNodes;

    /** @hide */
    public DisplayTopologyGraph(int primaryDisplayId, DisplayNode[] displayNodes) {
        mPrimaryDisplayId = primaryDisplayId;
        mDisplayNodes = displayNodes;
    }

    /** @hide */
    public int getPrimaryDisplayId() {
        return mPrimaryDisplayId;
    }

    public @NonNull List<DisplayNode> getDisplayNodes() {
        return Arrays.asList(mDisplayNodes);
    /**
     * Gets list of node representation of all displays available in the {@link DisplayTopology}.
     * The key of the SparseArray is the id of the DisplayNode
     */
    public @NonNull SparseArray<DisplayNode> getDisplayNodes() {
        SparseArray<DisplayNode> displayNodes = new SparseArray<>(mDisplayNodes.length);
        for (DisplayNode displayNode : mDisplayNodes) {
            displayNodes.put(displayNode.mDisplayId, displayNode);
        }
        return displayNodes;
    }

    /** Display in the topology */
    /** Node representation of a display, including its {@link AdjacentEdge} */
    public static class DisplayNode {

        private final int mDisplayId;
        private final int mDensity;
        private final RectF mBoundsInGlobalDp;
        private final AdjacentDisplay[] mAdjacentDisplays;
        private AdjacentEdge[] mAdjacentEdges;

        public DisplayNode(
                int displayId,
                int density,
                @NonNull RectF boundsInGlobalDp,
                AdjacentDisplay[] adjacentDisplays) {
        /** @hide */
        public DisplayNode(int displayId, int density, @NonNull RectF boundsInGlobalDp) {
            mDisplayId = displayId;
            mDensity = density;
            mBoundsInGlobalDp = boundsInGlobalDp;
            mAdjacentDisplays = adjacentDisplays;
        }

        /**
         * Gets the display id of this display node
         */
        public int getDisplayId() {
            return mDisplayId;
        }

        /** @hide */
        public int getDensity() {
            return mDensity;
        }

        /** @hide */
        public @NonNull RectF getBoundsInGlobalDp() {
            return mBoundsInGlobalDp;
        }

        public @NonNull List<AdjacentDisplay> getAdjacentDisplays() {
            return Arrays.asList(mAdjacentDisplays);
        /** @hide */
        void setAdjacentEdges(@NonNull AdjacentEdge[] edges) {
            mAdjacentEdges = edges;
        }

        /**
         * Gets a list of neighboring displays
         */
        public @NonNull List<AdjacentEdge> getAdjacentEdges() {
            return Collections.unmodifiableList(Arrays.asList(mAdjacentEdges));
        }
    }

    /** Edge to adjacent display */
    public static final class AdjacentDisplay {
    public static final class AdjacentEdge {

        // The logical Id of this adjacent display
        private final int mDisplayId;
        private final DisplayNode mDisplayNode;

        // Side of the other display which touches this adjacent display.
        @DisplayTopology.TreeNode.Position private final int mPosition;
        @DisplayTopology.Position
        private final int mPosition;

        // The distance from the top edge of the other display to the top edge of this display
        // (in case of POSITION_LEFT or POSITION_RIGHT) or from the left edge of the parent
@@ -98,23 +129,30 @@ public class DisplayTopologyGraph {
        // POSITION_BOTTOM). The unit used is density-independent pixels (dp).
        private final float mOffsetDp;

        /** Constructor for AdjacentDisplay. */
        public AdjacentDisplay(
                int displayId, @DisplayTopology.TreeNode.Position int position, float offsetDp) {
            mDisplayId = displayId;
        /** @hide */
        public AdjacentEdge(DisplayNode displayNode, @DisplayTopology.Position int position,
                float offsetDp) {
            mDisplayNode = displayNode;
            mPosition = position;
            mOffsetDp = offsetDp;
        }

        public int getDisplayId() {
            return mDisplayId;
        /**
         * Gets the {@link DisplayNode} of this adjacent display
         */
        public @NonNull DisplayNode getDisplayNode() {
            return mDisplayNode;
        }

        @DisplayTopology.TreeNode.Position
        /**
         * Gets the position of this display relative to {@link DisplayNode} it belongs to
         */
        @DisplayTopology.Position
        public int getPosition() {
            return mPosition;
        }

        /** @hide */
        public float getOffsetDp() {
            return mOffsetDp;
        }
@@ -127,27 +165,21 @@ public class DisplayTopologyGraph {
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            AdjacentDisplay rhs = (AdjacentDisplay) o;
            return this.mDisplayId == rhs.mDisplayId
                    && this.mPosition == rhs.mPosition
                    && this.mOffsetDp == rhs.mOffsetDp;
            AdjacentEdge rhs = (AdjacentEdge) o;
            return this.mDisplayNode.mDisplayId == rhs.mDisplayNode.mDisplayId
                    && this.mPosition == rhs.mPosition && this.mOffsetDp == rhs.mOffsetDp;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mDisplayId, mPosition, mOffsetDp);
            return Objects.hash(mDisplayNode.mDisplayId, mPosition, mOffsetDp);
        }

        @Override
        public String toString() {
            return "AdjacentDisplay{"
                    + "displayId="
                    + mDisplayId
                    + ", position="
                    + DisplayTopology.TreeNode.positionToString(mPosition)
                    + ", offsetDp="
                    + mOffsetDp
                    + '}';
            return "AdjacentEdge{" + "displayId=" + mDisplayNode.mDisplayId + ", position="
                    + DisplayTopology.TreeNode.positionToString(mPosition) + ", offsetDp="
                    + mOffsetDp + '}';
        }
    }
}
+21 −16
Original line number Diff line number Diff line
@@ -37,12 +37,12 @@ static struct {
    jfieldID displayId;
    jfieldID density;
    jfieldID boundsInGlobalDp;
    jfieldID adjacentDisplays;
    jfieldID adjacentEdges;
} gDisplayTopologyGraphNodeClassInfo;

static struct {
    jclass clazz;
    jfieldID displayId;
    jfieldID displayNode;
    jfieldID position;
    jfieldID offsetDp;
} gDisplayTopologyGraphAdjacentDisplayClassInfo;
@@ -73,9 +73,13 @@ status_t android_hardware_display_DisplayTopologyDisplayBounds_toNative(JNIEnv*

status_t android_hardware_display_DisplayTopologyAdjacentDisplay_toNative(
        JNIEnv* env, jobject adjacentDisplayObj, DisplayTopologyAdjacentDisplay* adjacentDisplay) {
    ScopedLocalRef<jobject>
            displayNodeObj(env,
                           env->GetObjectField(adjacentDisplayObj,
                                               gDisplayTopologyGraphAdjacentDisplayClassInfo
                                                       .displayNode));
    adjacentDisplay->displayId = ui::LogicalDisplayId{
            env->GetIntField(adjacentDisplayObj,
                             gDisplayTopologyGraphAdjacentDisplayClassInfo.displayId)};
            env->GetIntField(displayNodeObj.get(), gDisplayTopologyGraphNodeClassInfo.displayId)};
    adjacentDisplay->position = static_cast<DisplayTopologyPosition>(
            env->GetIntField(adjacentDisplayObj,
                             gDisplayTopologyGraphAdjacentDisplayClassInfo.position));
@@ -102,14 +106,14 @@ status_t android_hardware_display_DisplayTopologyGraphNode_toNative(
                                                                   &topologyGraph[displayId]
                                                                            .boundsInGlobalDp);

    jobjectArray adjacentDisplaysArray = static_cast<jobjectArray>(
            env->GetObjectField(nodeObj, gDisplayTopologyGraphNodeClassInfo.adjacentDisplays));
    jobjectArray adjacentEdgesArray = static_cast<jobjectArray>(
            env->GetObjectField(nodeObj, gDisplayTopologyGraphNodeClassInfo.adjacentEdges));

    if (adjacentDisplaysArray) {
        jsize length = env->GetArrayLength(adjacentDisplaysArray);
    if (adjacentEdgesArray) {
        jsize length = env->GetArrayLength(adjacentEdgesArray);
        for (jsize i = 0; i < length; i++) {
            ScopedLocalRef<jobject>
                    adjacentDisplayObj(env, env->GetObjectArrayElement(adjacentDisplaysArray, i));
                    adjacentDisplayObj(env, env->GetObjectArrayElement(adjacentEdgesArray, i));
            if (NULL == adjacentDisplayObj.get()) {
                break; // found null element indicating end of used portion of the array
            }
@@ -171,17 +175,18 @@ int register_android_hardware_display_DisplayTopology(JNIEnv* env) {
    gDisplayTopologyGraphNodeClassInfo.boundsInGlobalDp =
            GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "mBoundsInGlobalDp",
                            "Landroid/graphics/RectF;");
    gDisplayTopologyGraphNodeClassInfo.adjacentDisplays =
            GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "mAdjacentDisplays",
                            "[Landroid/hardware/display/DisplayTopologyGraph$AdjacentDisplay;");
    gDisplayTopologyGraphNodeClassInfo.adjacentEdges =
            GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "mAdjacentEdges",
                            "[Landroid/hardware/display/DisplayTopologyGraph$AdjacentEdge;");

    jclass adjacentDisplayClazz =
            FindClassOrDie(env, "android/hardware/display/DisplayTopologyGraph$AdjacentDisplay");
            FindClassOrDie(env, "android/hardware/display/DisplayTopologyGraph$AdjacentEdge");
    gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz =
            MakeGlobalRefOrDie(env, adjacentDisplayClazz);
    gDisplayTopologyGraphAdjacentDisplayClassInfo.displayId =
            GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz, "mDisplayId",
                            "I");
    gDisplayTopologyGraphAdjacentDisplayClassInfo.displayNode =
            GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz,
                            "mDisplayNode",
                            "Landroid/hardware/display/DisplayTopologyGraph$DisplayNode;");
    gDisplayTopologyGraphAdjacentDisplayClassInfo.position =
            GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz, "mPosition",
                            "I");
+136 −96

File changed.

Preview size limit exceeded, changes collapsed.

Loading