Repository: flutter
Issue: NewEngineFragmentBuilder and NewEngineInGroupFragmentBuilder in FlutterFragment should respect shouldDestroyEngineWithHost when using provideFlutterEngine
Labels: platform-android,engine,c: proposal,P2,team-android,triaged-android

### Use case

We use local_auth plugin which used androidx Biometric on Android.

androidx biometric force use fragment Activity, so we change our super class to FlutterFragmentActivity.

Previously, we override `getCachedEngineId` to used cached fragment, but this result in blank screen after put app in background for over one night.

Then we  remove `getCachedEngineId`, and use override of `provideFlutterEngine`.

Recently, when using monkey test on Android, we found crash log for flutter fragment like this:

```console
crash:
// CRASH: com.xxx.xxx.preseries.cn.univ (pid 28143) (dump time: 2024-01-05 00:34:21
// Version: 
// Long Msg: java.lang.AssertionError: The internal FlutterEngine created by FlutterFragment{c10f699} (940cd33c-d79f-4781-adf4-f4001eed9003 id=0x1 tag=flutter_fragment) has been attached to by another activity. To persist a FlutterEngine beyond the ownership of this activity, explicitly create a FlutterEngine
// 	at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.detachFromFlutterEngine(Unknown Source:40)
// 	at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.attachToActivity(Unknown Source:9)
// 	at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onAttach(Unknown Source:37)
// 	at io.flutter.embedding.android.FlutterFragment.onAttach(Unknown Source:11)
// 	at androidx.fragment.app.Fragment.performAttach(Unknown Source:49)
// 	at androidx.fragment.app.FragmentStateManager.attach(Unknown Source:186)
// 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(Unknown Source:134)
// 	at androidx.fragment.app.FragmentManager.executeOpsTogether(Unknown Source:347)
// 	at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(Unknown Source:81)
// 	at androidx.fragment.app.FragmentManager.execPendingActions(Unknown Source:21)
// 	at androidx.fragment.app.FragmentManager.dispatchStateChange(Unknown Source:38)
// 	at androidx.fragment.app.FragmentManager.dispatchActivityCreated(Unknown Source:11)
// 	at androidx.fragment.app.FragmentController.dispatchActivityCreated(Unknown Source:4)
// 	at androidx.fragment.app.FragmentActivity.onStart(Unknown Source:20)
// 	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1470)
// 	at android.app.Activity.performStart(Activity.java:8513)
// 	at android.app.ActivityThread.handleStartActivity(ActivityThread.java:4656)
// 	at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:235)
// 	at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:215)
// 	at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:187)
// 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:105)
// 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2928)
// 	at android.os.Handler.dispatchMessage(Handler.java:117)
// 	at android.os.Looper.loopOnce(Looper.java:205)
// 	at android.os.Looper.loop(Looper.java:293)
// 	at android.app.ActivityThread.main(ActivityThread.java:9596)
// 	at java.lang.reflect.Method.invoke(Native Method)
// 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
// 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1204)
// crashend

```

### Proposal

I checked the start process of FlutterFragmentActivity and found this:

method `ensureFlutterFragmentCreated` in FlutterFragmentActivity will call `createFlutterFragment`,
when `getCachedEngineId() != null` it will use `CachedEngineFragmentBuilder` to build the Fragment, which provide `destroyEngineWithFragment` method to hook the engine.

But when using  provideFlutterEngine, It will use NewEngineFragmentBuilder, which config `ARG_DESTROY_ENGINE_WITH_FRAGMENT` to true in `createArgs`.
```java
    @NonNull
    protected Bundle createArgs() {
      Bundle args = new Bundle();
      args.putString(ARG_CACHED_ENGINE_GROUP_ID, cachedEngineGroupId);
      args.putString(ARG_DART_ENTRYPOINT, dartEntrypoint);
      args.putString(ARG_INITIAL_ROUTE, initialRoute);
      args.putBoolean(ARG_HANDLE_DEEPLINKING, handleDeeplinking);
      args.putString(
          ARG_FLUTTERVIEW_RENDER_MODE,
          renderMode != null ? renderMode.name() : RenderMode.surface.name());
      args.putString(
          ARG_FLUTTERVIEW_TRANSPARENCY_MODE,
          transparencyMode != null ? transparencyMode.name() : TransparencyMode.transparent.name());
      args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity);
      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;
    }
```

The same issue with NewEngineInGroupFragmentBuilder.

In FlutterFragment `shouldDestroyEngineWithHost` method, it deal with the cached case and provided case in same process.
```java
  @Override
  public boolean shouldDestroyEngineWithHost() {
    boolean explicitDestructionRequested =
        getArguments().getBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, false);//Since NewEngineInGroupFragmentBuilder always put true, we got true here.
    if (getCachedEngineId() != null || delegate.isFlutterEngineFromHost()) {
      // Only destroy a cached engine if explicitly requested by app developer.
      return explicitDestructionRequested;
    } else {
      // If this Fragment created the FlutterEngine, destroy it by default unless
      // explicitly requested not to.
      return getArguments().getBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, true);
    }
  }
```
But because NewEngineFragmentBuilder not respect to what we configured in FlutterFragmentActivity with `shouldDestroyEngineWithHost` method, we got this issue.

I think we should respect cached engine and provided engine in both creation of fragment and `detachFromFlutterEngine` in 
`FlutterActivityAndFragmentDelegate`