Loading core/java/android/hardware/display/DisplayTopology.java +55 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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 Loading @@ -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); Loading Loading @@ -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; } Loading core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +29 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading services/core/java/com/android/server/display/DisplayTopologyCoordinator.java +4 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading @@ -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) { Loading services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt +3 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) } Loading Loading
core/java/android/hardware/display/DisplayTopology.java +55 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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 Loading @@ -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); Loading Loading @@ -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; } Loading
core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +29 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading
services/core/java/com/android/server/display/DisplayTopologyCoordinator.java +4 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading @@ -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) { Loading
services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt +3 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) } Loading