// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.embedding.android;

import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;

/**
 * {@code Fragment} which displays a Flutter UI that takes up all available {@code Fragment} space.
 * <p>
 * WARNING: THIS CLASS IS EXPERIMENTAL. DO NOT SHIP A DEPENDENCY ON THIS CODE.
 * IF YOU USE IT, WE WILL BREAK YOU.
 * <p>
 * Using a {@code FlutterFragment} requires forwarding a number of calls from an {@code Activity} to
 * ensure that the internal Flutter app behaves as expected:
 * <ol>
 *   <li>{@link android.app.Activity#onPostResume()}</li>
 *   <li>{@link android.app.Activity#onBackPressed()}</li>
 *   <li>{@link android.app.Activity#onRequestPermissionsResult(int, String[], int[])} ()}</li>
 *   <li>{@link android.app.Activity#onNewIntent(Intent)} ()}</li>
 *   <li>{@link android.app.Activity#onUserLeaveHint()}</li>
 *   <li>{@link android.app.Activity#onTrimMemory(int)}</li>
 * </ol>
 * Additionally, when starting an {@code Activity} for a result from this {@code Fragment}, be sure
 * to invoke {@link Fragment#startActivityForResult(Intent, int)} rather than
 * {@link android.app.Activity#startActivityForResult(Intent, int)}. If the {@code Activity} version
 * of the method is invoked then this {@code Fragment} will never receive its
 * {@link Fragment#onActivityResult(int, int, Intent)} callback.
 * <p>
 * If convenient, consider using a {@link FlutterActivity} instead of a {@code FlutterFragment} to
 * avoid the work of forwarding calls.
 * <p>
 * If Flutter is needed in a location that can only use a {@code View}, consider using a
 * {@link FlutterView}. Using a {@link FlutterView} requires forwarding some calls from an
 * {@code Activity}, as well as forwarding lifecycle calls from an {@code Activity} or a
 * {@code Fragment}.
 */
public class FlutterFragment extends Fragment {
  private static final String TAG = "FlutterFragment";

  protected static final String ARG_DART_ENTRYPOINT = "dart_entrypoint";
  protected static final String ARG_INITIAL_ROUTE = "initial_route";
  protected static final String ARG_APP_BUNDLE_PATH = "app_bundle_path";
  protected static final String ARG_FLUTTER_INITIALIZATION_ARGS = "initialization_args";
  protected static final String ARG_FLUTTERVIEW_RENDER_MODE = "flutterview_render_mode";
  protected static final String ARG_FLUTTERVIEW_TRANSPARENCY_MODE = "flutterview_transparency_mode";
  protected static final String ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY = "should_attach_engine_to_activity";

  /**
   * Builder that creates a new {@code FlutterFragment} with {@code arguments} that correspond
   * to the values set on this {@code Builder}.
   * <p>
   * To create a {@code FlutterFragment} with default {@code arguments}, invoke {@code build()}
   * without setting any builder properties:
   * {@code
   *   FlutterFragment fragment = new FlutterFragment.Builder().build();
   * }
   * <p>
   * Subclasses of {@code FlutterFragment} that do not introduce any new arguments can use this
   * {@code Builder} to construct instances of the subclass without subclassing this {@code Builder}.
   * {@code
   *   MyFlutterFragment f = new FlutterFragment.Builder(MyFlutterFragment.class)
   *     .someProperty(...)
   *     .someOtherProperty(...)
   *     .build<MyFlutterFragment>();
   * }
   * <p>
   * Subclasses of {@code FlutterFragment} that introduce new arguments should subclass this
   * {@code Builder} to add the new properties:
   * <ol>
   *   <li>Ensure the {@code FlutterFragment} subclass has a no-arg constructor.</li>
   *   <li>Subclass this {@code Builder}.</li>
   *   <li>Override the new {@code Builder}'s no-arg constructor and invoke the super constructor
   *   to set the {@code FlutterFragment} subclass: {@code
   *     public MyBuilder() {
   *       super(MyFlutterFragment.class);
   *     }
   *   }</li>
   *   <li>Add appropriate property methods for the new properties.</li>
   *   <li>Override {@link Builder#createArgs()}, call through to the super method, then add
   *   the new properties as arguments in the {@link Bundle}.</li>
   * </ol>
   * Once a {@code Builder} subclass is defined, the {@code FlutterFragment} subclass can be
   * instantiated as follows.
   * {@code
   *   MyFlutterFragment f = new MyBuilder()
   *     .someExistingProperty(...)
   *     .someNewProperty(...)
   *     .build<MyFlutterFragment>();
   * }
   */
  public static class Builder {
    private final Class<? extends FlutterFragment> fragmentClass;
    private String dartEntrypoint = "main";
    private String initialRoute = "/";
    private String appBundlePath = null;
    private FlutterShellArgs shellArgs = null;
    private FlutterView.RenderMode renderMode = FlutterView.RenderMode.surface;
    private FlutterView.TransparencyMode transparencyMode = FlutterView.TransparencyMode.transparent;
    private boolean shouldAttachEngineToActivity = true;

