diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index d3464fde4b75c..d8b1f41c86d5d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -90,6 +90,7 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import android.window.WindowMetricsHelper; import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IInputContentUriToken; @@ -1438,8 +1439,8 @@ public class InputMethodService extends AbstractInputMethodService { */ public int getMaxWidth() { final WindowManager windowManager = getSystemService(WindowManager.class); - final Rect windowBounds = windowManager.getCurrentWindowMetrics().getBounds(); - return windowBounds.width(); + return WindowMetricsHelper.getBoundsExcludingNavigationBarAndCutout( + windowManager.getCurrentWindowMetrics()).width(); } /** diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java index 86ef87997a07c..d96c5c82fedbd 100644 --- a/core/java/android/view/WindowMetrics.java +++ b/core/java/android/view/WindowMetrics.java @@ -48,22 +48,19 @@ public final class WindowMetrics { * and display cutout areas. The value reported by {@link Display#getSize(Point)} can be * obtained by using: *
-     * final WindowMetrics metrics = windowManager.getCurrentMetrics();
+     * final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
      * // Gets all excluding insets
      * final WindowInsets windowInsets = metrics.getWindowInsets();
-     * Insets insets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
-     * final DisplayCutout cutout = windowInsets.getCutout();
-     * if (cutout != null) {
-     *     final Insets cutoutSafeInsets = Insets.of(cutout.getSafeInsetsLeft(), ...);
-     *     insets = insets.max(insets, cutoutSafeInsets);
-     * }
+     * Insets insets = windowInsets.getInsetsIgnoreVisibility(WindowInsets.Type.navigationBars()
+     *         | WindowInsets.Type.displayCutout());
      *
      * int insetsWidth = insets.right + insets.left;
      * int insetsHeight = insets.top + insets.bottom;
      *
      * // Legacy size that Display#getSize reports
-     * final Size legacySize = new Size(metrics.getWidth() - insetsWidth,
-     *         metrics.getHeight() - insetsHeight);
+     * final Rect bounds = metrics.getBounds();
+     * final Size legacySize = new Size(bounds.width() - insetsWidth,
+     *         bounds.height() - insetsHeight);
      * 
*

* diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java index 2ead352fd199c..3161c3c498cfd 100644 --- a/core/java/android/view/autofill/AutofillPopupWindow.java +++ b/core/java/android/view/autofill/AutofillPopupWindow.java @@ -31,6 +31,7 @@ import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.PopupWindow; +import android.window.WindowMetricsHelper; /** * Custom {@link PopupWindow} used to isolate its content from the autofilled app - the @@ -128,7 +129,8 @@ public class AutofillPopupWindow extends PopupWindow { // Gravity.BOTTOM because PopupWindow base class does not expose computeGravity(). final WindowManager windowManager = anchor.getContext() .getSystemService(WindowManager.class); - final Rect windowBounds = windowManager.getCurrentWindowMetrics().getBounds(); + final Rect windowBounds = WindowMetricsHelper.getBoundsExcludingNavigationBarAndCutout( + windowManager.getCurrentWindowMetrics()); width = windowBounds.width(); if (height != LayoutParams.MATCH_PARENT) { offsetY = windowBounds.height() - height; diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java index 2e6cbeee7d22a..d2614da31ff9d 100644 --- a/core/java/android/window/VirtualDisplayTaskEmbedder.java +++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java @@ -336,11 +336,7 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { /** Get density of the hosting display. */ private int getBaseDisplayDensity() { - if (mTmpDisplayMetrics == null) { - mTmpDisplayMetrics = new DisplayMetrics(); - } - mContext.getDisplayNoVerify().getRealMetrics(mTmpDisplayMetrics); - return mTmpDisplayMetrics.densityDpi; + return mContext.getResources().getConfiguration().densityDpi; } /** diff --git a/core/java/android/window/WindowMetricsHelper.java b/core/java/android/window/WindowMetricsHelper.java new file mode 100644 index 0000000000000..fb8b27e52be13 --- /dev/null +++ b/core/java/android/window/WindowMetricsHelper.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.window; + +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.WindowInsets.Type.displayCutout; +import static android.view.WindowInsets.Type.navigationBars; + +import android.annotation.NonNull; +import android.graphics.Insets; +import android.graphics.Point; +import android.graphics.Rect; +import android.view.Display; +import android.view.DisplayCutout; +import android.view.ViewRootImpl; +import android.view.WindowInsets; +import android.view.WindowMetrics; + +/** + * Helper class to calculate size with {@link android.graphics.Insets} based on provided + * {@link WindowMetrics} + * + * @hide + */ +public final class WindowMetricsHelper { + private WindowMetricsHelper() {} + + /** + * Returns bounds excluding navigation bar and display cutout (but including status bar). + * This has the same behavior as {@link Display#getSize(Point)}. + */ + public static Rect getBoundsExcludingNavigationBarAndCutout( + @NonNull WindowMetrics windowMetrics) { + final WindowInsets windowInsets = windowMetrics.getWindowInsets(); + Insets insets; + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) { + insets = windowInsets.getInsetsIgnoringVisibility(navigationBars() | displayCutout()); + } else { + final Insets stableInsets = windowInsets.getStableInsets(); + insets = Insets.of(stableInsets.left, 0 /* top */, stableInsets.right, + stableInsets.bottom); + final DisplayCutout cutout = windowInsets.getDisplayCutout(); + insets = (cutout != null) ? Insets.max(insets, Insets.of(cutout.getSafeInsets())) + : insets; + } + final Rect result = new Rect(windowMetrics.getBounds()); + result.inset(insets); + return result; + } +} diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 67a57aaaa101a..5c2841aff1d83 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1461,7 +1461,10 @@ - + + Build/Install/Run: + * atest FrameworksCoreTests:WindowMetricsHelperTest + * + *

