Loading core/java/android/hardware/display/DisplayTopology.java +27 −28 Original line number Diff line number Diff line Loading @@ -246,10 +246,9 @@ public final class DisplayTopology implements Parcelable { // The optimal pair is the pair which has the smallest deviation. The deviation consists of // an x-axis component and a y-axis component, called xDeviation and yDeviation. // // The deviations are like distances but a little different. They are calculated in two // steps. The first step calculates both axes in a similar way. The next step compares the // two values and chooses which axis to attach along. Depending on which axis is chosen, // the deviation for one axis is updated. See below for details. // The deviations are like distances but a little different. When they are calculated, each // dimension is treated differently, depending on which edges (left+right or top+bottom) are // attached. while (!needsParent.isEmpty()) { double bestDist = Double.POSITIVE_INFINITY; TreeNode bestChild = null, bestParent = null; Loading @@ -263,33 +262,32 @@ public final class DisplayTopology implements Parcelable { float parentRight = parentPos.x + parent.getWidth(); float parentBottom = parentPos.y + parent.getHeight(); // This is the smaller of the two ranges minus the amount of overlap shared // between them. The "amount of overlap" is negative if there is no overlap, but // this does not make a parenting ineligible, because we allow for attaching at // the corner and for floating point error. The overlap is more negative the // farther apart the closest corner pair is. // // For each axis, this calculates (SmallerRange - Overlap). If one range lies // completely in the other (or they are equal), the axis' deviation will be // zero. // // The "SmallerRange," which refers to smaller of the widths of the two rects, // or smaller of the heights of the two rects, is added to the deviation so that // a maximum overlap results in a deviation of zero. float xSmallerRange = Math.min(child.getWidth(), parent.getWidth()); float ySmallerRange = Math.min(child.getHeight(), parent.getHeight()); float xOverlap = Math.min(parentRight, childRight) - Math.max(parentPos.x, childPos.x); float yOverlap = Math.min(parentBottom, childBottom) - Math.max(parentPos.y, childPos.y); float xDeviation = xSmallerRange - xOverlap; float yDeviation = ySmallerRange - yOverlap; // The "amount of overlap" indicates how much of one display is within the other // (considering one axis only). It's zero if they only share an edge and // negative if they're away from each other. // A zero or negative overlap does not make a parenting ineligible, because we // allow for attaching at the corner and for floating point error. float xOverlap = Math.min(parentRight, childRight) - Math.max(parentPos.x, childPos.x); float yOverlap = Math.min(parentBottom, childBottom) - Math.max(parentPos.y, childPos.y); float xDeviation, yDeviation; float offset; int pos; if (xDeviation <= yDeviation) { if (Math.abs(xOverlap) > Math.abs(yOverlap)) { // Deviation in each dimension is a penalty in the potential parenting. To // get the X deviation, overlap is subtracted from the lesser width so that // a maximum overlap results in a deviation of zero. // Note that because xOverlap is *subtracted* from the lesser width, no // overlap in X becomes a *penalty* if we are attaching on the top+bottom // edges. // // The Y deviation is simply the distance from the clamping edges. // // Treatment of the X and Y deviations are swapped for // POSITION_LEFT/POSITION_RIGHT attachments in the "else" block below. xDeviation = Math.min(child.getWidth(), parent.getWidth()) - xOverlap; if (childPos.y < parentPos.y) { yDeviation = childBottom - parentPos.y; pos = POSITION_TOP; Loading @@ -299,6 +297,7 @@ public final class DisplayTopology implements Parcelable { } offset = childPos.x - parentPos.x; } else { yDeviation = Math.min(child.getHeight(), parent.getHeight()) - yOverlap; if (childPos.x < parentPos.x) { xDeviation = childRight - parentPos.x; pos = POSITION_LEFT; Loading core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +53 −1 Original line number Diff line number Diff line Loading @@ -643,12 +643,64 @@ class DisplayTopologyTest { verifyDisplay( root.children[0], id = 1, width = 30f, height = 30f, POSITION_RIGHT, offset = 10f, noOfChildren = 1) // In the case of corner adjacency, we prefer a left/right attachment. verifyDisplay( root.children[0].children[0], id = 2, width = 29.5f, height = 30f, POSITION_BOTTOM, offset = 30f, noOfChildren = 0) } @Test fun rearrange_preferLessShiftInOverlapDimension() { val root = rearrangeRects( // '*' represents overlap // Clamping requires moving display 2 and 1 slightly to avoid overlap with 0. We should // shift the minimal amount to avoid overlap - e.g. display 2 shifts left (10 pixels) // rather than up (20 pixels). // 222 // 22*00 // 22*00 // 0**1 // 111 // 111 RectF(20f, 10f, 50f, 40f), RectF(30f, 30f, 60f, 60f), RectF(0f, 0f, 30f, 30f), ) verifyDisplay(root, id = 0, width = 30f, height = 30f, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30f, height = 30f, POSITION_BOTTOM, offset = 10f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30f, height = 30f, POSITION_LEFT, offset = -10f, noOfChildren = 0) } @Test fun rearrange_doNotAttachCornerForShortOverlapOnLongEdgeBottom() { val root = rearrangeRects( RectF(0f, 0f, 1920f, 1080f), RectF(1850f, 1070f, 3770f, 2150f), ) verifyDisplay(root, id = 0, width = 1920f, height = 1080f, noOfChildren = 1) verifyDisplay( root.children[0], id = 1, width = 1920f, height = 1080f, POSITION_BOTTOM, offset = 1850f, noOfChildren = 0) } @Test fun rearrange_doNotAttachCornerForShortOverlapOnLongEdgeLeft() { val root = rearrangeRects( RectF(0f, 0f, 1080f, 1920f), RectF(-1070f, -1880f, 10f, 40f), ) verifyDisplay(root, id = 0, width = 1080f, height = 1920f, noOfChildren = 1) verifyDisplay( root.children[0], id = 1, width = 1080f, height = 1920f, POSITION_LEFT, offset = -1880f, noOfChildren = 0) } @Test fun copy() { val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f, Loading Loading
core/java/android/hardware/display/DisplayTopology.java +27 −28 Original line number Diff line number Diff line Loading @@ -246,10 +246,9 @@ public final class DisplayTopology implements Parcelable { // The optimal pair is the pair which has the smallest deviation. The deviation consists of // an x-axis component and a y-axis component, called xDeviation and yDeviation. // // The deviations are like distances but a little different. They are calculated in two // steps. The first step calculates both axes in a similar way. The next step compares the // two values and chooses which axis to attach along. Depending on which axis is chosen, // the deviation for one axis is updated. See below for details. // The deviations are like distances but a little different. When they are calculated, each // dimension is treated differently, depending on which edges (left+right or top+bottom) are // attached. while (!needsParent.isEmpty()) { double bestDist = Double.POSITIVE_INFINITY; TreeNode bestChild = null, bestParent = null; Loading @@ -263,33 +262,32 @@ public final class DisplayTopology implements Parcelable { float parentRight = parentPos.x + parent.getWidth(); float parentBottom = parentPos.y + parent.getHeight(); // This is the smaller of the two ranges minus the amount of overlap shared // between them. The "amount of overlap" is negative if there is no overlap, but // this does not make a parenting ineligible, because we allow for attaching at // the corner and for floating point error. The overlap is more negative the // farther apart the closest corner pair is. // // For each axis, this calculates (SmallerRange - Overlap). If one range lies // completely in the other (or they are equal), the axis' deviation will be // zero. // // The "SmallerRange," which refers to smaller of the widths of the two rects, // or smaller of the heights of the two rects, is added to the deviation so that // a maximum overlap results in a deviation of zero. float xSmallerRange = Math.min(child.getWidth(), parent.getWidth()); float ySmallerRange = Math.min(child.getHeight(), parent.getHeight()); float xOverlap = Math.min(parentRight, childRight) - Math.max(parentPos.x, childPos.x); float yOverlap = Math.min(parentBottom, childBottom) - Math.max(parentPos.y, childPos.y); float xDeviation = xSmallerRange - xOverlap; float yDeviation = ySmallerRange - yOverlap; // The "amount of overlap" indicates how much of one display is within the other // (considering one axis only). It's zero if they only share an edge and // negative if they're away from each other. // A zero or negative overlap does not make a parenting ineligible, because we // allow for attaching at the corner and for floating point error. float xOverlap = Math.min(parentRight, childRight) - Math.max(parentPos.x, childPos.x); float yOverlap = Math.min(parentBottom, childBottom) - Math.max(parentPos.y, childPos.y); float xDeviation, yDeviation; float offset; int pos; if (xDeviation <= yDeviation) { if (Math.abs(xOverlap) > Math.abs(yOverlap)) { // Deviation in each dimension is a penalty in the potential parenting. To // get the X deviation, overlap is subtracted from the lesser width so that // a maximum overlap results in a deviation of zero. // Note that because xOverlap is *subtracted* from the lesser width, no // overlap in X becomes a *penalty* if we are attaching on the top+bottom // edges. // // The Y deviation is simply the distance from the clamping edges. // // Treatment of the X and Y deviations are swapped for // POSITION_LEFT/POSITION_RIGHT attachments in the "else" block below. xDeviation = Math.min(child.getWidth(), parent.getWidth()) - xOverlap; if (childPos.y < parentPos.y) { yDeviation = childBottom - parentPos.y; pos = POSITION_TOP; Loading @@ -299,6 +297,7 @@ public final class DisplayTopology implements Parcelable { } offset = childPos.x - parentPos.x; } else { yDeviation = Math.min(child.getHeight(), parent.getHeight()) - yOverlap; if (childPos.x < parentPos.x) { xDeviation = childRight - parentPos.x; pos = POSITION_LEFT; Loading
core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +53 −1 Original line number Diff line number Diff line Loading @@ -643,12 +643,64 @@ class DisplayTopologyTest { verifyDisplay( root.children[0], id = 1, width = 30f, height = 30f, POSITION_RIGHT, offset = 10f, noOfChildren = 1) // In the case of corner adjacency, we prefer a left/right attachment. verifyDisplay( root.children[0].children[0], id = 2, width = 29.5f, height = 30f, POSITION_BOTTOM, offset = 30f, noOfChildren = 0) } @Test fun rearrange_preferLessShiftInOverlapDimension() { val root = rearrangeRects( // '*' represents overlap // Clamping requires moving display 2 and 1 slightly to avoid overlap with 0. We should // shift the minimal amount to avoid overlap - e.g. display 2 shifts left (10 pixels) // rather than up (20 pixels). // 222 // 22*00 // 22*00 // 0**1 // 111 // 111 RectF(20f, 10f, 50f, 40f), RectF(30f, 30f, 60f, 60f), RectF(0f, 0f, 30f, 30f), ) verifyDisplay(root, id = 0, width = 30f, height = 30f, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30f, height = 30f, POSITION_BOTTOM, offset = 10f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30f, height = 30f, POSITION_LEFT, offset = -10f, noOfChildren = 0) } @Test fun rearrange_doNotAttachCornerForShortOverlapOnLongEdgeBottom() { val root = rearrangeRects( RectF(0f, 0f, 1920f, 1080f), RectF(1850f, 1070f, 3770f, 2150f), ) verifyDisplay(root, id = 0, width = 1920f, height = 1080f, noOfChildren = 1) verifyDisplay( root.children[0], id = 1, width = 1920f, height = 1080f, POSITION_BOTTOM, offset = 1850f, noOfChildren = 0) } @Test fun rearrange_doNotAttachCornerForShortOverlapOnLongEdgeLeft() { val root = rearrangeRects( RectF(0f, 0f, 1080f, 1920f), RectF(-1070f, -1880f, 10f, 40f), ) verifyDisplay(root, id = 0, width = 1080f, height = 1920f, noOfChildren = 1) verifyDisplay( root.children[0], id = 1, width = 1080f, height = 1920f, POSITION_LEFT, offset = -1880f, noOfChildren = 0) } @Test fun copy() { val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f, Loading