    /**
     * Constructs a {@code Builder} that is configured to construct an instance of
     * {@code FlutterFragment}.
     */
    public Builder() {
      fragmentClass = FlutterFragment.class;
    }

    /**
     * Constructs a {@code Builder} that is configured to construct an instance of
     * {@code subclass}, which extends {@code FlutterFragment}.
     */
    public Builder(@NonNull Class<? extends FlutterFragment> subclass) {
      fragmentClass = subclass;
    }

    /**
     * The name of the initial Dart method to invoke, defaults to "main".
     */
    @NonNull
    public Builder dartEntrypoint(@NonNull String dartEntrypoint) {
      this.dartEntrypoint = dartEntrypoint;
      return this;
    }

    /**
     * The initial route that a Flutter app will render in this {@link FlutterFragment},
     * defaults to "/".
     */
    @NonNull
    public Builder initialRoute(@NonNull String initialRoute) {
      this.initialRoute = initialRoute;
      return this;
    }

    /**
     * The path to the app bundle which contains the Dart app to execute, defaults
     * to {@link FlutterMain#findAppBundlePath(Context)}
     */
    @NonNull
    public Builder appBundlePath(@NonNull String appBundlePath) {
      this.appBundlePath = appBundlePath;
      return this;
    }

    /**
     * Any special configuration arguments for the Flutter engine
     */
    @NonNull
    public Builder flutterShellArgs(@NonNull FlutterShellArgs shellArgs) {
      this.shellArgs = shellArgs;
      return this;
    }

    /**
     * Render Flutter either as a {@link FlutterView.RenderMode#surface} or a
     * {@link FlutterView.RenderMode#texture}. You should use {@code surface} unless
     * you have a specific reason to use {@code texture}. {@code texture} comes with
     * a significant performance impact, but {@code texture} can be displayed
     * beneath other Android {@code View}s and animated, whereas {@code surface}
     * cannot.
     */
    @NonNull
    public Builder renderMode(@NonNull FlutterView.RenderMode renderMode) {
      this.renderMode = renderMode;
      return this;
    }

    /**
     * Support a {@link FlutterView.TransparencyMode#transparent} background within {@link FlutterView},
     * or force an {@link FlutterView.TransparencyMode#opaque} background.
     * <p>
     * See {@link FlutterView.TransparencyMode} for implications of this selection.
     */
    @NonNull
    public Builder transparencyMode(@NonNull FlutterView.TransparencyMode transparencyMode) {
      this.transparencyMode = transparencyMode;
      return this;
    }

