Loading core/api/test-current.txt +22 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading core/java/android/hardware/display/DisplayTopology.java +46 −40 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<>() { Loading Loading @@ -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) -> { Loading @@ -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 Loading @@ -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); } Loading Loading @@ -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 = Loading core/java/android/hardware/display/DisplayTopologyGraph.java +67 −35 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading @@ -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 + '}'; } } } core/jni/android_hardware_display_DisplayTopology.cpp +21 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading @@ -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 } Loading Loading @@ -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"); Loading core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +136 −96 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/api/test-current.txt +22 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
core/java/android/hardware/display/DisplayTopology.java +46 −40 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<>() { Loading Loading @@ -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) -> { Loading @@ -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 Loading @@ -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); } Loading Loading @@ -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 = Loading
core/java/android/hardware/display/DisplayTopologyGraph.java +67 −35 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading @@ -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 + '}'; } } }
core/jni/android_hardware_display_DisplayTopology.cpp +21 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading @@ -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 } Loading Loading @@ -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"); Loading
core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +136 −96 File changed.Preview size limit exceeded, changes collapsed. Show changes