This test class is a part of Window Manager Service tests and specified in + * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit +public class WindowMetricsHelperTest { + + @Rule + public ActivityTestRule mActivityRule = + new ActivityTestRule<>(TestActivity.class); + + @Test + public void testGetLegacySizeMatchesDisplayGetSize() throws Throwable { + mActivityRule.runOnUiThread(() -> { + Activity activity = mActivityRule.getActivity(); + final WindowMetrics metrics = activity.getWindowManager().getCurrentWindowMetrics(); + final Rect legacyBounds = WindowMetricsHelper + .getBoundsExcludingNavigationBarAndCutout(metrics); + + final Point expectedSize = new Point(); + activity.getDisplay().getSize(expectedSize); + + assertEquals(expectedSize.x, legacyBounds.width()); + assertEquals(expectedSize.y, legacyBounds.height()); + }); + } + + public static class TestActivity extends Activity { } +} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java index daeb731ad457d..0ae640dd79108 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java @@ -58,6 +58,7 @@ import android.os.Handler; import android.util.Log; import android.util.Pair; import android.util.Size; +import android.view.Display; import android.view.Surface; import android.view.WindowManager; @@ -2210,14 +2211,14 @@ public class CameraTestUtils extends Assert { } public static Size getPreviewSizeBound(WindowManager windowManager, Size bound) { - Rect windowBounds = windowManager.getCurrentWindowMetrics().getBounds(); + Display display = windowManager.getDefaultDisplay(); - int width = windowBounds.width(); - int height = windowBounds.height(); + int width = display.getWidth(); + int height = display.getHeight(); if (height > width) { height = width; - width = windowBounds.height(); + width = display.getHeight(); } if (bound.getWidth() <= width && diff --git a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java index 210fdc662bed0..3e053d59ded40 100644 --- a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java +++ b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java @@ -20,9 +20,9 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; -import android.util.LongSparseArray; import android.util.DisplayMetrics; import android.util.Log; +import android.util.LongSparseArray; import android.util.Pools.Pool; import android.util.Pools.SynchronizedPool; import android.view.View; @@ -163,7 +163,7 @@ public class TiledImageRenderer { private static boolean isHighResolution(Context context) { DisplayMetrics metrics = new DisplayMetrics(); - context.getDisplayNoVerify().getMetrics(metrics); + context.getDisplayNoVerify().getRealMetrics(metrics); return metrics.heightPixels > 2048 || metrics.widthPixels > 2048; } diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java index fe9f60fe2859c..d8184f2d169d6 100644 --- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java +++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java @@ -40,6 +40,7 @@ import android.util.Log; import android.view.Display; import android.view.View; import android.widget.Toast; +import android.window.WindowMetricsHelper; import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; @@ -357,7 +358,8 @@ public class WallpaperCropActivity extends Activity { // Get the crop boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; - Rect windowBounds = getWindowManager().getCurrentWindowMetrics().getBounds(); + Rect windowBounds = WindowMetricsHelper.getBoundsExcludingNavigationBarAndCutout( + getWindowManager().getCurrentWindowMetrics()); boolean isPortrait = windowBounds.width() < windowBounds.height(); Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(), diff --git a/test-runner/src/android/test/TouchUtils.java b/test-runner/src/android/test/TouchUtils.java index f2f0be73c0109..1122cd8fc3417 100644 --- a/test-runner/src/android/test/TouchUtils.java +++ b/test-runner/src/android/test/TouchUtils.java @@ -16,16 +16,23 @@ package android.test; +import static android.view.WindowInsets.Type.displayCutout; +import static android.view.WindowInsets.Type.navigationBars; + import android.app.Activity; import android.app.Instrumentation; -import android.graphics.Point; +import android.graphics.Insets; +import android.graphics.Rect; import android.os.SystemClock; -import android.view.Display; +import android.util.Size; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.WindowMetrics; /** * Reusable methods for generating touch events. These methods can be used with @@ -59,13 +66,12 @@ public class TouchUtils { * @param activity The activity that is in the foreground of the test case */ public static void dragQuarterScreenDown(InstrumentationTestCase test, Activity activity) { - Display display = activity.getWindowManager().getDefaultDisplay(); - final Point size = new Point(); - display.getSize(size); + WindowManager wm = activity.getWindowManager(); + final Size size = getSizeExcludingNavigationBarAndCutout(wm.getCurrentWindowMetrics()); - final float x = size.x / 2.0f; - final float fromY = size.y * 0.5f; - final float toY = size.y * 0.75f; + final float x = size.getWidth() / 2.0f; + final float fromY = size.getHeight() * 0.5f; + final float toY = size.getHeight() * 0.75f; drag(test, x, x, fromY, toY, 4); } @@ -89,17 +95,27 @@ public class TouchUtils { * @param activity The activity that is in the foreground of the test case */ public static void dragQuarterScreenUp(InstrumentationTestCase test, Activity activity) { - Display display = activity.getWindowManager().getDefaultDisplay(); - final Point size = new Point(); - display.getSize(size); + WindowManager wm = activity.getWindowManager(); + final Size size = getSizeExcludingNavigationBarAndCutout(wm.getCurrentWindowMetrics()); - final float x = size.x / 2.0f; - final float fromY = size.y * 0.5f; - final float toY = size.y * 0.25f; + final float x = size.getWidth() / 2.0f; + final float fromY = size.getHeight() * 0.5f; + final float toY = size.getHeight() * 0.25f; drag(test, x, x, fromY, toY, 4); } + private static Size getSizeExcludingNavigationBarAndCutout(WindowMetrics windowMetrics) { + WindowInsets windowInsets = windowMetrics.getWindowInsets(); + final Insets insetsWithCutout = windowInsets + .getInsetsIgnoringVisibility(navigationBars() | displayCutout()); + final int insetsWidth = insetsWithCutout.left + insetsWithCutout.right; + final int insetsHeight = insetsWithCutout.top + insetsWithCutout.bottom; + + Rect bounds = windowMetrics.getBounds(); + return new Size(bounds.width() - insetsWidth, bounds.height() - insetsHeight); + } + /** * Scroll a ViewGroup to the bottom by repeatedly calling * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)} @@ -222,8 +238,9 @@ public class TouchUtils { */ public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v, int stepCount) { - int screenHeight = - activity.getWindowManager().getCurrentWindowMetrics().getBounds().height(); + WindowManager wm = activity.getWindowManager(); + final int screenHeight = getSizeExcludingNavigationBarAndCutout( + wm.getCurrentWindowMetrics()).getHeight(); int[] xy = new int[2]; v.getLocationOnScreen(xy); diff --git a/tests/GamePerformance/src/android/gameperformance/CustomControlView.java b/tests/GamePerformance/src/android/gameperformance/CustomControlView.java index e63736b9ee61b..8d11a416c8a8b 100644 --- a/tests/GamePerformance/src/android/gameperformance/CustomControlView.java +++ b/tests/GamePerformance/src/android/gameperformance/CustomControlView.java @@ -15,20 +15,21 @@ */ package android.gameperformance; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; - import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.WorkerThread; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Point; import android.graphics.drawable.AnimationDrawable; +import android.view.WindowManager; import android.widget.AbsoluteLayout; import android.widget.ImageView; +import android.window.WindowMetricsHelper; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; /** * View that holds requested number of UI controls as ImageView with an infinite animation. @@ -42,9 +43,10 @@ public class CustomControlView extends AbsoluteLayout { public CustomControlView(@NonNull Context context) { super(context); - final Point size = new Point(); - context.getDisplay().getSize(size); - mPerRowControlCount = size.x / CONTROL_DIMENSION; + final WindowManager wm = context.getSystemService(WindowManager.class); + final int width = WindowMetricsHelper.getBoundsExcludingNavigationBarAndCutout( + wm.getCurrentWindowMetrics()).width(); + mPerRowControlCount = width / CONTROL_DIMENSION; } /** diff --git a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java index 31532a2268001..8afe8411a790b 100644 --- a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java +++ b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java @@ -39,6 +39,7 @@ import android.view.WindowManagerGlobal; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; +import android.window.WindowMetricsHelper; public class MirrorSurfaceActivity extends Activity implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener { @@ -89,7 +90,8 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe .getSystemService(WindowManager.class); mIWm = WindowManagerGlobal.getWindowManagerService(); - Rect windowBounds = mWm.getCurrentWindowMetrics().getBounds(); + Rect windowBounds = WindowMetricsHelper.getBoundsExcludingNavigationBarAndCutout( + mWm.getCurrentWindowMetrics()); mWindowBounds.set(0, 0, windowBounds.width(), windowBounds.height()); mScaleText = findViewById(R.id.scale); diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java index 0dd45bad8a016..ea803f2aba8b5 100644 --- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java +++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java @@ -48,7 +48,8 @@ public final class FrameworksTestsFilter extends SelectTest { "android.view.InsetsStateTest", "android.view.WindowMetricsTest", "android.view.PendingInsetsControllerTest", - "android.app.WindowContextTest" + "android.app.WindowContextTest", + "android.window.WindowMetricsHelperTest" }; public FrameworksTestsFilter(Bundle testArgs) {