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

Commit b8d17854 authored by Nergi Rahardi's avatar Nergi Rahardi Committed by Android (Google) Code Review
Browse files

Merge "Expose getGraph() and DisplayTopologyGraph as TestApi" into main

parents d77af0f2 d3f9d21f
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