From 6328abd3f5251b8274d3de0772c64f57b737db31 Mon Sep 17 00:00:00 2001
From: Charles Chen
Date: Thu, 15 Sep 2022 18:19:44 +0800
Subject: [PATCH] Add density to WindowMetrics
This CL adds density to WindowMetrics and also provides the capability
of providing window dimensions in DP.
Bug: 187712731
Test: WindowMetricsTest
Change-Id: If3532db0a4222b377679eb07ed47b42ba37d8cde
---
core/api/current.txt | 4 +-
core/java/android/content/res/Resources.java | 15 ++--
core/java/android/util/DisplayMetrics.java | 11 +++
core/java/android/view/Display.java | 3 +-
core/java/android/view/WindowMetrics.java | 82 ++++++++++++++++++--
5 files changed, 99 insertions(+), 16 deletions(-)
diff --git a/core/api/current.txt b/core/api/current.txt
index fc319ce6891e9..975f99a0408a2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -52288,8 +52288,10 @@ package android.view {
}
public final class WindowMetrics {
- ctor public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets);
+ ctor @Deprecated public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets);
+ ctor public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets, float);
method @NonNull public android.graphics.Rect getBounds();
+ method public float getDensity();
method @NonNull public android.view.WindowInsets getWindowInsets();
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index fb1fcf8e2a063..d6934bca46b76 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -43,6 +43,7 @@ import android.annotation.StyleableRes;
import android.annotation.XmlRes;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.content.res.loader.ResourcesLoader;
@@ -2181,17 +2182,19 @@ public class Resources {
}
/**
- * Return the current display metrics that are in effect for this resource
+ * Returns the current display metrics that are in effect for this resource
* object. The returned object should be treated as read-only.
*
* Note that the reported value may be different than the window this application is
* interested in.
*
- * Best practices are to obtain metrics from {@link WindowManager#getCurrentWindowMetrics()}
- * for window bounds, {@link Display#getRealMetrics(DisplayMetrics)} for display bounds and
- * obtain density from {@link Configuration#densityDpi}. The value obtained from this API may be
- * wrong if the {@link Resources} is from the context which is different than the window is
- * attached such as {@link Application#getResources()}.
+ *
The best practices is to obtain metrics from
+ * {@link WindowManager#getCurrentWindowMetrics()} for window bounds. The value obtained from
+ * this API may be wrong if {@link Context#getResources()} is from
+ * non-{@link android.annotation.UiContext}.
+ * For example, use the {@link DisplayMetrics} obtained from {@link Application#getResources()}
+ * to build {@link android.app.Activity} UI elements especially when the
+ * {@link android.app.Activity} is in the multi-window mode or on the secondary {@link Display}.
*
*
* @return The resource's current display metrics.
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 517d98222093a..2defb13299adf 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -19,12 +19,23 @@ package android.util;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemProperties;
+import android.view.WindowManager;
/**
* A structure describing general information about a display, such as its
* size, density, and font scaling.
* To access the DisplayMetrics members, retrieve display metrics like this:
* context.getResources().getDisplayMetrics();
+ *
+ *
+ * For UI layout, obtain {@link android.view.WindowMetrics} from
+ * {@link WindowManager#getCurrentWindowMetrics()}. {@code DisplayMetrics} should only be used for
+ * obtaining display related properties, such as {@link #xdpi} and {@link #ydpi}
+ *
+ * See {@link #density} for more information about the differences between {@link #xdpi},
+ * {@link #ydpi} and {@link #density}.
+ *
+ *
*/
public class DisplayMetrics {
/**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5933ae4f8ca45..d06eb44f0ac49 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1434,7 +1434,8 @@ public final class Display {
* @param outMetrics A {@link DisplayMetrics} object which receives the display metrics.
*
* @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application
- * window. Use {@link Configuration#densityDpi} to get the display density.
+ * window. Use {@link WindowMetrics#getDensity()} to get the density of the application
+ * window.
*/
@Deprecated
public void getMetrics(DisplayMetrics outMetrics) {
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
index 52e4e15cc9a01..141849f0593a0 100644
--- a/core/java/android/view/WindowMetrics.java
+++ b/core/java/android/view/WindowMetrics.java
@@ -25,22 +25,64 @@ import android.graphics.Rect;
*
* This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and
* {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ * After {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it also provides density.
+ * Obtains Window Dimensions in Density-independent Pixel(DP)
+ *
+ * While {@link #getDensity()} is provided, the dimension in density-independent pixel could also be
+ * calculated with {@code WindowMetrics} properties, which is similar to
+ * {@link android.content.res.Configuration#screenWidthDp}
+ *
+ * float widthInDp = windowMetrics.getBounds().width() / windowMetrics.getDensity();
+ * float heightInDp = windowMetrics.getBounds().height() / windowMetrics.getDensity();
+ *
+ * Also, the density in DPI can be obtained by:
+ *
+ * float densityDp = DisplayMetrics.DENSITY_DEFAULT * windowMetrics.getDensity();
+ *
+ *
*
* @see WindowInsets#getInsets(int)
* @see WindowManager#getCurrentWindowMetrics()
* @see WindowManager#getMaximumWindowMetrics()
+ * @see android.annotation.UiContext
*/
public final class WindowMetrics {
- private final @NonNull Rect mBounds;
- private final @NonNull WindowInsets mWindowInsets;
+ @NonNull
+ private final Rect mBounds;
+ @NonNull
+ private final WindowInsets mWindowInsets;
+ /** @see android.util.DisplayMetrics#density */
+ private final float mDensity;
+
+ /** @deprecated use {@link #WindowMetrics(Rect, WindowInsets, float)} instead. */
+ @Deprecated
public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets) {
- mBounds = bounds;
- mWindowInsets = windowInsets;
+ this(bounds, windowInsets, 1.0f);
}
/**
- * Returns the bounds of the area associated with this window or visual context.
+ * The constructor to create a {@link WindowMetrics} instance.
+ *
+ * Note that in most cases {@link WindowMetrics} is obtained from
+ * {@link WindowManager#getCurrentWindowMetrics()} or
+ * {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ *
+ * @param bounds The window bounds
+ * @param windowInsets The {@link WindowInsets} of the window
+ * @param density The window density
+ */
+ public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets, float density) {
+ mBounds = bounds;
+ mWindowInsets = windowInsets;
+ mDensity = density;
+ }
+
+ /**
+ * Returns the bounds of the area associated with this window or
+ * {@link android.annotation.UiContext}.
*
* Note that the size of the reported bounds can have different size than
* {@link Display#getSize(Point)}. This method reports the window size including all system
@@ -66,16 +108,40 @@ public final class WindowMetrics {
*
* @return window bounds in pixels.
*/
- public @NonNull Rect getBounds() {
+ @NonNull
+ public Rect getBounds() {
return mBounds;
}
/**
- * Returns the {@link WindowInsets} of the area associated with this window or visual context.
+ * Returns the {@link WindowInsets} of the area associated with this window or
+ * {@link android.annotation.UiContext}.
*
* @return the {@link WindowInsets} of the visual area.
*/
- public @NonNull WindowInsets getWindowInsets() {
+ @NonNull
+ public WindowInsets getWindowInsets() {
return mWindowInsets;
}
+
+ /**
+ * Returns the density of the area associated with this window or
+ * {@link android.annotation.UiContext}, which uses the same units as
+ * {@link android.util.DisplayMetrics#density}.
+ *
+ * @see android.util.DisplayMetrics#DENSITY_DEFAULT
+ * @see android.util.DisplayMetrics#density
+ */
+ public float getDensity() {
+ return mDensity;
+ }
+
+ @Override
+ public String toString() {
+ return WindowMetrics.class.getSimpleName() + ":{"
+ + "bounds=" + mBounds
+ + ", windowInsets=" + mWindowInsets
+ + ", density" + mDensity
+ + "}";
+ }
}