From 4caa1a9e2a9becf87aed50d6146f766eefe1ecb5 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Fri, 28 Jun 2019 16:12:33 -0700 Subject: [PATCH] Fixes a plugin overwrite bug in the plugin shim system. --- .../plugins/shim/ShimPluginRegistry.java | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java b/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java index f882f170b0757..ce85eb0f37c90 100644 --- a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java +++ b/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java @@ -8,10 +8,15 @@ import android.support.annotation.NonNull; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import io.flutter.Log; import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.embedding.engine.plugins.activity.ActivityAware; +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.view.FlutterView; @@ -38,6 +43,7 @@ public class ShimPluginRegistry implements PluginRegistry { private final FlutterEngine flutterEngine; private final PlatformViewsController platformViewsController; private final Map pluginMap = new HashMap<>(); + private final ShimRegistrarAggregate shimRegistrarAggregate; private final FlutterEngine.EngineLifecycleListener engineLifecycleListener = new FlutterEngine.EngineLifecycleListener() { @Override public void onPreEngineRestart() { @@ -53,6 +59,8 @@ public ShimPluginRegistry( this.flutterEngine = flutterEngine; this.flutterEngine.addEngineLifecycleListener(engineLifecycleListener); this.platformViewsController = platformViewsController; + this.shimRegistrarAggregate = new ShimRegistrarAggregate(); + this.flutterEngine.getPlugins().add(shimRegistrarAggregate); } @Override @@ -63,7 +71,7 @@ public Registrar registrarFor(String pluginKey) { } pluginMap.put(pluginKey, null); ShimRegistrar registrar = new ShimRegistrar(pluginKey, pluginMap); - flutterEngine.getPlugins().add(registrar); + shimRegistrarAggregate.addPlugin(registrar); return registrar; } @@ -97,4 +105,81 @@ private void onPreEngineRestart() { public PlatformViewsController getPlatformViewsController() { return platformViewsController; } + + /** + * Aggregates all {@link ShimRegistrar}s within one single {@link FlutterPlugin}. + *

+ * The reason we need this aggregate is because the new embedding uniquely identifies + * plugins by their plugin class, but the plugin shim system represents every plugin + * with a {@link ShimRegistrar}. Therefore, every plugin we would register after the first + * plugin, would overwrite the previous plugin, because they're all {@link ShimRegistrar} + * instances. + *

+ * {@code ShimRegistrarAggregate} multiplexes {@link FlutterPlugin} and {@link ActivityAware} + * calls so that we can register just one {@code ShimRegistrarAggregate} with a + * {@link FlutterEngine}, while forwarding the relevant plugin resources to any number + * of {@link ShimRegistrar}s within this {@code ShimRegistrarAggregate}. + */ + private static class ShimRegistrarAggregate implements FlutterPlugin, ActivityAware { + private final Set shimRegistrars = new HashSet<>(); + private FlutterPluginBinding flutterPluginBinding; + private ActivityPluginBinding activityPluginBinding; + + public void addPlugin(@NonNull ShimRegistrar shimRegistrar) { + shimRegistrars.add(shimRegistrar); + + if (flutterPluginBinding != null) { + shimRegistrar.onAttachedToEngine(flutterPluginBinding); + } + if (activityPluginBinding != null) { + shimRegistrar.onAttachedToActivity(activityPluginBinding); + } + } + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { + flutterPluginBinding = binding; + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onAttachedToEngine(binding); + } + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onDetachedFromEngine(binding); + } + flutterPluginBinding = null; + } + + @Override + public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + activityPluginBinding = binding; + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onAttachedToActivity(binding); + } + } + + @Override + public void onDetachedFromActivityForConfigChanges() { + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onDetachedFromActivity(); + } + activityPluginBinding = null; + } + + @Override + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onReattachedToActivityForConfigChanges(binding); + } + } + + @Override + public void onDetachedFromActivity() { + for (ShimRegistrar shimRegistrar : shimRegistrars) { + shimRegistrar.onDetachedFromActivity(); + } + } + } }