diff options
author | Charles Chen <charlesccchen@google.com> | 2020-02-05 16:33:40 +0800 |
---|---|---|
committer | Charles Chen <charlesccchen@google.com> | 2020-02-12 11:09:25 +0800 |
commit | 3e857ec536f54fc08ab59bedcd878a819ebd71c3 (patch) | |
tree | 9f63c96f64bbc86d591374f239a39a0bcf0cf37e | |
parent | 848b6d4441d7b1444b0410e68b949d9236fb5099 (diff) |
Always get window insets from server
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
Test: atest FrameworksCoreTests:WindowMetricsTest
Test: atest WindowMetricsTests
Change-Id: Ic5512c31f86c597d99e13d29df654d3f527d6b55
4 files changed, 94 insertions, 16 deletions
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 4365d1f5194a..25bdbb22ea6c 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -16,6 +16,9 @@ package android.view; +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 +70,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 +101,6 @@ public final class WindowManagerImpl implements WindowManager { public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); - mIsViewAdded = true; - mLastView = view; - mLastParams = (WindowManager.LayoutParams) params; } @Override @@ -250,18 +246,15 @@ public final class WindowManagerImpl implements WindowManager { // TODO(window-context): 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()); - } + return getWindowInsetsFromServer(getDefaultParams()); + } + private static WindowManager.LayoutParams getDefaultParams() { + final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; + return params; } private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) { diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 59335a595334..be94f02dc3e7 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..d2eb8f5f5573 --- /dev/null +++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java @@ -0,0 +1,81 @@ +/* + * 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 android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.platform.test.annotations.Presubmit; + +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. + mWm.getCurrentWindowMetrics(); + mWm.getMaximumWindowMetrics(); + + mWm.removeViewImmediate(view); + // Check get metrics do not crash. + mWm.getCurrentWindowMetrics(); + mWm.getMaximumWindowMetrics(); + }, 0); + } +} 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 957216e17925..37842de92e79 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 @@ -45,6 +45,7 @@ public final class FrameworksTestsFilter extends SelectTest { "android.view.InsetsSourceTest", "android.view.InsetsSourceConsumerTest", "android.view.InsetsStateTest", + "android.view.WindowMetricsTest" }; public FrameworksTestsFilter(Bundle testArgs) { |