Skip to content

[pigeon] Support multi-engine registration in Native Interop (JNI/FFI) HostApi Registrars #195877

Closed

Description

@tarrinneal

Problem Description

In Pigeon's Native Interop generators (useJni: true for Kotlin and useFfi: true for Swift), @HostApi registrations are stored in a process-wide static map keyed only by the instance name (defaultInstanceName by default):

  • Kotlin (kotlin_generator.dart):
    val Instances: MutableMap<String, Registrar> = mutableMapOf()

  • Swift (swift_generator.dart):
    static var registered = String:

Unlike platform channels (where <Api>.setUp(binaryMessenger, api) scopes registration to a specific engine's BinaryMessenger), JNI/FFI registrars are process-wide. This causes two problems when multiple FlutterEngine instances run in the same OS process (e.g., background isolates/engines spawned by WorkManager, firebase_messaging, or add-to-app setups):

  1. Detaching one engine unregisters the API for all remaining engines:
    When a second FlutterEngine starts, GeneratedPluginRegistrant instantiates a second plugin instance and calls onAttachedToEngine, which calls <Api>Registrar().register(this, name) and overwrites the first engine's registration under name. When that second FlutterEngine finishes and detaches, onDetachedFromEngine calls <Api>Registrar().register(null, name), removing name from <Api>Instances altogether and breaking subsequent calls from the still-running primary engine (e.g., [shared_preferences_android] Detaching a background engine unregisters the API used by the main engine #194920 / [shared_preferences_android] Keep API registration when another engine detaches packages#13359).

  2. Plugins with per-engine state overwrite each other:
    If a plugin holds per-engine or per-activity state (such as Activity from ActivityAware, TextureRegistry, PlatformViewRegistry, or FlutterAssets), a second headless/background FlutterEngine attaching will overwrite the UI engine's registered <Api> instance in <Api>Instances[name] with an instance that has different (or null) per-engine state.

Blocked On / Dependencies

To properly scope @HostApi registrations to a specific FlutterEngine instance over JNI/FFI:

Proposed Solution

1. Short-term (Documentation & Migration Guidance)

Until #195876 is resolved and rolls to stable:

  • Update Pigeon's Native Interop documentation and migration guidance (skills/native-interop-migration/SKILL.md) to clarify that <Api>Registrar is currently process-wide, not per-engine.
  • For plugins whose native implementation only depends on process-wide state (such as Android's binding.applicationContext or iOS/macOS UserDefaults), document that plugins should not unregister (register(null)) the process-wide singleton when an individual engine detaches in onDetachedFromEngine.
  • Warn against migrating @HostApi implementations that depend on per-engine state (ActivityAware, TextureRegistry, PlatformViewRegistry) away from BinaryMessenger until per-engine native interop registration is supported.

2. Long-term (Engine-Scoped Registration via engineId)

Once engineId is publicly exposed on native plugin bindings/registrars (#195876):

  • Update <Api>Registrar (Kotlin JNI and Swift FFI) to support keying registrations by (engineId, name) in addition to process-wide name fallback.
  • When registering/unregistering from onAttachedToEngine / onDetachedFromEngine (or registerWithRegistrar:), associate the registration with the binding's engineId so detaching an engine only removes that engine's registration.
  • Update Dart's generated createWithNativeInteropApi() to pass PlatformDispatcher.instance.engineId when looking up the host API instance via getInstance.

Activity

  1. added
    in triagePresently being triaged by the triage team
    packageflutter/packages repository. See also p: labels.
    p: pigeonrelated to pigeon messaging codegen tool
    and removed
    in triagePresently being triaged by the triage team
    on Nov 3, 2026
  2. puneetkukreja98 commented on Nov 3, 2026

    @puneetkukreja98
    Contributor

    @tarrinneal Thanks for reporting this, routing this to team-ecosystem for further investigation.

  3. added
    P0Critical issues such as a build break or regression
    on Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P0Critical issues such as a build break or regressionp: pigeonrelated to pigeon messaging codegen toolpackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions