summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Chen <charlesccchen@google.com>2020-02-17 01:04:27 +0000
committerCharles Chen <charlesccchen@google.com>2020-02-24 03:46:51 +0000
commit1ac295ec0878ce435ef55ec56cb710c2f8f2ce80 (patch)
tree5f4013637da531ce727b301449fc83791762d94f
parentb629d69db047c40f2b110f2d73ad8ceb1b32ea68 (diff)
Revert "Revert "Always get window insets from server""
This reverts commit 288e1bd0455132643cf6e1dc482913f430e56bba. The previous implementation of computeWindowInsets is to use last view from WM#addView, which may be invalid because the last added view is removed and throws NPE when getting property from the invalid view. In this CL, we change the approach to always obtain window insets from server. fixes: 148789183 fixes: 149480577 Test: atest FrameworksCoreTests:WindowMetricsTest Test: atest WindowMetricsTests Change-Id: I6db5970d14ac9eebe0ab0df65cb1300515ad1754 (cherry picked from commit 6bb2d4f68c02121850c62a83349aa35d36497afa)
-rw-r--r--core/java/android/view/WindowManagerImpl.java38
-rw-r--r--core/tests/coretests/AndroidManifest.xml3
-rw-r--r--core/tests/coretests/src/android/view/WindowMetricsTest.java96
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java57
-rw-r--r--tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java1
5 files changed, 149 insertions, 46 deletions
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d40f505f87a0..6435b42efca0 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,6 +16,11 @@
package android.view;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+
import android.annotation.NonNull;
import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
@@ -67,10 +72,6 @@ public final class WindowManagerImpl implements WindowManager {
private IBinder mDefaultToken;
- private boolean mIsViewAdded;
- private View mLastView;
- private WindowManager.LayoutParams mLastParams;
-
public WindowManagerImpl(Context context) {
this(context, null);
}
@@ -102,9 +103,6 @@ public final class WindowManagerImpl implements WindowManager {
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow);
- mIsViewAdded = true;
- mLastView = view;
- mLastParams = (WindowManager.LayoutParams) params;
}
@Override
@@ -247,21 +245,19 @@ public final class WindowManagerImpl implements WindowManager {
}
private WindowInsets computeWindowInsets() {
- // TODO(window-context): This can only be properly implemented
+ // TODO(b/118118435): This can only be properly implemented
// once we flip the new insets mode flag.
- if (mParentWindow != null) {
- if (mParentWindow.getDecorView().isAttachedToWindow()) {
- return mParentWindow.getDecorView().getViewRootImpl()
- .getWindowInsets(true /* forceConstruct */);
- }
- return getWindowInsetsFromServer(mParentWindow.getAttributes());
- }
- if (mIsViewAdded) {
- return mLastView.getViewRootImpl().getWindowInsets(true /* forceConstruct */);
- } else {
- return getWindowInsetsFromServer(new WindowManager.LayoutParams());
- }
-
+ // Initialize params which used for obtaining all system insets.
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+ params.token = (mParentWindow != null) ? mParentWindow.getContext().getActivityToken()
+ : mContext.getActivityToken();
+ params.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ params.setFitInsetsTypes(0);
+ params.setFitInsetsSides(0);
+
+ return getWindowInsetsFromServer(params);
}
private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 718ca46a4f18..b42fce02cede 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -138,6 +138,9 @@
<!-- vr test permissions -->
<uses-permission android:name="android.permission.RESTRICTED_VR_ACCESS" />
+ <!-- WindowMetricsTest permissions -->
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
<application android:theme="@style/Theme" android:supportsRtl="true">
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
diff --git a/core/tests/coretests/src/android/view/WindowMetricsTest.java b/core/tests/coretests/src/android/view/WindowMetricsTest.java
new file mode 100644
index 000000000000..fa6886075bfd
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.view;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+import android.util.Size;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link WindowManager#getCurrentWindowMetrics()} and
+ * {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:WindowMetricsTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@FlakyTest(bugId = 148789183, detail = "Remove after confirmed it's stable.")
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowMetricsTest {
+ private Context mWindowContext;
+ private WindowManager mWm;
+
+ @Before
+ public void setUp() {
+ final Context insetContext = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext();
+ final Display display = insetContext.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY);
+ mWindowContext = insetContext.createDisplayContext(display)
+ .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
+ mWm = mWindowContext.getSystemService(WindowManager.class);
+ }
+
+ @Test
+ public void testAddViewANdRemoveView_GetMetrics_DoNotCrash() {
+ final View view = new View(mWindowContext);
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ Handler.getMain().runWithScissors(() -> {
+ mWm.addView(view, params);
+ // Check get metrics do not crash.
+ WindowMetrics currentMetrics = mWm.getCurrentWindowMetrics();
+ WindowMetrics maxMetrics = mWm.getMaximumWindowMetrics();
+ verifyMetricsSanity(currentMetrics, maxMetrics);
+
+ mWm.removeViewImmediate(view);
+ // Check get metrics do not crash.
+ currentMetrics = mWm.getCurrentWindowMetrics();
+ maxMetrics = mWm.getMaximumWindowMetrics();
+ verifyMetricsSanity(currentMetrics, maxMetrics);
+ }, 0);
+ }
+
+ private static void verifyMetricsSanity(WindowMetrics currentMetrics,
+ WindowMetrics maxMetrics) {
+ Size currentSize = currentMetrics.getSize();
+ Size maxSize = maxMetrics.getSize();
+
+ assertTrue(maxSize.getWidth() >= currentSize.getWidth());
+ assertTrue(maxSize.getHeight() >= currentSize.getHeight());
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9cb5ba7a74a4..e0f8f0e9aee9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8075,32 +8075,39 @@ public class WindowManagerService extends IWindowManager.Stub
public void getWindowInsets(WindowManager.LayoutParams attrs,
int displayId, Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper displayCutout) {
- synchronized (mGlobalLock) {
- final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
- if (dc == null) {
- throw new WindowManager.InvalidDisplayException("Display#" + displayId
- + "could not be found!");
- }
- final WindowToken windowToken = dc.getWindowToken(attrs.token);
- final ActivityRecord activity;
- if (windowToken != null && windowToken.asActivityRecord() != null) {
- activity = windowToken.asActivityRecord();
- } else {
- activity = null;
- }
- final Rect taskBounds = new Rect();
- final boolean floatingStack;
- if (activity != null && activity.getTask() != null) {
- final Task task = activity.getTask();
- task.getBounds(taskBounds);
- floatingStack = task.isFloating();
- } else {
- floatingStack = false;
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = getDisplayContentOrCreate(displayId, attrs.token);
+ if (dc == null) {
+ throw new WindowManager.InvalidDisplayException("Display#" + displayId
+ + "could not be found!");
+ }
+ final WindowToken windowToken = dc.getWindowToken(attrs.token);
+ final ActivityRecord activity;
+ if (windowToken != null && windowToken.asActivityRecord() != null) {
+ activity = windowToken.asActivityRecord();
+ } else {
+ activity = null;
+ }
+ final Rect taskBounds;
+ final boolean floatingStack;
+ if (activity != null && activity.getTask() != null) {
+ final Task task = activity.getTask();
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ floatingStack = task.isFloating();
+ } else {
+ taskBounds = null;
+ floatingStack = false;
+ }
+ final DisplayFrames displayFrames = dc.mDisplayFrames;
+ final DisplayPolicy policy = dc.getDisplayPolicy();
+ policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
+ new Rect(), outContentInsets, outStableInsets, displayCutout);
}
- final DisplayFrames displayFrames = dc.mDisplayFrames;
- final DisplayPolicy policy = dc.getDisplayPolicy();
- policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
- new Rect(), outContentInsets, outStableInsets, displayCutout);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
}
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 26916bcffcfb..aed62d046896 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
@@ -46,6 +46,7 @@ public final class FrameworksTestsFilter extends SelectTest {
"android.view.InsetsSourceTest",
"android.view.InsetsSourceConsumerTest",
"android.view.InsetsStateTest",
+ "android.view.WindowMetricsTest"
};
public FrameworksTestsFilter(Bundle testArgs) {