5package io.flutter.embedding.engine;
9import android.content.BroadcastReceiver;
10import android.content.ContentProvider;
14import androidx.annotation.NonNull;
15import androidx.annotation.Nullable;
16import androidx.lifecycle.Lifecycle;
18import io.flutter.embedding.android.ExclusiveAppComponent;
19import io.flutter.embedding.engine.loader.FlutterLoader;
20import io.flutter.embedding.engine.plugins.FlutterPlugin;
21import io.flutter.embedding.engine.plugins.PluginRegistry;
22import io.flutter.embedding.engine.plugins.activity.ActivityAware;
23import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
24import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
25import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverAware;
26import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverControlSurface;
27import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverPluginBinding;
28import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderAware;
29import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderControlSurface;
30import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderPluginBinding;
31import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference;
32import io.flutter.embedding.engine.plugins.service.ServiceAware;
33import io.flutter.embedding.engine.plugins.service.ServiceControlSurface;
34import io.flutter.embedding.engine.plugins.service.ServicePluginBinding;
35import io.flutter.util.TraceSection;
36import java.util.HashMap;
37import java.util.HashSet;
54 private static final String TAG =
"FlutterEngineCxnRegstry";
58 private final Map<Class<? extends FlutterPlugin>,
FlutterPlugin> plugins =
new HashMap<>();
62 @NonNull
private final FlutterPlugin.FlutterPluginBinding pluginBinding;
66 private final Map<Class<? extends FlutterPlugin>,
ActivityAware> activityAwarePlugins =
70 @Nullable
private FlutterEngineActivityPluginBinding activityPluginBinding;
71 private boolean isWaitingForActivityReattachment =
false;
75 private final Map<Class<? extends FlutterPlugin>,
ServiceAware> serviceAwarePlugins =
78 @Nullable
private Service service;
79 @Nullable
private FlutterEngineServicePluginBinding servicePluginBinding;
84 broadcastReceiverAwarePlugins =
new HashMap<>();
86 @Nullable
private BroadcastReceiver broadcastReceiver;
87 @Nullable
private FlutterEngineBroadcastReceiverPluginBinding broadcastReceiverPluginBinding;
92 contentProviderAwarePlugins =
new HashMap<>();
94 @Nullable
private ContentProvider contentProvider;
95 @Nullable
private FlutterEngineContentProviderPluginBinding contentProviderPluginBinding;
98 @NonNull Context appContext,
102 this.flutterEngine = flutterEngine;
107 flutterEngine.getDartExecutor(),
108 flutterEngine.getRenderer(),
109 flutterEngine.getPlatformViewsController().getRegistry(),
110 new DefaultFlutterAssets(flutterLoader),
120 detachFromAppComponent();
130 "FlutterEngineConnectionRegistry#add " + plugin.getClass().getSimpleName())) {
131 if (
has(plugin.getClass())) {
134 "Attempted to register plugin ("
137 +
"already registered with this FlutterEngine ("
143 Log.
v(
TAG,
"Adding plugin: " + plugin);
146 plugins.put(plugin.getClass(), plugin);
147 plugin.onAttachedToEngine(pluginBinding);
154 activityAwarePlugins.put(plugin.getClass(), activityAware);
156 if (isAttachedToActivity()) {
166 serviceAwarePlugins.put(plugin.getClass(), serviceAware);
168 if (isAttachedToService()) {
178 broadcastReceiverAwarePlugins.put(plugin.getClass(), broadcastReceiverAware);
180 if (isAttachedToBroadcastReceiver()) {
190 contentProviderAwarePlugins.put(plugin.getClass(), contentProviderAware);
192 if (isAttachedToContentProvider()) {
200 public void add(@NonNull Set<FlutterPlugin> plugins) {
207 public boolean has(@NonNull Class<? extends FlutterPlugin> pluginClass) {
208 return plugins.containsKey(pluginClass);
212 public FlutterPlugin get(@NonNull Class<? extends FlutterPlugin> pluginClass) {
213 return plugins.get(pluginClass);
217 public void remove(@NonNull Class<? extends FlutterPlugin> pluginClass) {
219 if (plugin ==
null) {
225 "FlutterEngineConnectionRegistry#remove " + pluginClass.getSimpleName())) {
230 if (isAttachedToActivity()) {
234 activityAwarePlugins.remove(pluginClass);
241 if (isAttachedToService()) {
245 serviceAwarePlugins.remove(pluginClass);
252 if (isAttachedToBroadcastReceiver()) {
256 broadcastReceiverAwarePlugins.remove(pluginClass);
263 if (isAttachedToContentProvider()) {
267 contentProviderAwarePlugins.remove(pluginClass);
273 plugins.remove(pluginClass);
278 public void remove(@NonNull Set<Class<? extends FlutterPlugin>> pluginClasses) {
279 for (Class<? extends FlutterPlugin> pluginClass : pluginClasses) {
288 remove(
new HashSet<>(plugins.keySet()));
292 private void detachFromAppComponent() {
293 if (isAttachedToActivity()) {
295 }
else if (isAttachedToService()) {
297 }
else if (isAttachedToBroadcastReceiver()) {
299 }
else if (isAttachedToContentProvider()) {
305 private boolean isAttachedToActivity() {
306 return exclusiveActivity !=
null;
309 private Activity attachedActivity() {
310 return exclusiveActivity !=
null ? exclusiveActivity.getAppComponent() :
null;
317 if (this.exclusiveActivity !=
null) {
318 this.exclusiveActivity.detachFromFlutterEngine();
321 detachFromAppComponent();
322 this.exclusiveActivity = exclusiveActivity;
323 attachToActivityInternal(exclusiveActivity.getAppComponent(), lifecycle);
327 private void attachToActivityInternal(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
328 this.activityPluginBinding =
new FlutterEngineActivityPluginBinding(activity, lifecycle);
330 final boolean useSoftwareRendering =
331 activity.getIntent() !=
null
336 flutterEngine.getPlatformViewsController().setSoftwareRendering(useSoftwareRendering);
342 .getPlatformViewsController()
343 .attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor());
346 for (
ActivityAware activityAware : activityAwarePlugins.values()) {
347 if (isWaitingForActivityReattachment) {
348 activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding);
350 activityAware.onAttachedToActivity(activityPluginBinding);
353 isWaitingForActivityReattachment =
false;
358 if (isAttachedToActivity()) {
361 "FlutterEngineConnectionRegistry#detachFromActivityForConfigChanges")) {
362 isWaitingForActivityReattachment =
true;
364 for (
ActivityAware activityAware : activityAwarePlugins.values()) {
365 activityAware.onDetachedFromActivityForConfigChanges();
368 detachFromActivityInternal();
371 Log.
e(
TAG,
"Attempted to detach plugins from an Activity when no Activity was attached.");
377 if (isAttachedToActivity()) {
380 for (
ActivityAware activityAware : activityAwarePlugins.values()) {
381 activityAware.onDetachedFromActivity();
384 detachFromActivityInternal();
387 Log.
e(
TAG,
"Attempted to detach plugins from an Activity when no Activity was attached.");
391 private void detachFromActivityInternal() {
393 flutterEngine.getPlatformViewsController().detach();
395 exclusiveActivity =
null;
396 activityPluginBinding =
null;
401 int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResult) {
402 if (isAttachedToActivity()) {
405 return activityPluginBinding.onRequestPermissionsResult(
406 requestCode, permissions, grantResult);
411 "Attempted to notify ActivityAware plugins of onRequestPermissionsResult, but no Activity"
419 if (isAttachedToActivity()) {
422 return activityPluginBinding.onActivityResult(requestCode, resultCode,
data);
427 "Attempted to notify ActivityAware plugins of onActivityResult, but no Activity was"
435 if (isAttachedToActivity()) {
437 activityPluginBinding.onNewIntent(intent);
442 "Attempted to notify ActivityAware plugins of onNewIntent, but no Activity was"
449 if (isAttachedToActivity()) {
452 activityPluginBinding.onUserLeaveHint();
457 "Attempted to notify ActivityAware plugins of onUserLeaveHint, but no Activity was"
464 if (isAttachedToActivity()) {
467 activityPluginBinding.onSaveInstanceState(bundle);
472 "Attempted to notify ActivityAware plugins of onSaveInstanceState, but no Activity was"
479 if (isAttachedToActivity()) {
482 activityPluginBinding.onRestoreInstanceState(bundle);
487 "Attempted to notify ActivityAware plugins of onRestoreInstanceState, but no Activity was"
494 private boolean isAttachedToService() {
495 return service !=
null;
500 @NonNull Service service, @Nullable Lifecycle lifecycle,
boolean isForeground) {
503 detachFromAppComponent();
505 this.service = service;
506 this.servicePluginBinding =
new FlutterEngineServicePluginBinding(service, lifecycle);
509 for (
ServiceAware serviceAware : serviceAwarePlugins.values()) {
510 serviceAware.onAttachedToService(servicePluginBinding);
517 if (isAttachedToService()) {
521 for (
ServiceAware serviceAware : serviceAwarePlugins.values()) {
522 serviceAware.onDetachedFromService();
526 servicePluginBinding =
null;
529 Log.
e(
TAG,
"Attempted to detach plugins from a Service when no Service was attached.");
535 if (isAttachedToService()) {
538 servicePluginBinding.onMoveToForeground();
545 if (isAttachedToService()) {
548 servicePluginBinding.onMoveToBackground();
555 private boolean isAttachedToBroadcastReceiver() {
556 return broadcastReceiver !=
null;
561 @NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle) {
565 detachFromAppComponent();
567 this.broadcastReceiver = broadcastReceiver;
568 this.broadcastReceiverPluginBinding =
569 new FlutterEngineBroadcastReceiverPluginBinding(broadcastReceiver);
576 broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
583 if (isAttachedToBroadcastReceiver()) {
589 broadcastReceiverAwarePlugins.values()) {
590 broadcastReceiverAware.onDetachedFromBroadcastReceiver();
596 "Attempted to detach plugins from a BroadcastReceiver when no BroadcastReceiver was"
603 private boolean isAttachedToContentProvider() {
604 return contentProvider !=
null;
609 @NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle) {
614 detachFromAppComponent();
616 this.contentProvider = contentProvider;
617 this.contentProviderPluginBinding =
618 new FlutterEngineContentProviderPluginBinding(contentProvider);
625 contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
632 if (isAttachedToContentProvider()) {
638 contentProviderAware.onDetachedFromContentProvider();
644 "Attempted to detach plugins from a ContentProvider when no ContentProvider was"
650 private static class DefaultFlutterAssets
implements FlutterPlugin.FlutterAssets {
653 private DefaultFlutterAssets(@NonNull
FlutterLoader flutterLoader) {
654 this.flutterLoader = flutterLoader;
657 public String getAssetFilePathByName(@NonNull String assetFileName) {
661 public String getAssetFilePathByName(
662 @NonNull String assetFileName, @NonNull String packageName) {
666 public String getAssetFilePathBySubpath(@NonNull String assetSubpath) {
670 public String getAssetFilePathBySubpath(
671 @NonNull String assetSubpath, @NonNull String packageName) {
676 private static class FlutterEngineActivityPluginBinding
implements ActivityPluginBinding {
677 @NonNull
private final Activity activity;
678 @NonNull
private final HiddenLifecycleReference hiddenLifecycleReference;
681 private final Set<io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener>
682 onRequestPermissionsResultListeners =
new HashSet<>();
685 private final Set<io.flutter.plugin.common.PluginRegistry.ActivityResultListener>
686 onActivityResultListeners =
new HashSet<>();
689 private final Set<io.flutter.plugin.common.PluginRegistry.NewIntentListener>
690 onNewIntentListeners =
new HashSet<>();
693 private final Set<io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener>
694 onUserLeaveHintListeners =
new HashSet<>();
697 private final Set<io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener>
698 onWindowFocusChangedListeners =
new HashSet<>();
701 private final Set<OnSaveInstanceStateListener> onSaveInstanceStateListeners =
new HashSet<>();
703 public FlutterEngineActivityPluginBinding(
704 @NonNull Activity activity, @NonNull Lifecycle lifecycle) {
705 this.activity = activity;
706 this.hiddenLifecycleReference =
new HiddenLifecycleReference(lifecycle);
711 public Activity getActivity() {
717 public Object getLifecycle() {
718 return hiddenLifecycleReference;
724 io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
725 onRequestPermissionsResultListeners.add(listener);
731 io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
732 onRequestPermissionsResultListeners.remove(listener);
741 int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResult) {
742 boolean didConsumeResult =
false;
743 for (io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener :
744 onRequestPermissionsResultListeners) {
746 listener.onRequestPermissionsResult(requestCode, permissions, grantResult)
749 return didConsumeResult;
754 @NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
755 onActivityResultListeners.add(listener);
760 @NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
761 onActivityResultListeners.remove(listener);
770 boolean didConsumeResult =
false;
771 for (io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener :
772 new HashSet<>(onActivityResultListeners)) {
774 listener.onActivityResult(requestCode, resultCode,
data) || didConsumeResult;
776 return didConsumeResult;
781 @NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
782 onNewIntentListeners.add(listener);
787 @NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
788 onNewIntentListeners.remove(listener);
797 for (io.flutter.plugin.common.PluginRegistry.NewIntentListener listener :
798 onNewIntentListeners) {
799 listener.onNewIntent(intent);
805 @NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
806 onUserLeaveHintListeners.add(listener);
811 @NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
812 onUserLeaveHintListeners.remove(listener);
817 @NonNull io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener) {
818 onWindowFocusChangedListeners.add(listener);
823 @NonNull io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener) {
824 onWindowFocusChangedListeners.remove(listener);
827 void onWindowFocusChanged(
boolean hasFocus) {
828 for (io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener :
829 onWindowFocusChangedListeners) {
830 listener.onWindowFocusChanged(hasFocus);
835 public void addOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
836 onSaveInstanceStateListeners.add(listener);
840 public void removeOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
841 onSaveInstanceStateListeners.remove(listener);
850 for (io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener :
851 onUserLeaveHintListeners) {
852 listener.onUserLeaveHint();
862 for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
863 listener.onSaveInstanceState(bundle);
873 for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
874 listener.onRestoreInstanceState(bundle);
879 private static class FlutterEngineServicePluginBinding
implements ServicePluginBinding {
880 @NonNull
private final Service
service;
881 @Nullable
private final HiddenLifecycleReference hiddenLifecycleReference;
884 private final Set<ServiceAware.OnModeChangeListener> onModeChangeListeners =
new HashSet<>();
886 FlutterEngineServicePluginBinding(@NonNull Service service, @Nullable Lifecycle lifecycle) {
888 hiddenLifecycleReference = lifecycle !=
null ?
new HiddenLifecycleReference(lifecycle) : null;
893 public Service getService() {
899 public Object getLifecycle() {
900 return hiddenLifecycleReference;
904 public void addOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
905 onModeChangeListeners.add(listener);
909 public void removeOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
910 onModeChangeListeners.remove(listener);
914 for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
915 listener.onMoveToForeground();
920 for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
921 listener.onMoveToBackground();
926 private static class FlutterEngineBroadcastReceiverPluginBinding
927 implements BroadcastReceiverPluginBinding {
928 @NonNull
private final BroadcastReceiver broadcastReceiver;
930 FlutterEngineBroadcastReceiverPluginBinding(@NonNull BroadcastReceiver broadcastReceiver) {
931 this.broadcastReceiver = broadcastReceiver;
936 public BroadcastReceiver getBroadcastReceiver() {
937 return broadcastReceiver;
941 private static class FlutterEngineContentProviderPluginBinding
942 implements ContentProviderPluginBinding {
943 @NonNull
private final ContentProvider contentProvider;
945 FlutterEngineContentProviderPluginBinding(@NonNull ContentProvider contentProvider) {
946 this.contentProvider = contentProvider;
951 public ContentProvider getContentProvider() {
952 return contentProvider;
static void v(@NonNull String tag, @NonNull String message)
static void e(@NonNull String tag, @NonNull String message)
static void w(@NonNull String tag, @NonNull String message)
void attachToActivity( @NonNull ExclusiveAppComponent< Activity > exclusiveActivity, @NonNull Lifecycle lifecycle)
FlutterEngineConnectionRegistry( @NonNull Context appContext, @NonNull FlutterEngine flutterEngine, @NonNull FlutterLoader flutterLoader, @Nullable FlutterEngineGroup group)
void detachFromContentProvider()
void attachToContentProvider( @NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle)
boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult)
void detachFromActivityForConfigChanges()
void onMoveToBackground()
void attachToBroadcastReceiver( @NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle)
void detachFromActivity()
void add(@NonNull FlutterPlugin plugin)
void onMoveToForeground()
void add(@NonNull Set< FlutterPlugin > plugins)
void detachFromBroadcastReceiver()
void onNewIntent(@NonNull Intent intent)
void attachToService( @NonNull Service service, @Nullable Lifecycle lifecycle, boolean isForeground)
void onSaveInstanceState(@NonNull Bundle bundle)
void onRestoreInstanceState(@Nullable Bundle bundle)
boolean has(@NonNull Class<? extends FlutterPlugin > pluginClass)
boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
static final String ARG_KEY_ENABLE_SOFTWARE_RENDERING
String getLookupKeyForAsset(@NonNull String asset)
static TraceSection scoped(String name)
void onDetachedFromEngine(@NonNull FlutterPluginBinding binding)
void onDetachedFromActivity()
void onAttachedToActivity(@NonNull ActivityPluginBinding binding)
void removeOnUserLeaveHintListener(@NonNull PluginRegistry.UserLeaveHintListener listener)
void addActivityResultListener(@NonNull PluginRegistry.ActivityResultListener listener)
void addOnWindowFocusChangedListener(@NonNull PluginRegistry.WindowFocusChangedListener listener)
void addOnNewIntentListener(@NonNull PluginRegistry.NewIntentListener listener)
void removeActivityResultListener(@NonNull PluginRegistry.ActivityResultListener listener)
void addOnUserLeaveHintListener(@NonNull PluginRegistry.UserLeaveHintListener listener)
void addRequestPermissionsResultListener( @NonNull PluginRegistry.RequestPermissionsResultListener listener)
void removeRequestPermissionsResultListener( @NonNull PluginRegistry.RequestPermissionsResultListener listener)
void removeOnWindowFocusChangedListener( @NonNull PluginRegistry.WindowFocusChangedListener listener)
void removeOnNewIntentListener(@NonNull PluginRegistry.NewIntentListener listener)
void onAttachedToBroadcastReceiver(@NonNull BroadcastReceiverPluginBinding binding)
void onDetachedFromBroadcastReceiver()
void onAttachedToContentProvider(@NonNull ContentProviderPluginBinding binding)
void onDetachedFromContentProvider()
void onAttachedToService(@NonNull ServicePluginBinding binding)
void onDetachedFromService()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm service
std::shared_ptr< const fml::Mapping > data