diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 16497674240de..060221650243f 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -542,8 +542,7 @@ private View createFlutterView() { /* inflater=*/ null, /* container=*/ null, /* savedInstanceState=*/ null, - /*flutterViewId=*/ FLUTTER_VIEW_ID, - /*shouldDelayFirstAndroidViewDraw=*/ getRenderMode() == RenderMode.surface); + /*flutterViewId=*/ FLUTTER_VIEW_ID); } private void configureStatusBarForFullscreenFlutterExperience() { diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index d153a26d7cfc8..b6f5eb465a03d 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -15,7 +15,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver.OnPreDrawListener; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -68,17 +67,15 @@ private static final String TAG = "FlutterActivityAndFragmentDelegate"; private static final String FRAMEWORK_RESTORATION_BUNDLE_KEY = "framework"; private static final String PLUGINS_RESTORATION_BUNDLE_KEY = "plugins"; - private static final int FLUTTER_SPLASH_VIEW_FALLBACK_ID = 486947586; // The FlutterActivity or FlutterFragment that is delegating most of its calls // to this FlutterActivityAndFragmentDelegate. @NonNull private Host host; @Nullable private FlutterEngine flutterEngine; + @Nullable private FlutterSplashView flutterSplashView; @Nullable private FlutterView flutterView; @Nullable private PlatformPlugin platformPlugin; - @VisibleForTesting @Nullable OnPreDrawListener activePreDrawListener; private boolean isFlutterEngineFromHost; - private boolean isFlutterUiDisplayed; @NonNull private final FlutterUiDisplayListener flutterUiDisplayListener = @@ -86,13 +83,11 @@ @Override public void onFlutterUiDisplayed() { host.onFlutterUiDisplayed(); - isFlutterUiDisplayed = true; } @Override public void onFlutterUiNoLongerDisplayed() { host.onFlutterUiNoLongerDisplayed(); - isFlutterUiDisplayed = false; } }; @@ -259,16 +254,6 @@ void onAttach(@NonNull Context context) { * *
{@code inflater} and {@code container} may be null when invoked from an {@code Activity}. * - *
{@code shouldDelayFirstAndroidViewDraw} determines whether to set up an {@link - * android.view.ViewTreeObserver.OnPreDrawListener}, which will defer the current drawing pass - * till after the Flutter UI has been displayed. This results in more accurate timings reported - * with Android tools, such as "Displayed" timing printed with `am start`. - * - *
Note that it should only be set to true when {@code Host#getRenderMode()} is {@code - * RenderMode.surface}. This parameter is also ignored, disabling the delay should the legacy - * {@code Host#provideSplashScreen()} be non-null. See Android Splash Migration. - * *
This method: * *
See {#link FlutterActivityAndFragmentDelegate#onCreateView} for more details. - */ - @NonNull - public NewEngineFragmentBuilder shouldDelayFirstAndroidViewDraw( - boolean shouldDelayFirstAndroidViewDraw) { - this.shouldDelayFirstAndroidViewDraw = shouldDelayFirstAndroidViewDraw; - return this; - } - /** * Creates a {@link Bundle} of arguments that are assigned to the new {@code FlutterFragment}. * @@ -427,7 +410,6 @@ protected Bundle createArgs() { args.putBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, true); args.putBoolean( ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, shouldAutomaticallyHandleOnBackPressed); - args.putBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW, shouldDelayFirstAndroidViewDraw); return args; } @@ -514,7 +496,6 @@ public static class CachedEngineFragmentBuilder { private TransparencyMode transparencyMode = TransparencyMode.transparent; private boolean shouldAttachEngineToActivity = true; private boolean shouldAutomaticallyHandleOnBackPressed = false; - private boolean shouldDelayFirstAndroidViewDraw = false; private CachedEngineFragmentBuilder(@NonNull String engineId) { this(FlutterFragment.class, engineId); @@ -640,18 +621,6 @@ public CachedEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed( return this; } - /** - * Whether to delay the Android drawing pass till after the Flutter UI has been displayed. - * - *
See {#link FlutterActivityAndFragmentDelegate#onCreateView} for more details.
- */
- @NonNull
- public CachedEngineFragmentBuilder shouldDelayFirstAndroidViewDraw(
- @NonNull boolean shouldDelayFirstAndroidViewDraw) {
- this.shouldDelayFirstAndroidViewDraw = shouldDelayFirstAndroidViewDraw;
- return this;
- }
-
/**
* Creates a {@link Bundle} of arguments that are assigned to the new {@code FlutterFragment}.
*
@@ -673,7 +642,6 @@ protected Bundle createArgs() {
args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity);
args.putBoolean(
ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, shouldAutomaticallyHandleOnBackPressed);
- args.putBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW, shouldDelayFirstAndroidViewDraw);
return args;
}
@@ -759,11 +727,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return delegate.onCreateView(
- inflater,
- container,
- savedInstanceState,
- /*flutterViewId=*/ FLUTTER_VIEW_ID,
- shouldDelayFirstAndroidViewDraw());
+ inflater, container, savedInstanceState, /*flutterViewId=*/ FLUTTER_VIEW_ID);
}
@Override
@@ -1303,12 +1267,6 @@ public boolean popSystemNavigator() {
return false;
}
- @VisibleForTesting
- @NonNull
- boolean shouldDelayFirstAndroidViewDraw() {
- return getArguments().getBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW);
- }
-
private boolean stillAttachedForEvent(String event) {
if (delegate == null) {
Log.w(TAG, "FlutterFragment " + hashCode() + " " + event + " called after release.");
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
index 52c65ca855d45..74e008448872f 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
@@ -424,7 +424,6 @@ protected FlutterFragment createFlutterFragment() {
backgroundMode == BackgroundMode.opaque
? TransparencyMode.opaque
: TransparencyMode.transparent;
- final boolean shouldDelayFirstAndroidViewDraw = renderMode == RenderMode.surface;
if (getCachedEngineId() != null) {
Log.v(
@@ -448,7 +447,6 @@ protected FlutterFragment createFlutterFragment() {
.handleDeeplinking(shouldHandleDeeplinking())
.shouldAttachEngineToActivity(shouldAttachEngineToActivity())
.destroyEngineWithFragment(shouldDestroyEngineWithHost())
- .shouldDelayFirstAndroidViewDraw(shouldDelayFirstAndroidViewDraw)
.build();
} else {
Log.v(
@@ -478,7 +476,6 @@ protected FlutterFragment createFlutterFragment() {
.renderMode(renderMode)
.transparencyMode(transparencyMode)
.shouldAttachEngineToActivity(shouldAttachEngineToActivity())
- .shouldDelayFirstAndroidViewDraw(shouldDelayFirstAndroidViewDraw)
.build();
}
}
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
index 112b3736a3080..5dfd509230e49 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
@@ -2,9 +2,7 @@
import static android.content.ComponentCallbacks2.*;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThrows;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.notNull;
@@ -17,8 +15,6 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
@@ -90,7 +86,7 @@ public void itSendsLifecycleEventsToFlutter() {
// We're testing lifecycle behaviors, which require/expect that certain methods have already
// been executed by the time they run. Therefore, we run those expected methods first.
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
// --- Execute the behavior under test ---
// By the time an Activity/Fragment is started, we don't expect any lifecycle messages
@@ -168,7 +164,7 @@ public void itUsesCachedEngineWhenProvided() {
// --- Execute the behavior under test ---
// The FlutterEngine is obtained in onAttach().
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
@@ -224,7 +220,7 @@ public void itGivesHostAnOpportunityToConfigureFlutterSurfaceView() {
// --- Execute the behavior under test ---
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
// Verify that the host was asked to configure a FlutterSurfaceView.
verify(mockHost, times(1)).onFlutterSurfaceViewCreated(notNull(FlutterSurfaceView.class));
@@ -253,7 +249,7 @@ public void itGivesHostAnOpportunityToConfigureFlutterTextureView() {
// --- Execute the behavior under test ---
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, false);
+ delegate.onCreateView(null, null, null, 0);
// Verify that the host was asked to configure a FlutterTextureView.
verify(customMockHost, times(1)).onFlutterTextureViewCreated(notNull(FlutterTextureView.class));
@@ -286,7 +282,7 @@ public void itSendsInitialRouteToFlutter() {
// --- Execute the behavior under test ---
// The initial route is sent in onStart().
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
// Verify that the navigation channel was given our initial route.
@@ -310,7 +306,7 @@ public void itExecutesDartEntrypointProvidedByHost() {
// --- Execute the behavior under test ---
// Dart is executed in onStart().
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
// Verify that the host's Dart entrypoint was used.
@@ -339,7 +335,7 @@ public void itUsesDefaultFlutterLoaderAppBundlePathWhenUnspecified() {
// --- Execute the behavior under test ---
// Dart is executed in onStart().
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
// Verify that the host's Dart entrypoint was used.
@@ -394,7 +390,7 @@ public void itDoesNotAttachFlutterToTheActivityIfNotDesired() {
// Make sure all of the other lifecycle methods can run safely as well
// without a valid Activity
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
delegate.onPause();
@@ -755,7 +751,7 @@ public void itDestroysItsOwnEngineIfHostRequestsIt() {
// --- Execute the behavior under test ---
// Push the delegate through all lifecycle methods all the way to destruction.
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
delegate.onPause();
@@ -779,7 +775,7 @@ public void itDoesNotDestroyItsOwnEngineWhenHostSaysNotTo() {
// --- Execute the behavior under test ---
// Push the delegate through all lifecycle methods all the way to destruction.
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
delegate.onPause();
@@ -810,7 +806,7 @@ public void itDestroysCachedEngineWhenHostRequestsIt() {
// --- Execute the behavior under test ---
// Push the delegate through all lifecycle methods all the way to destruction.
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
delegate.onPause();
@@ -842,7 +838,7 @@ public void itDoesNotDestroyCachedEngineWhenHostSaysNotTo() {
// --- Execute the behavior under test ---
// Push the delegate through all lifecycle methods all the way to destruction.
delegate.onAttach(RuntimeEnvironment.application);
- delegate.onCreateView(null, null, null, 0, true);
+ delegate.onCreateView(null, null, null, 0);
delegate.onStart();
delegate.onResume();
delegate.onPause();
@@ -854,77 +850,6 @@ public void itDoesNotDestroyCachedEngineWhenHostSaysNotTo() {
verify(cachedEngine, never()).destroy();
}
- @Test
- public void itDelaysFirstDrawWhenRequested() {
- // ---- Test setup ----
- FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);
-
- // We're testing lifecycle behaviors, which require/expect that certain methods have already
- // been executed by the time they run. Therefore, we run those expected methods first.
- delegate.onAttach(RuntimeEnvironment.application);
-
- // --- Execute the behavior under test ---
- boolean shouldDelayFirstAndroidViewDraw = true;
- delegate.onCreateView(null, null, null, 0, shouldDelayFirstAndroidViewDraw);
-
- assertNotNull(delegate.activePreDrawListener);
- }
-
- @Test
- public void itDoesNotDelayFirstDrawWhenNotRequested() {
- // ---- Test setup ----
- FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);
-
- // We're testing lifecycle behaviors, which require/expect that certain methods have already
- // been executed by the time they run. Therefore, we run those expected methods first.
- delegate.onAttach(RuntimeEnvironment.application);
-
- // --- Execute the behavior under test ---
- boolean shouldDelayFirstAndroidViewDraw = false;
- delegate.onCreateView(null, null, null, 0, shouldDelayFirstAndroidViewDraw);
-
- assertNull(delegate.activePreDrawListener);
- }
-
- @Test
- public void itThrowsWhenDelayingTheFirstDrawAndUsingATextureView() {
- // ---- Test setup ----
- when(mockHost.getRenderMode()).thenReturn(RenderMode.texture);
- FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);
-
- // We're testing lifecycle behaviors, which require/expect that certain methods have already
- // been executed by the time they run. Therefore, we run those expected methods first.
- delegate.onAttach(RuntimeEnvironment.application);
-
- // --- Execute the behavior under test ---
- boolean shouldDelayFirstAndroidViewDraw = true;
- assertThrows(
- IllegalArgumentException.class,
- () -> {
- delegate.onCreateView(null, null, null, 0, shouldDelayFirstAndroidViewDraw);
- });
- }
-
- @Test
- public void itDoesNotDelayTheFirstDrawWhenRequestedAndWithAProvidedSplashScreen() {
- when(mockHost.provideSplashScreen())
- .thenReturn(new DrawableSplashScreen(new ColorDrawable(Color.GRAY)));
-
- // ---- Test setup ----
- // Create the real object that we're testing.
- FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);
-
- // We're testing lifecycle behaviors, which require/expect that certain methods have already
- // been executed by the time they run. Therefore, we run those expected methods first.
- delegate.onAttach(RuntimeEnvironment.application);
-
- // --- Execute the behavior under test ---
- boolean shouldDelayFirstAndroidViewDraw = true;
- delegate.onCreateView(null, null, null, 0, shouldDelayFirstAndroidViewDraw);
-
- assertNull(delegate.activePreDrawListener);
- }
-
/**
* Creates a mock {@link io.flutter.embedding.engine.FlutterEngine}.
*
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
index b88460b3cb423..ae42af77c5c38 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
@@ -291,31 +291,6 @@ public void itCanBeDetachedFromTheEngineAndStopSendingFurtherEvents() {
verify(mockDelegate, times(1)).onDetach();
}
- @Test
- public void itDelaysDrawing() {
- Intent intent = FlutterActivity.createDefaultIntent(RuntimeEnvironment.application);
- ActivityController