    /**
     * Whether or not this {@code FlutterFragment} should automatically attach its
     * {@code Activity} as a control surface for its {@link FlutterEngine}.
     * <p>
     * Control surfaces are used to provide Android resources and lifecycle events to
     * plugins that are attached to the {@link FlutterEngine}. If {@code shouldAttachEngineToActivity}
     * is true then this {@code FlutterFragment} will connect its {@link FlutterEngine} to the
     * surrounding {@code Activity}, along with any plugins that are registered with that
     * {@link FlutterEngine}. This allows plugins to access the {@code Activity}, as well as
     * receive {@code Activity}-specific calls, e.g., {@link android.app.Activity#onNewIntent(Intent)}.
     * If {@code shouldAttachEngineToActivity} is false, then this {@code FlutterFragment} will not
     * automatically manage the connection between its {@link FlutterEngine} and the surrounding
     * {@code Activity}. The {@code Activity} will need to be manually connected to this
     * {@code FlutterFragment}'s {@link FlutterEngine} by the app developer. See
     * {@link FlutterEngine#getActivityControlSurface()}.
     * <p>
     * One reason that a developer might choose to manually manage the relationship between the
     * {@code Activity} and {@link FlutterEngine} is if the developer wants to move the
     * {@link FlutterEngine} somewhere else. For example, a developer might want the
     * {@link FlutterEngine} to outlive the surrounding {@code Activity} so that it can be used
     * later in a different {@code Activity}. To accomplish this, the {@link FlutterEngine} will
     * need to be disconnected from the surrounding {@code Activity} at an unusual time, preventing
     * this {@code FlutterFragment} from correctly managing the relationship between the
     * {@link FlutterEngine} and the surrounding {@code Activity}.
     * <p>
     * Another reason that a developer might choose to manually manage the relationship between the
     * {@code Activity} and {@link FlutterEngine} is if the developer wants to prevent, or explicitly
     * control when the {@link FlutterEngine}'s plugins have access to the surrounding {@code Activity}.
     * For example, imagine that this {@code FlutterFragment} only takes up part of the screen and
     * the app developer wants to ensure that none of the Flutter plugins are able to manipulate
     * the surrounding {@code Activity}. In this case, the developer would not want the
     * {@link FlutterEngine} to have access to the {@code Activity}, which can be accomplished by
     * setting {@code shouldAttachEngineToActivity} to {@code false}.
     */
    @NonNull
    public Builder shouldAttachEngineToActivity(boolean shouldAttachEngineToActivity) {
      this.shouldAttachEngineToActivity = shouldAttachEngineToActivity;
      return this;
    }

    /**
     * Creates a {@link Bundle} of arguments that are assigned to the new {@code FlutterFragment}.
     * <p>
     * Subclasses should override this method to add new properties to the {@link Bundle}. Subclasses
     * must call through to the super method to collect all existing property values.
     */
    @NonNull
    protected Bundle createArgs() {
      Bundle args = new Bundle();
      args.putString(ARG_INITIAL_ROUTE, initialRoute);
      args.putString(ARG_APP_BUNDLE_PATH, appBundlePath);
      args.putString(ARG_DART_ENTRYPOINT, dartEntrypoint);
      // TODO(mattcarroll): determine if we should have an explicit FlutterTestFragment instead of conflating.
      if (null != shellArgs) {
        args.putStringArray(ARG_FLUTTER_INITIALIZATION_ARGS, shellArgs.toArray());
      }
      args.putString(ARG_FLUTTERVIEW_RENDER_MODE, renderMode != null ? renderMode.name() : FlutterView.RenderMode.surface.name());
      args.putString(ARG_FLUTTERVIEW_TRANSPARENCY_MODE, transparencyMode != null ? transparencyMode.name() : FlutterView.TransparencyMode.transparent.name());
      args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity);
      return args;
    }

