Loading core/java/android/hardware/display/DisplayTopology.java +7 −8 Original line number Diff line number Diff line Loading @@ -346,18 +346,17 @@ public final class DisplayTopology implements Parcelable { float offset; int pos; if (xOverlap > 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. // Deviation in each dimension is a penalty in the potential parenting. In // the next line, a negative xOverlap (no shared coverage in the x axis) // results in an xDeviation (a penalty) but a non-negative xOverlap does // not. A non-negative xOverlap indicates no horizontal shifting is needed // to obtain a POSITION_TOP or POSITION_BOTTOM attachment. // // 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; xDeviation = Math.min(xOverlap, 0); if (childPos.y < parentPos.y) { yDeviation = childBottom - parentPos.y; pos = POSITION_TOP; Loading @@ -367,7 +366,7 @@ public final class DisplayTopology implements Parcelable { } offset = childPos.x - parentPos.x; } else { yDeviation = Math.min(child.getHeight(), parent.getHeight()) - yOverlap; yDeviation = Math.min(yOverlap, 0); if (childPos.x < parentPos.x) { xDeviation = childRight - parentPos.x; pos = POSITION_LEFT; Loading core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +91 −27 Original line number Diff line number Diff line Loading @@ -570,7 +570,7 @@ class DisplayTopologyTest { } @Test fun rearrange_elbowArrangementDoesNotUseCornerAdjacency1() { fun rearrange_elbowArrangement1() { val root = rearrangeRects( // 2 // | Loading @@ -581,19 +581,19 @@ class DisplayTopologyTest { DisplayArrangement(100, 100, 160, 100f, -100f), ) verifyDisplay(root, id = 0, width = 100, height = 100, density = 160, noOfChildren = 1) verifyDisplay(root, id = 0, width = 100, height = 100, density = 160, noOfChildren = 2) var node = root.children[0] verifyDisplay( node, id = 1, width = 100, height = 100, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 1) node = node.children[0] noOfChildren = 0) node = root.children[1] verifyDisplay( node, id = 2, width = 100, height = 100, density = 160, POSITION_TOP, offset = 0f, noOfChildren = 0) node, id = 2, width = 100, height = 100, density = 160, POSITION_RIGHT, offset = -100f, noOfChildren = 0) } @Test fun rearrange_elbowArrangementDoesNotUseCornerAdjacency2() { fun rearrange_elbowArrangement2() { val root = rearrangeRects( // 0 // | Loading @@ -611,19 +611,17 @@ class DisplayTopologyTest { var node = root.children[0] verifyDisplay( node, id = 1, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 1) node = node.children[0] offset = 0f, noOfChildren = 2) verifyDisplay( node, id = 2, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 1) node = node.children[0] node.children[0], id = 2, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 0) verifyDisplay( node, id = 3, width = 100, height = 100, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) node.children[1], id = 3, width = 100, height = 100, density = 160, POSITION_LEFT, offset = 100f, noOfChildren = 0) } @Test fun rearrange_useLargerEdge() { fun rearrange_rootHasFourDirectChildren() { val root = rearrangeRects( // 444111 // 444111 Loading @@ -641,19 +639,19 @@ class DisplayTopologyTest { DisplayArrangement(30, 30, 160, 0f, 0f), ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 2) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 4) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_TOP, offset = 10f, noOfChildren = 1) offset = 10f, noOfChildren = 0) verifyDisplay( root.children[0].children[0], id = 4, width = 30, height = 30, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 1) root.children[2], id = 3, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 20f, noOfChildren = 0) verifyDisplay( root.children[1].children[0], id = 3, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = -10f, noOfChildren = 0) root.children[3], id = 4, width = 30, height = 30, density = 160, POSITION_TOP, offset = -20f, noOfChildren = 0) } @Test Loading Loading @@ -682,12 +680,9 @@ class DisplayTopologyTest { } @Test fun rearrange_preferLessShiftInOverlapDimension() { fun rearrange_preferLessShiftInOverlapDimension1() { 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 Loading @@ -697,12 +692,55 @@ class DisplayTopologyTest { DisplayArrangement(30, 30, 160, 20f, 10f), DisplayArrangement(30, 30, 160, 30f, 30f), DisplayArrangement(30, 30, 160, 0f, 0f), // In the main body of DisplayTopology.rearrange, the parent/child relationship will // be 0 -> 1 -> 2, and the absolute positions will be: // 22*00 // 22*00 // 22*00 // 111 // 111 // 111 // Then normalize() will change this to 0 -> [1, 2] and positioned like this: // 222000 // 222000 // 222000 // 111 // 111 // 111 ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 10f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) } @Test fun rearrange_preferLessShiftInOverlapDimension2() { 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*00000 // 22*00000 // 0000**1 // 111 // 111 DisplayArrangement(60, 30, 160, 20f, 10f), DisplayArrangement(30, 30, 160, 60f, 30f), DisplayArrangement(30, 30, 160, 0f, 0f), ) verifyDisplay(root, id = 0, width = 60, height = 30, density = 160, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 40f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_LEFT, offset = -10f, noOfChildren = 0) Loading Loading @@ -834,6 +872,32 @@ class DisplayTopologyTest { assertThat(root.children[1].height).isEqualTo(30f) } @Test fun rearrange_useCornerAttachment() { // Verify that 0 and 2 do not clamp directly together: // 000 222 // 000 222 // 000 222 // 111 // 111 // 111 // (see b/394355269) val root = rearrangeRects( DisplayArrangement(30, 30, 160, 0f, 0f), DisplayArrangement(30, 30, 160, 30f, 30f), DisplayArrangement(30, 30, 160, 60f, 0f), ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 1) val dis1 = root.children[0] verifyDisplay(dis1, id = 1, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 30f, noOfChildren = 1) val dis2 = dis1.children[0] verifyDisplay(dis2, id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = -30f, noOfChildren = 0) } @Test fun copy() { val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* logicalWidth= */ 200, Loading Loading
core/java/android/hardware/display/DisplayTopology.java +7 −8 Original line number Diff line number Diff line Loading @@ -346,18 +346,17 @@ public final class DisplayTopology implements Parcelable { float offset; int pos; if (xOverlap > 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. // Deviation in each dimension is a penalty in the potential parenting. In // the next line, a negative xOverlap (no shared coverage in the x axis) // results in an xDeviation (a penalty) but a non-negative xOverlap does // not. A non-negative xOverlap indicates no horizontal shifting is needed // to obtain a POSITION_TOP or POSITION_BOTTOM attachment. // // 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; xDeviation = Math.min(xOverlap, 0); if (childPos.y < parentPos.y) { yDeviation = childBottom - parentPos.y; pos = POSITION_TOP; Loading @@ -367,7 +366,7 @@ public final class DisplayTopology implements Parcelable { } offset = childPos.x - parentPos.x; } else { yDeviation = Math.min(child.getHeight(), parent.getHeight()) - yOverlap; yDeviation = Math.min(yOverlap, 0); if (childPos.x < parentPos.x) { xDeviation = childRight - parentPos.x; pos = POSITION_LEFT; Loading
core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt +91 −27 Original line number Diff line number Diff line Loading @@ -570,7 +570,7 @@ class DisplayTopologyTest { } @Test fun rearrange_elbowArrangementDoesNotUseCornerAdjacency1() { fun rearrange_elbowArrangement1() { val root = rearrangeRects( // 2 // | Loading @@ -581,19 +581,19 @@ class DisplayTopologyTest { DisplayArrangement(100, 100, 160, 100f, -100f), ) verifyDisplay(root, id = 0, width = 100, height = 100, density = 160, noOfChildren = 1) verifyDisplay(root, id = 0, width = 100, height = 100, density = 160, noOfChildren = 2) var node = root.children[0] verifyDisplay( node, id = 1, width = 100, height = 100, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 1) node = node.children[0] noOfChildren = 0) node = root.children[1] verifyDisplay( node, id = 2, width = 100, height = 100, density = 160, POSITION_TOP, offset = 0f, noOfChildren = 0) node, id = 2, width = 100, height = 100, density = 160, POSITION_RIGHT, offset = -100f, noOfChildren = 0) } @Test fun rearrange_elbowArrangementDoesNotUseCornerAdjacency2() { fun rearrange_elbowArrangement2() { val root = rearrangeRects( // 0 // | Loading @@ -611,19 +611,17 @@ class DisplayTopologyTest { var node = root.children[0] verifyDisplay( node, id = 1, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 1) node = node.children[0] offset = 0f, noOfChildren = 2) verifyDisplay( node, id = 2, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 1) node = node.children[0] node.children[0], id = 2, width = 100, height = 100, density = 160, POSITION_BOTTOM, offset = 0f, noOfChildren = 0) verifyDisplay( node, id = 3, width = 100, height = 100, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) node.children[1], id = 3, width = 100, height = 100, density = 160, POSITION_LEFT, offset = 100f, noOfChildren = 0) } @Test fun rearrange_useLargerEdge() { fun rearrange_rootHasFourDirectChildren() { val root = rearrangeRects( // 444111 // 444111 Loading @@ -641,19 +639,19 @@ class DisplayTopologyTest { DisplayArrangement(30, 30, 160, 0f, 0f), ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 2) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 4) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_TOP, offset = 10f, noOfChildren = 1) offset = 10f, noOfChildren = 0) verifyDisplay( root.children[0].children[0], id = 4, width = 30, height = 30, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 0f, noOfChildren = 1) root.children[2], id = 3, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 20f, noOfChildren = 0) verifyDisplay( root.children[1].children[0], id = 3, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = -10f, noOfChildren = 0) root.children[3], id = 4, width = 30, height = 30, density = 160, POSITION_TOP, offset = -20f, noOfChildren = 0) } @Test Loading Loading @@ -682,12 +680,9 @@ class DisplayTopologyTest { } @Test fun rearrange_preferLessShiftInOverlapDimension() { fun rearrange_preferLessShiftInOverlapDimension1() { 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 Loading @@ -697,12 +692,55 @@ class DisplayTopologyTest { DisplayArrangement(30, 30, 160, 20f, 10f), DisplayArrangement(30, 30, 160, 30f, 30f), DisplayArrangement(30, 30, 160, 0f, 0f), // In the main body of DisplayTopology.rearrange, the parent/child relationship will // be 0 -> 1 -> 2, and the absolute positions will be: // 22*00 // 22*00 // 22*00 // 111 // 111 // 111 // Then normalize() will change this to 0 -> [1, 2] and positioned like this: // 222000 // 222000 // 222000 // 111 // 111 // 111 ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 10f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_LEFT, offset = 0f, noOfChildren = 0) } @Test fun rearrange_preferLessShiftInOverlapDimension2() { 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*00000 // 22*00000 // 0000**1 // 111 // 111 DisplayArrangement(60, 30, 160, 20f, 10f), DisplayArrangement(30, 30, 160, 60f, 30f), DisplayArrangement(30, 30, 160, 0f, 0f), ) verifyDisplay(root, id = 0, width = 60, height = 30, density = 160, noOfChildren = 2) verifyDisplay( root.children[0], id = 1, width = 30, height = 30, density = 160, POSITION_BOTTOM, offset = 40f, noOfChildren = 0) verifyDisplay( root.children[1], id = 2, width = 30, height = 30, density = 160, POSITION_LEFT, offset = -10f, noOfChildren = 0) Loading Loading @@ -834,6 +872,32 @@ class DisplayTopologyTest { assertThat(root.children[1].height).isEqualTo(30f) } @Test fun rearrange_useCornerAttachment() { // Verify that 0 and 2 do not clamp directly together: // 000 222 // 000 222 // 000 222 // 111 // 111 // 111 // (see b/394355269) val root = rearrangeRects( DisplayArrangement(30, 30, 160, 0f, 0f), DisplayArrangement(30, 30, 160, 30f, 30f), DisplayArrangement(30, 30, 160, 60f, 0f), ) verifyDisplay(root, id = 0, width = 30, height = 30, density = 160, noOfChildren = 1) val dis1 = root.children[0] verifyDisplay(dis1, id = 1, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = 30f, noOfChildren = 1) val dis2 = dis1.children[0] verifyDisplay(dis2, id = 2, width = 30, height = 30, density = 160, POSITION_RIGHT, offset = -30f, noOfChildren = 0) } @Test fun copy() { val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* logicalWidth= */ 200, Loading