Apply display density to topology pane scaling
Account for high DPI screens in topology pane scaling. Flag: com.android.settings.flags.display_topology_pane_in_display_list Bug: b/352650922 Test: atest DisplayTopologyPreferenceTest.kt Test: atest TopologyScaleTest.kt Test: compare appearance on mid-dpi and high-dpi screens with a single 1080p external display Change-Id: I192fccd402c20e00beacdb5ad55eed406252eb93
This commit is contained in:
@@ -35,7 +35,9 @@ import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
|
|||||||
import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
|
import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
|
||||||
import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
|
import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
|
||||||
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
|
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.DisplayInfo
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
@@ -84,7 +86,7 @@ fun Float.atLeast(n: Number): Float = max(this, n.toFloat())
|
|||||||
* @param displaysPos the absolute topology coordinates for each display in the topology.
|
* @param displaysPos the absolute topology coordinates for each display in the topology.
|
||||||
*/
|
*/
|
||||||
class TopologyScale(
|
class TopologyScale(
|
||||||
paneWidth: Int, minPaneHeight: Float, minEdgeLength: Int, maxBlockRatio: Float,
|
paneWidth: Int, minPaneHeight: Float, minEdgeLength: Float, maxBlockRatio: Float,
|
||||||
displaysPos: Collection<RectF>) {
|
displaysPos: Collection<RectF>) {
|
||||||
/** Scale of block sizes to real-world display sizes. Should be less than 1. */
|
/** Scale of block sizes to real-world display sizes. Should be less than 1. */
|
||||||
val blockRatio: Float
|
val blockRatio: Float
|
||||||
@@ -120,7 +122,7 @@ class TopologyScale(
|
|||||||
// If the `ratio` is set too low because one of the displays will have an edge less
|
// If the `ratio` is set too low because one of the displays will have an edge less
|
||||||
// than minEdgeLength(dp) long, increase it such that the smallest edge is that
|
// than minEdgeLength(dp) long, increase it such that the smallest edge is that
|
||||||
// long.
|
// long.
|
||||||
.atLeast(minEdgeLength.toFloat() / smallestDisplayDim)
|
.atLeast(minEdgeLength / smallestDisplayDim)
|
||||||
|
|
||||||
// Essentially, we just set the pane height based on the pre-determined pane width and the
|
// Essentially, we just set the pane height based on the pre-determined pane width and the
|
||||||
// aspect ratio of the display bounds.
|
// aspect ratio of the display bounds.
|
||||||
@@ -308,6 +310,16 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
open val wallpaper: Bitmap?
|
open val wallpaper: Bitmap?
|
||||||
get() = WallpaperManager.getInstance(context).bitmap
|
get() = WallpaperManager.getInstance(context).bitmap
|
||||||
|
|
||||||
|
open val densityDpi: Int
|
||||||
|
get() {
|
||||||
|
val info = DisplayInfo()
|
||||||
|
return if (context.display.getDisplayInfo(info)) {
|
||||||
|
info.logicalDensityDpi
|
||||||
|
} else {
|
||||||
|
DisplayMetrics.DENSITY_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
open fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
||||||
displayManager.registerTopologyListener(context.mainExecutor, listener)
|
displayManager.registerTopologyListener(context.mainExecutor, listener)
|
||||||
}
|
}
|
||||||
@@ -395,9 +407,14 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
recycleableBlocks.add(mPaneContent.getChildAt(i) as DisplayBlock)
|
recycleableBlocks.add(mPaneContent.getChildAt(i) as DisplayBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This density is the density of the current display (showing the topology pane). It is
|
||||||
|
// necessary to use this density here because the topology pane coordinates are in physical
|
||||||
|
// pixels, and the display coordinates are in density-independent pixels.
|
||||||
|
val dpi = injector.densityDpi
|
||||||
val scaling = TopologyScale(
|
val scaling = TopologyScale(
|
||||||
mPaneContent.width, minPaneHeight = mTopologyInfo?.scaling?.paneHeight ?: 0f,
|
mPaneContent.width, minPaneHeight = mTopologyInfo?.scaling?.paneHeight ?: 0f,
|
||||||
minEdgeLength = 60, maxBlockRatio = 0.12f,
|
minEdgeLength = DisplayTopology.dpToPx(60f, dpi),
|
||||||
|
maxBlockRatio = DisplayTopology.dpToPx(0.12f, dpi),
|
||||||
newBounds.map { it.second }.toList())
|
newBounds.map { it.second }.toList())
|
||||||
mPaneHolder.layoutParams.let {
|
mPaneHolder.layoutParams.let {
|
||||||
val newHeight = scaling.paneHeight.toInt()
|
val newHeight = scaling.paneHeight.toInt()
|
||||||
|
@@ -25,6 +25,7 @@ import android.graphics.Bitmap
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.hardware.display.DisplayTopology
|
import android.hardware.display.DisplayTopology
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
@@ -71,6 +72,8 @@ class DisplayTopologyPreferenceTest {
|
|||||||
override val wallpaper: Bitmap?
|
override val wallpaper: Bitmap?
|
||||||
get() = systemWallpaper!!
|
get() = systemWallpaper!!
|
||||||
|
|
||||||
|
override val densityDpi = DisplayMetrics.DENSITY_DEFAULT
|
||||||
|
|
||||||
override fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
override fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
||||||
if (topologyListener != null) {
|
if (topologyListener != null) {
|
||||||
throw IllegalStateException(
|
throw IllegalStateException(
|
||||||
|
@@ -35,7 +35,7 @@ class TopologyScaleTest {
|
|||||||
fun oneDisplay4to3Aspect() {
|
fun oneDisplay4to3Aspect() {
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 640, minPaneHeight = 0f,
|
/* paneWidth= */ 640, minPaneHeight = 0f,
|
||||||
minEdgeLength = 48, maxBlockRatio = 0.05f,
|
minEdgeLength = 48f, maxBlockRatio = 0.05f,
|
||||||
listOf(RectF(0f, 0f, 640f, 480f)))
|
listOf(RectF(0f, 0f, 640f, 480f)))
|
||||||
|
|
||||||
// blockRatio is higher than 0.05 in order to make the smallest display edge (480 dp) 48dp
|
// blockRatio is higher than 0.05 in order to make the smallest display edge (480 dp) 48dp
|
||||||
@@ -52,7 +52,7 @@ class TopologyScaleTest {
|
|||||||
// The paneHeight and origin coordinates are changed but the block ratio is the same.
|
// The paneHeight and origin coordinates are changed but the block ratio is the same.
|
||||||
val taller = TopologyScale(
|
val taller = TopologyScale(
|
||||||
/* paneWidth= */ 640, minPaneHeight = 155.0f,
|
/* paneWidth= */ 640, minPaneHeight = 155.0f,
|
||||||
minEdgeLength = 48, maxBlockRatio = 0.05f,
|
minEdgeLength = 48f, maxBlockRatio = 0.05f,
|
||||||
listOf(RectF(0f, 0f, 640f, 480f)))
|
listOf(RectF(0f, 0f, 640f, 480f)))
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@@ -64,7 +64,7 @@ class TopologyScaleTest {
|
|||||||
fun twoUnalignedDisplays() {
|
fun twoUnalignedDisplays() {
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 300, minPaneHeight = 0f,
|
/* paneWidth= */ 300, minPaneHeight = 0f,
|
||||||
minEdgeLength = 48, maxBlockRatio = 0.05f,
|
minEdgeLength = 48f, maxBlockRatio = 0.05f,
|
||||||
listOf(RectF(0f, 0f, 1920f, 1200f), RectF(1920f, -300f, 3840f, 900f)))
|
listOf(RectF(0f, 0f, 1920f, 1200f), RectF(1920f, -300f, 3840f, 900f)))
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@@ -80,7 +80,7 @@ class TopologyScaleTest {
|
|||||||
fun twoDisplaysBlockRatioBumpedForGarSizeMinimumHorizontal() {
|
fun twoDisplaysBlockRatioBumpedForGarSizeMinimumHorizontal() {
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 192, minPaneHeight = 0f,
|
/* paneWidth= */ 192, minPaneHeight = 0f,
|
||||||
minEdgeLength = 48, maxBlockRatio = 0.05f,
|
minEdgeLength = 48f, maxBlockRatio = 0.05f,
|
||||||
listOf(RectF(0f, 0f, 240f, 320f), RectF(-240f, -320f, 0f, 0f)))
|
listOf(RectF(0f, 0f, 240f, 320f), RectF(-240f, -320f, 0f, 0f)))
|
||||||
|
|
||||||
// blockRatio is higher than 0.05 in order to make the smallest display edge (240 dp) 48dp
|
// blockRatio is higher than 0.05 in order to make the smallest display edge (240 dp) 48dp
|
||||||
@@ -98,7 +98,7 @@ class TopologyScaleTest {
|
|||||||
fun paneVerticalPaddingLimitedByTallestDisplay() {
|
fun paneVerticalPaddingLimitedByTallestDisplay() {
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 300, minPaneHeight = 0f,
|
/* paneWidth= */ 300, minPaneHeight = 0f,
|
||||||
minEdgeLength = 48, maxBlockRatio = 0.05f,
|
minEdgeLength = 48f, maxBlockRatio = 0.05f,
|
||||||
listOf(
|
listOf(
|
||||||
RectF(0f, 0f, 640f, 480f),
|
RectF(0f, 0f, 640f, 480f),
|
||||||
RectF(0f, 480f, 640f, 960f),
|
RectF(0f, 480f, 640f, 960f),
|
||||||
@@ -118,7 +118,7 @@ class TopologyScaleTest {
|
|||||||
fun limitedByCustomMaxBlockRatio() {
|
fun limitedByCustomMaxBlockRatio() {
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 300, minPaneHeight = 0f,
|
/* paneWidth= */ 300, minPaneHeight = 0f,
|
||||||
minEdgeLength = 24, maxBlockRatio = 0.12f,
|
minEdgeLength = 24f, maxBlockRatio = 0.12f,
|
||||||
listOf(
|
listOf(
|
||||||
RectF(0f, 0f, 640f, 480f),
|
RectF(0f, 0f, 640f, 480f),
|
||||||
RectF(0f, 480f, 640f, 960f)))
|
RectF(0f, 480f, 640f, 960f)))
|
||||||
@@ -135,7 +135,7 @@ class TopologyScaleTest {
|
|||||||
// minBlockEdgeLength/minDisplayEdgeLength = 80/480 = 1/6, so the block ratio will be 1/6
|
// minBlockEdgeLength/minDisplayEdgeLength = 80/480 = 1/6, so the block ratio will be 1/6
|
||||||
val scale = TopologyScale(
|
val scale = TopologyScale(
|
||||||
/* paneWidth= */ 300, minPaneHeight = 0f,
|
/* paneWidth= */ 300, minPaneHeight = 0f,
|
||||||
minEdgeLength = 80, maxBlockRatio = 0.05f,
|
minEdgeLength = 80f, maxBlockRatio = 0.05f,
|
||||||
listOf(
|
listOf(
|
||||||
RectF(0f, 0f, 640f, 480f),
|
RectF(0f, 0f, 640f, 480f),
|
||||||
RectF(0f, 480f, 640f, 960f)))
|
RectF(0f, 480f, 640f, 960f)))
|
||||||
|
Reference in New Issue
Block a user