    /**
     * Constructs a new {@code FlutterFragment} (or a subclass) that is configured based on
     * properties set on this {@code Builder}.
     */
    @NonNull
    public <T extends FlutterFragment> T build() {
      try {
        @SuppressWarnings("unchecked")
        T frag = (T) fragmentClass.getDeclaredConstructor().newInstance();
        if (frag == null) {
          throw new RuntimeException("The FlutterFragment subclass sent in the constructor ("
              + fragmentClass.getCanonicalName() + ") does not match the expected return type.");
        }

        Bundle args = createArgs();
        frag.setArguments(args);

        return frag;
      } catch (Exception e) {
        throw new RuntimeException("Could not instantiate FlutterFragment subclass (" + fragmentClass.getName() + ")", e);
      }
    }
  }

  @Nullable
  private FlutterEngine flutterEngine;
  private boolean isFlutterEngineFromActivity;
  @Nullable
  private FlutterView flutterView;
  @Nullable
  private PlatformPlugin platformPlugin;

  private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() {
    @Override
    public void onFirstFrameRendered() {
      // Notify our subclasses that the first frame has been rendered.
      FlutterFragment.this.onFirstFrameRendered();

      // Notify our owning Activity that the first frame has been rendered.
      FragmentActivity fragmentActivity = getActivity();
      if (fragmentActivity != null && fragmentActivity instanceof OnFirstFrameRenderedListener) {
        OnFirstFrameRenderedListener activityAsListener = (OnFirstFrameRenderedListener) fragmentActivity;
        activityAsListener.onFirstFrameRendered();
      }
    }
  };

  public FlutterFragment() {
    // Ensure that we at least have an empty Bundle of arguments so that we don't
    // need to continually check for null arguments before grabbing one.
    setArguments(new Bundle());
  }

  /**
   * The {@link FlutterEngine} that backs the Flutter content presented by this {@code Fragment}.
   *
   * @return the {@link FlutterEngine} held by this {@code Fragment}
   */
  @Nullable
  public FlutterEngine getFlutterEngine() {
    return flutterEngine;
  }

  @Override
  public void onAttach(Context context) {
    super.onAttach(context);

    initializeFlutter(getContextCompat());

    // When "retain instance" is true, the FlutterEngine will survive configuration
    // changes. Therefore, we create a new one only if one does not already exist.
    if (flutterEngine == null) {
      setupFlutterEngine();
    }

    // Regardless of whether or not a FlutterEngine already existed, the PlatformPlugin
    // is bound to a specific Activity. Therefore, it needs to be created and configured
    // every time this Fragment attaches to a new Activity.
    // TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes
    //                    control of the entire window. This is unacceptable for non-fullscreen
    //                    use-cases.
    platformPlugin = new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel());

    if (shouldAttachEngineToActivity()) {
      // Notify any plugins that are currently attached to our FlutterEngine that they
      // are now attached to an Activity.
      // TODO(mattcarroll): send in a real lifecycle.
      flutterEngine.getActivityControlSurface().attachToActivity(getActivity(), null);
    }
  }

  private void initializeFlutter(@NonNull Context context) {
    String[] flutterShellArgsArray = getArguments().getStringArray(ARG_FLUTTER_INITIALIZATION_ARGS);
    FlutterShellArgs flutterShellArgs = new FlutterShellArgs(
        flutterShellArgsArray != null ? flutterShellArgsArray : new String[] {}
    );

    FlutterMain.ensureInitializationComplete(context.getApplicationContext(), flutterShellArgs.toArray());
  }

  /**
   * Obtains a reference to a FlutterEngine to back this {@code FlutterFragment}.
   * <p>
   * First, {@code FlutterFragment} subclasses are given an opportunity to provide a
   * {@link FlutterEngine} by overriding {@link #createFlutterEngine(Context)}.
   * <p>
   * Second, the {@link FragmentActivity} that owns this {@code FlutterFragment} is
   * given the opportunity to provide a {@link FlutterEngine} as a {@link FlutterEngineProvider}.
   * <p>
   * If subclasses do not provide a {@link FlutterEngine}, and the owning {@link FragmentActivity}
   * does not implement {@link FlutterEngineProvider} or chooses to return {@code null}, then a new
   * {@link FlutterEngine} is instantiated.
   */
  private void setupFlutterEngine() {
    // First, defer to subclasses for a custom FlutterEngine.
    flutterEngine = createFlutterEngine(getContextCompat());
    if (flutterEngine != null) {
      return;
    }

    // Second, defer to the FragmentActivity that owns us to see if it wants to provide a
    // FlutterEngine.
    FragmentActivity attachedActivity = getActivity();
    if (attachedActivity instanceof FlutterEngineProvider) {
      // Defer to the Activity that owns us to provide a FlutterEngine.
      Log.d(TAG, "Deferring to attached Activity to provide a FlutterEngine.");
      FlutterEngineProvider flutterEngineProvider = (FlutterEngineProvider) attachedActivity;
      flutterEngine = flutterEngineProvider.getFlutterEngine(getContext());
      if (flutterEngine != null) {
        isFlutterEngineFromActivity = true;
      }
      return;
    }

    // Neither our subclass, nor our owning Activity wanted to provide a custom FlutterEngine.
    // Create a FlutterEngine to back our FlutterView.
    Log.d(TAG, "No subclass or our attached Activity provided a custom FlutterEngine. Creating a "
        + "new FlutterEngine for this FlutterFragment.");
    flutterEngine = new FlutterEngine(getContext());
    isFlutterEngineFromActivity = false;
  }

  /**
   * Hook for subclasses to return a {@link FlutterEngine} with whatever configuration
   * is desired.
   * <p>
   * This method takes precedence for creation of a {@link FlutterEngine} over any owning
   * {@code Activity} that may implement {@link FlutterEngineProvider}.
   * <p>
   * Consider returning a cached {@link FlutterEngine} instance from this method to avoid the
   * typical warm-up time that a new {@link FlutterEngine} instance requires.
   * <p>
   * If null is returned then a new default {@link FlutterEngine} will be created to back this
   * {@code FlutterFragment}.
   */
  @Nullable
  protected FlutterEngine createFlutterEngine(@NonNull Context context) {
    return null;
  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    flutterView = new FlutterView(getContext(), getRenderMode(), getTransparencyMode());
    flutterView.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener);
    return flutterView;
  }

  /**
   * Starts running Dart within the FlutterView for the first time.
   *
   * Reloading/restarting Dart within a given FlutterView is not supported. If this method is
   * invoked while Dart is already executing then it does nothing.
   *
   * {@code flutterEngine} must be non-null when invoking this method.
   */
  private void doInitialFlutterViewRun() {
    if (flutterEngine.getDartExecutor().isExecutingDart()) {
      // No warning is logged because this situation will happen on every config
      // change if the developer does not choose to retain the Fragment instance.
      // So this is expected behavior in many cases.
      return;
    }

    // The engine needs to receive the Flutter app's initial route before executing any
    // Dart code to ensure that the initial route arrives in time to be applied.
    if (getInitialRoute() != null) {
      flutterEngine.getNavigationChannel().setInitialRoute(getInitialRoute());
    }

    // Configure the Dart entrypoint and execute it.
    DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint(
        getResources().getAssets(),
        getAppBundlePath(),
        getDartEntrypointFunctionName()
    );
    flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
  }

  /**
   * Returns the initial route that should be rendered within Flutter, once the Flutter app starts.
   *
   * Defaults to {@code null}, which signifies a route of "/" in Flutter.
   */
  @Nullable
  protected String getInitialRoute() {
    return getArguments().getString(ARG_INITIAL_ROUTE);
  }

  /**
   * Returns the file path to the desired Flutter app's bundle of code.
   *
   * Defaults to {@link FlutterMain#findAppBundlePath(Context)}.
   */
  @NonNull
  protected String getAppBundlePath() {
    return getArguments().getString(ARG_APP_BUNDLE_PATH, FlutterMain.findAppBundlePath(getContextCompat()));
  }

  /**
   * Returns the name of the Dart method that this {@code FlutterFragment} should execute to
   * start a Flutter app.
   *
   * Defaults to "main".
   */
  @NonNull
  protected String getDartEntrypointFunctionName() {
    return getArguments().getString(ARG_DART_ENTRYPOINT, "main");
  }

  /**
   * Returns the desired {@link FlutterView.RenderMode} for the {@link FlutterView} displayed in
   * this {@code FlutterFragment}.
   *
   * Defaults to {@link FlutterView.RenderMode#surface}.
   */
  @NonNull
  protected FlutterView.RenderMode getRenderMode() {
    String renderModeName = getArguments().getString(ARG_FLUTTERVIEW_RENDER_MODE, FlutterView.RenderMode.surface.name());
    return FlutterView.RenderMode.valueOf(renderModeName);
  }

  /**
   * Returns the desired {@link FlutterView.TransparencyMode} for the {@link FlutterView} displayed in
   * this {@code FlutterFragment}.
   * <p>
   * Defaults to {@link FlutterView.TransparencyMode#transparent}.
   */
  @NonNull
  protected FlutterView.TransparencyMode getTransparencyMode() {
    String transparencyModeName = getArguments().getString(ARG_FLUTTERVIEW_TRANSPARENCY_MODE, FlutterView.TransparencyMode.transparent.name());
    return FlutterView.TransparencyMode.valueOf(transparencyModeName);
  }

  @Override
  public void onStart() {
    super.onStart();
    Log.d(TAG, "onStart()");

    // We post() the code that attaches the FlutterEngine to our FlutterView because there is
    // some kind of blocking logic on the native side when the surface is connected. That lag
    // causes launching Activitys to wait a second or two before launching. By post()'ing this
    // behavior we are able to move this blocking logic to after the Activity's launch.
    // TODO(mattcarroll): figure out how to avoid blocking the MAIN thread when connecting a surface
    new Handler().post(new Runnable() {
      @Override
      public void run() {
        flutterView.attachToFlutterEngine(flutterEngine);

        // TODO(mattcarroll): the following call should exist here, but the plugin system needs to be revamped.
        //                    The existing attach() method does not know how to handle this kind of FlutterView.
        //flutterEngine.getPlugins().attach(this, getActivity());

        doInitialFlutterViewRun();
      }
    });
  }

  @Override
  public void onResume() {
    super.onResume();
    Log.d(TAG, "onResume()");
    flutterEngine.getLifecycleChannel().appIsResumed();
  }

  // TODO(mattcarroll): determine why this can't be in onResume(). Comment reason, or move if possible.
  public void onPostResume() {
    Log.d(TAG, "onPostResume()");
    if (flutterEngine != null) {
      // TODO(mattcarroll): find a better way to handle the update of UI overlays than calling through
      //                    to platformPlugin. We're implicitly entangling the Window, Activity, Fragment,
      //                    and engine all with this one call.
      platformPlugin.onPostResume();
    } else {
      Log.w(TAG, "onPostResume() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  @Override
  public void onPause() {
    super.onPause();
    Log.d(TAG, "onPause()");
    flutterEngine.getLifecycleChannel().appIsInactive();
  }

  @Override
  public void onStop() {
    super.onStop();
    Log.d(TAG, "onStop()");
    flutterEngine.getLifecycleChannel().appIsPaused();
    flutterView.detachFromFlutterEngine();
  }

  @Override
  public void onDestroyView() {
    super.onDestroyView();
    Log.d(TAG, "onDestroyView()");
    flutterView.removeOnFirstFrameRenderedListener(onFirstFrameRenderedListener);
  }

  @Override
  public void onDetach() {
    super.onDetach();
    Log.d(TAG, "onDetach()");

    if (shouldAttachEngineToActivity()) {
      // Notify plugins that they are no longer attached to an Activity.
      // TODO(mattcarroll): differentiate between detaching for config changes and otherwise.
      flutterEngine.getActivityControlSurface().detachFromActivity();
    }

    // Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
    // and this Fragment's Activity.
    platformPlugin = null;

    // Destroy our FlutterEngine if we're not set to retain it.
    if (!retainFlutterEngineAfterFragmentDestruction() && !isFlutterEngineFromActivity) {
      flutterEngine.destroy();
      flutterEngine = null;
    }
  }

  /**
   * Returns true if the {@link FlutterEngine} within this {@code FlutterFragment} should outlive
   * the {@code FlutterFragment}, itself.
   *
   * Defaults to false. This method can be overridden in subclasses to retain the
   * {@link FlutterEngine}.
   */
  // TODO(mattcarroll): consider a dynamic determination of this preference based on whether the
  //                    engine was created automatically, or if the engine was provided manually.
  //                    Manually provided engines should probably not be destroyed.
  protected boolean retainFlutterEngineAfterFragmentDestruction() {
    return false;
  }

  protected boolean shouldAttachEngineToActivity() {
    return getArguments().getBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY);
  }

  /**
   * The hardware back button was pressed.
   *
   * See {@link android.app.Activity#onBackPressed()}
   */
  public void onBackPressed() {
    Log.d(TAG, "onBackPressed()");
    if (flutterEngine != null) {
      flutterEngine.getNavigationChannel().popRoute();
    } else {
      Log.w(TAG, "Invoked onBackPressed() before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * The result of a permission request has been received.
   *
   * See {@link android.app.Activity#onRequestPermissionsResult(int, String[], int[])}
   *
   * @param requestCode identifier passed with the initial permission request
   * @param permissions permissions that were requested
   * @param grantResults permission grants or denials
   */
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (flutterEngine != null) {
      flutterEngine.getActivityControlSurface().onRequestPermissionsResult(requestCode, permissions, grantResults);
    } else {
      Log.w(TAG, "onRequestPermissionResult() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * A new Intent was received by the {@link android.app.Activity} that currently owns this
   * {@link Fragment}.
   *
   * See {@link android.app.Activity#onNewIntent(Intent)}
   *
   * @param intent new Intent
   */
  public void onNewIntent(@NonNull Intent intent) {
    if (flutterEngine != null) {
      flutterEngine.getActivityControlSurface().onNewIntent(intent);
    } else {
      Log.w(TAG, "onNewIntent() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * A result has been returned after an invocation of {@link Fragment#startActivityForResult(Intent, int)}.
   *
   * @param requestCode request code sent with {@link Fragment#startActivityForResult(Intent, int)}
   * @param resultCode code representing the result of the {@code Activity} that was launched
   * @param data any corresponding return data, held within an {@code Intent}
   */
  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (flutterEngine != null) {
      flutterEngine.getActivityControlSurface().onActivityResult(requestCode, resultCode, data);
    } else {
      Log.w(TAG, "onActivityResult() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * The {@link android.app.Activity} that owns this {@link Fragment} is about to go to the background
   * as the result of a user's choice/action, i.e., not as the result of an OS decision.
   *
   * See {@link android.app.Activity#onUserLeaveHint()}
   */
  public void onUserLeaveHint() {
    if (flutterEngine != null) {
      flutterEngine.getActivityControlSurface().onUserLeaveHint();
    } else {
      Log.w(TAG, "onUserLeaveHint() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * Callback invoked when memory is low.
   *
   * This implementation forwards a memory pressure warning to the running Flutter app.
   *
   * @param level level
   */
  public void onTrimMemory(int level) {
    if (flutterEngine != null) {
      // Use a trim level delivered while the application is running so the
      // framework has a chance to react to the notification.
      if (level == TRIM_MEMORY_RUNNING_LOW) {
        flutterEngine.getSystemChannel().sendMemoryPressureWarning();
      }
    } else {
      Log.w(TAG, "onTrimMemory() invoked before FlutterFragment was attached to an Activity.");
    }
  }

  /**
   * Callback invoked when memory is low.
   *
   * This implementation forwards a memory pressure warning to the running Flutter app.
   */
  @Override
  public void onLowMemory() {
    super.onLowMemory();
    flutterEngine.getSystemChannel().sendMemoryPressureWarning();
  }

  @NonNull
  private Context getContextCompat() {
    return Build.VERSION.SDK_INT >= 23
      ? getContext()
      : getActivity();
  }

  /**
   * Invoked after the {@link FlutterView} within this {@code FlutterFragment} renders its first
   * frame.
   * <p>
   * The owning {@code Activity} is also sent this message, if it implements
   * {@link OnFirstFrameRenderedListener}. This method is invoked before the {@code Activity}'s
   * version.
   */
  protected void onFirstFrameRendered() {}

  /**
   * Provides a {@link FlutterEngine} instance to be used by a {@code FlutterFragment}.
   * <p>
   * {@link FlutterEngine} instances require significant time to warm up. Therefore, a developer
   * might choose to hold onto an existing {@link FlutterEngine} and connect it to various
   * {@link FlutterActivity}s and/or {@code FlutterFragments}.
   * <p>
   * If the {@link FragmentActivity} that owns this {@code FlutterFragment} implements
   * {@code FlutterEngineProvider}, that {@link FlutterActivity} will be given an opportunity
   * to provide a {@link FlutterEngine} instead of the {@code FlutterFragment} creating a
   * new one. The {@link FragmentActivity} can provide an existing, pre-warmed {@link FlutterEngine},
   * if desired.
   * <p>
   * See {@link #setupFlutterEngine()} for more information.
   */
  public interface FlutterEngineProvider {
    /**
     * Returns the {@link FlutterEngine} that should be used by a child {@code FlutterFragment}.
     * <p>
     * This method may return a new {@link FlutterEngine}, an existing, cached {@link FlutterEngine},
     * or null to express that the {@code FlutterEngineProvider} would like the {@code FlutterFragment}
     * to provide its own {@code FlutterEngine} instance.
     */
    @Nullable
    FlutterEngine getFlutterEngine(@NonNull Context context);
  }
}
