From d17d47377b0a5c11c3dbfa5f36c10553d43b4192 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 23 Jan 2024 17:34:34 -0800 Subject: [PATCH 1/6] make static, todo fix tests --- .../gradle/wrapper/gradle-wrapper.properties | 5 + .../platform/SingleViewPresentation.java | 120 ++++++++++-------- 2 files changed, 69 insertions(+), 56 deletions(-) create mode 100644 shell/platform/android/gradle/wrapper/gradle-wrapper.properties diff --git a/shell/platform/android/gradle/wrapper/gradle-wrapper.properties b/shell/platform/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000..41dfb87909a87 --- /dev/null +++ b/shell/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index b7ca559ac7c64..4915936bb6da7 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -22,17 +22,17 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.WindowMetrics; import android.view.accessibility.AccessibilityEvent; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import io.flutter.Log; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import java.util.concurrent.Executor; +import java.util.function.Consumer; /* * A presentation used for hosting a single Android view in a virtual display. @@ -359,7 +359,7 @@ public Object getSystemService(String name) { private WindowManager getWindowManager() { if (windowManager == null) { - windowManager = windowManagerHandler.getWindowManager(); + windowManager = windowManagerHandler; } return windowManager; } @@ -377,21 +377,17 @@ private boolean isCalledFromAlertDialog() { } /* - * A dynamic proxy handler for a WindowManager with custom overrides. + * A static proxy handler for a WindowManager with custom overrides. * * The presentation's window manager delegates all calls to the default window manager. * WindowManager#addView calls triggered by views that are attached to the virtual display are crashing * (see: https://github.com/flutter/flutter/issues/20714). This was triggered when selecting text in an embedded * WebView (as the selection handles are implemented as popup windows). * - * This dynamic proxy overrides the addView, removeView, removeViewImmediate, and updateViewLayout methods - * to prevent these crashes. - * - * This will be more efficient as a static proxy that's not using reflection, but as the engine is currently - * not being built against the latest Android SDK we cannot override all relevant method. - * Tracking issue for upgrading the engine's Android sdk: https://github.com/flutter/flutter/issues/20717 + * This static proxy overrides the addView, removeView, removeViewImmediate, and updateViewLayout methods + * to prevent these crashes, and passes all other calls to the delegate. */ - static class WindowManagerHandler implements InvocationHandler { + class WindowManagerHandler implements WindowManager { private static final String TAG = "PlatformViewsController"; private final WindowManager delegate; @@ -402,72 +398,84 @@ static class WindowManagerHandler implements InvocationHandler { fakeWindowRootView = fakeWindowViewGroup; } - public WindowManager getWindowManager() { - return (WindowManager) - Proxy.newProxyInstance( - WindowManager.class.getClassLoader(), new Class[] {WindowManager.class}, this); + @Override + public Display getDefaultDisplay() { + return delegate.getDefaultDisplay(); } @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - switch (method.getName()) { - case "addView": - addView(args); - return null; - case "removeView": - removeView(args); - return null; - case "removeViewImmediate": - removeViewImmediate(args); - return null; - case "updateViewLayout": - updateViewLayout(args); - return null; - } - try { - return method.invoke(delegate, args); - } catch (InvocationTargetException e) { - throw e.getCause(); + public void removeViewImmediate(View view) { + if (fakeWindowRootView == null) { + Log.w(TAG, "Embedded view called removeViewImmediate while detached from presentation"); + return; } + view.clearAnimation(); + fakeWindowRootView.removeView(view); } - private void addView(Object[] args) { + @Override + public void addView(View view, ViewGroup.LayoutParams params) { if (fakeWindowRootView == null) { Log.w(TAG, "Embedded view called addView while detached from presentation"); return; } - View view = (View) args[0]; - WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) args[1]; - fakeWindowRootView.addView(view, layoutParams); + fakeWindowRootView.addView(view, params); } - private void removeView(Object[] args) { + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (fakeWindowRootView == null) { - Log.w(TAG, "Embedded view called removeView while detached from presentation"); + Log.w(TAG, "Embedded view called updateViewLayout while detached from presentation"); return; } - View view = (View) args[0]; - fakeWindowRootView.removeView(view); + fakeWindowRootView.updateViewLayout(view, params); } - private void removeViewImmediate(Object[] args) { + @Override + public void removeView(View view) { if (fakeWindowRootView == null) { - Log.w(TAG, "Embedded view called removeViewImmediate while detached from presentation"); + Log.w(TAG, "Embedded view called removeView while detached from presentation"); return; } - View view = (View) args[0]; - view.clearAnimation(); fakeWindowRootView.removeView(view); } - private void updateViewLayout(Object[] args) { - if (fakeWindowRootView == null) { - Log.w(TAG, "Embedded view called updateViewLayout while detached from presentation"); - return; - } - View view = (View) args[0]; - WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) args[1]; - fakeWindowRootView.updateViewLayout(view, layoutParams); + @RequiresApi(api = Build.VERSION_CODES.R) + @NonNull + @Override + public WindowMetrics getCurrentWindowMetrics() { + return delegate.getCurrentWindowMetrics(); + } + + @RequiresApi(api = Build.VERSION_CODES.R) + @NonNull + @Override + public WindowMetrics getMaximumWindowMetrics() { + return delegate.getMaximumWindowMetrics(); + } + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public boolean isCrossWindowBlurEnabled() { + return delegate.isCrossWindowBlurEnabled(); + } + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public void addCrossWindowBlurEnabledListener(@NonNull Consumer listener) { + delegate.addCrossWindowBlurEnabledListener(listener); + } + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public void addCrossWindowBlurEnabledListener(@NonNull Executor executor, @NonNull Consumer listener) { + delegate.addCrossWindowBlurEnabledListener(executor, listener); + } + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public void removeCrossWindowBlurEnabledListener(@NonNull Consumer listener) { + delegate.removeCrossWindowBlurEnabledListener(listener); } } From 3783c9b1db0e57766ad883db167ac4534eeee6ff Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 23 Jan 2024 17:35:14 -0800 Subject: [PATCH 2/6] format --- .../io/flutter/plugin/platform/SingleViewPresentation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index 4915936bb6da7..031a24182d525 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -468,7 +468,8 @@ public void addCrossWindowBlurEnabledListener(@NonNull Consumer listene @RequiresApi(api = Build.VERSION_CODES.S) @Override - public void addCrossWindowBlurEnabledListener(@NonNull Executor executor, @NonNull Consumer listener) { + public void addCrossWindowBlurEnabledListener( + @NonNull Executor executor, @NonNull Consumer listener) { delegate.addCrossWindowBlurEnabledListener(executor, listener); } From 71a7e42525664c81561e7fa91dda64bd206255f8 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 23 Jan 2024 22:41:49 -0800 Subject: [PATCH 3/6] Remove file --- .../android/gradle/wrapper/gradle-wrapper.properties | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 shell/platform/android/gradle/wrapper/gradle-wrapper.properties diff --git a/shell/platform/android/gradle/wrapper/gradle-wrapper.properties b/shell/platform/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 41dfb87909a87..0000000000000 --- a/shell/platform/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists From faf0f6dad6372bdf1a159654317a257b00c2ff4a Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 20 Feb 2024 16:26:27 -0800 Subject: [PATCH 4/6] write some tests --- .../platform/SingleViewPresentation.java | 9 +- .../platform/SingleViewPresentationTest.java | 112 ++++++++++++++++++ 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index 031a24182d525..5e4958e21a84e 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -30,6 +30,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.annotation.VisibleForTesting; + import io.flutter.Log; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -164,7 +166,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager windowManagerDelegate = (WindowManager) getContext().getSystemService(WINDOW_SERVICE); state.windowManagerHandler = - new WindowManagerHandler(windowManagerDelegate, state.fakeWindowViewGroup); + new WindowManagerHandler(windowManagerDelegate, state.fakeWindowViewGroup); } container = new FrameLayout(getContext()); @@ -385,9 +387,10 @@ private boolean isCalledFromAlertDialog() { * WebView (as the selection handles are implemented as popup windows). * * This static proxy overrides the addView, removeView, removeViewImmediate, and updateViewLayout methods - * to prevent these crashes, and passes all other calls to the delegate. + * to prevent these crashes, and forwards all other calls to the delegate. */ - class WindowManagerHandler implements WindowManager { + @VisibleForTesting + static class WindowManagerHandler implements WindowManager { private static final String TAG = "PlatformViewsController"; private final WindowManager delegate; diff --git a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java index d27e08bbbdc97..5e2e23da55f44 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java @@ -10,12 +10,17 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.annotation.TargetApi; import android.content.Context; import android.hardware.display.DisplayManager; import android.view.Display; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -23,6 +28,9 @@ import org.junit.runner.RunWith; import org.robolectric.annotation.Config; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + @Config(manifest = Config.NONE) @RunWith(AndroidJUnit4.class) @TargetApi(P) @@ -83,4 +91,108 @@ public void returnsOuterContextInputMethodManager_createDisplayContext() { // Android OS (or Robolectric's shadow, in this case). assertEquals(expected, actual); } + + @Test + @Config(minSdk = R) + public void windowManagerHandler_passesCorrectlyToFakeWindowViewGroup() { + // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. + WindowManager mockWindowManager = mock(WindowManager.class); + SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup + = mock(SingleViewPresentation.FakeWindowViewGroup.class); + + View mockView = mock(View.class); + ViewGroup.LayoutParams mockLayoutParams = mock(ViewGroup.LayoutParams.class); + + SingleViewPresentation.WindowManagerHandler windowManagerHandler + = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); + + // removeViewImmediate + windowManagerHandler.removeViewImmediate(mockView); + verify(mockView).clearAnimation(); + verify(mockFakeWindowViewGroup).removeView(mockView); + verifyNoInteractions(mockWindowManager); + + // addView + windowManagerHandler.addView(mockView, mockLayoutParams); + verify(mockFakeWindowViewGroup).addView(mockView, mockLayoutParams); + verifyNoInteractions(mockWindowManager); + + // updateViewLayout + windowManagerHandler.updateViewLayout(mockView, mockLayoutParams); + verify(mockFakeWindowViewGroup).updateViewLayout(mockView, mockLayoutParams); + verifyNoInteractions(mockWindowManager); + + // removeView + windowManagerHandler.updateViewLayout(mockView, mockLayoutParams); + verify(mockFakeWindowViewGroup).removeView(mockView); + verifyNoInteractions(mockWindowManager); + } + + @Test + @Config(minSdk = R) + public void windowManagerHandler_logAndReturnEarly_whenFakeWindowViewGroupIsNull() { + // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. + WindowManager mockWindowManager = mock(WindowManager.class); + + View mockView = mock(View.class); + ViewGroup.LayoutParams mockLayoutParams = mock(ViewGroup.LayoutParams.class); + + SingleViewPresentation.WindowManagerHandler windowManagerHandler + = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, null); + + // removeViewImmediate + windowManagerHandler.removeViewImmediate(mockView); + verifyNoInteractions(mockView); + verifyNoInteractions(mockWindowManager); + + // addView + windowManagerHandler.addView(mockView, mockLayoutParams); + verifyNoInteractions(mockWindowManager); + + // updateViewLayout + windowManagerHandler.updateViewLayout(mockView, mockLayoutParams); + verifyNoInteractions(mockWindowManager); + + // removeView + windowManagerHandler.updateViewLayout(mockView, mockLayoutParams); + verifyNoInteractions(mockWindowManager); + } + + @Test + @Config(minSdk = R) + public void windowManagerHandler_forwardsAllOtherCallsToDelegate() { + // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. + WindowManager mockWindowManager = mock(WindowManager.class); + SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup + = mock(SingleViewPresentation.FakeWindowViewGroup.class); + + SingleViewPresentation.WindowManagerHandler windowManagerHandler + = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); + + // Verify that all other calls get forwarded to the delegate. + Executor mockExecutor = mock(Executor.class); + @SuppressWarnings("Unchecked cast") + Consumer mockListener = (Consumer) mock(Consumer.class); + + windowManagerHandler.getDefaultDisplay(); + verify(mockWindowManager).getDefaultDisplay(); + + windowManagerHandler.getCurrentWindowMetrics(); + verify(mockWindowManager).getCurrentWindowMetrics(); + + windowManagerHandler.getMaximumWindowMetrics(); + verify(mockWindowManager).getMaximumWindowMetrics(); + + windowManagerHandler.isCrossWindowBlurEnabled(); + verify(mockWindowManager).isCrossWindowBlurEnabled(); + + windowManagerHandler.addCrossWindowBlurEnabledListener(mockListener); + verify(mockWindowManager).addCrossWindowBlurEnabledListener(mockListener); + + windowManagerHandler.addCrossWindowBlurEnabledListener(mockExecutor, mockListener); + verify(mockWindowManager).addCrossWindowBlurEnabledListener(mockExecutor, mockListener); + + windowManagerHandler.removeCrossWindowBlurEnabledListener(mockListener); + verify(mockWindowManager).removeCrossWindowBlurEnabledListener(mockListener); + } } From 952037f5574de2dd45e2e7512c6014e90d442662 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 20 Feb 2024 16:27:13 -0800 Subject: [PATCH 5/6] format --- .../platform/SingleViewPresentation.java | 3 +-- .../platform/SingleViewPresentationTest.java | 25 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index 5e4958e21a84e..801c397a02b6c 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -31,7 +31,6 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; - import io.flutter.Log; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -166,7 +165,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager windowManagerDelegate = (WindowManager) getContext().getSystemService(WINDOW_SERVICE); state.windowManagerHandler = - new WindowManagerHandler(windowManagerDelegate, state.fakeWindowViewGroup); + new WindowManagerHandler(windowManagerDelegate, state.fakeWindowViewGroup); } container = new FrameLayout(getContext()); diff --git a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java index 5e2e23da55f44..61ebb5b6417f7 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java @@ -24,13 +24,12 @@ import android.view.inputmethod.InputMethodManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.util.concurrent.Executor; +import java.util.function.Consumer; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; -import java.util.concurrent.Executor; -import java.util.function.Consumer; - @Config(manifest = Config.NONE) @RunWith(AndroidJUnit4.class) @TargetApi(P) @@ -97,14 +96,14 @@ public void returnsOuterContextInputMethodManager_createDisplayContext() { public void windowManagerHandler_passesCorrectlyToFakeWindowViewGroup() { // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. WindowManager mockWindowManager = mock(WindowManager.class); - SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup - = mock(SingleViewPresentation.FakeWindowViewGroup.class); + SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup = + mock(SingleViewPresentation.FakeWindowViewGroup.class); View mockView = mock(View.class); ViewGroup.LayoutParams mockLayoutParams = mock(ViewGroup.LayoutParams.class); - SingleViewPresentation.WindowManagerHandler windowManagerHandler - = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); + SingleViewPresentation.WindowManagerHandler windowManagerHandler = + new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); // removeViewImmediate windowManagerHandler.removeViewImmediate(mockView); @@ -137,8 +136,8 @@ public void windowManagerHandler_logAndReturnEarly_whenFakeWindowViewGroupIsNull View mockView = mock(View.class); ViewGroup.LayoutParams mockLayoutParams = mock(ViewGroup.LayoutParams.class); - SingleViewPresentation.WindowManagerHandler windowManagerHandler - = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, null); + SingleViewPresentation.WindowManagerHandler windowManagerHandler = + new SingleViewPresentation.WindowManagerHandler(mockWindowManager, null); // removeViewImmediate windowManagerHandler.removeViewImmediate(mockView); @@ -163,11 +162,11 @@ public void windowManagerHandler_logAndReturnEarly_whenFakeWindowViewGroupIsNull public void windowManagerHandler_forwardsAllOtherCallsToDelegate() { // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. WindowManager mockWindowManager = mock(WindowManager.class); - SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup - = mock(SingleViewPresentation.FakeWindowViewGroup.class); + SingleViewPresentation.FakeWindowViewGroup mockFakeWindowViewGroup = + mock(SingleViewPresentation.FakeWindowViewGroup.class); - SingleViewPresentation.WindowManagerHandler windowManagerHandler - = new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); + SingleViewPresentation.WindowManagerHandler windowManagerHandler = + new SingleViewPresentation.WindowManagerHandler(mockWindowManager, mockFakeWindowViewGroup); // Verify that all other calls get forwarded to the delegate. Executor mockExecutor = mock(Executor.class); From 647c33727ba39f7614fa535d6a1739bfdfe65454 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 20 Feb 2024 17:10:05 -0800 Subject: [PATCH 6/6] fix tests, suppress deprecation warnings in test --- .../io/flutter/plugin/platform/SingleViewPresentation.java | 1 + .../plugin/platform/SingleViewPresentationTest.java | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index 801c397a02b6c..d8dc53049a5be 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -401,6 +401,7 @@ static class WindowManagerHandler implements WindowManager { } @Override + @Deprecated public Display getDefaultDisplay() { return delegate.getDefaultDisplay(); } diff --git a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java index 61ebb5b6417f7..d99d344568d25 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/SingleViewPresentationTest.java @@ -7,6 +7,7 @@ import static android.os.Build.VERSION_CODES.KITKAT; import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.R; +import static android.os.Build.VERSION_CODES.S; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -157,8 +158,12 @@ public void windowManagerHandler_logAndReturnEarly_whenFakeWindowViewGroupIsNull verifyNoInteractions(mockWindowManager); } + // This section tests that WindowManagerHandler forwards all of the non-special case calls to the + // delegate WindowManager. Because this must include some deprecated WindowManager method calls + // (because the proxy overrides every method), we suppress deprecation warnings here. @Test - @Config(minSdk = R) + @Config(minSdk = S) + @SuppressWarnings("deprecation") public void windowManagerHandler_forwardsAllOtherCallsToDelegate() { // Mock the WindowManager and FakeWindowViewGroup that get used by the WindowManagerHandler. WindowManager mockWindowManager = mock(WindowManager.class);