// Copyright 2014 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.

import 'dart:async';
import 'dart:developer';

import 'package:flutter/foundation.dart';

import 'binary_messenger.dart';
import 'binding.dart';
import 'debug.dart' show debugProfilePlatformChannels;
import 'message_codec.dart';
import 'message_codecs.dart';

export 'binary_messenger.dart' show BinaryMessenger;
export 'message_codec.dart' show MessageCodec, MethodCall, MethodCodec;

bool _debugProfilePlatformChannelsIsRunning = false;
const Duration _debugProfilePlatformChannelsRate = Duration(seconds: 1);
final Expando<BinaryMessenger> _debugBinaryMessengers = Expando<BinaryMessenger>();

class _ProfiledBinaryMessenger implements BinaryMessenger {
  const _ProfiledBinaryMessenger(this.proxy, this.channelTypeName, this.codecTypeName);
  final BinaryMessenger proxy;
  final String channelTypeName;
  final String codecTypeName;

  @override
  Future<void> handlePlatformMessage(String channel, ByteData? data, PlatformMessageResponseCallback? callback) {
    return proxy.handlePlatformMessage(channel, data, callback);
  }

  Future<ByteData?>? sendWithPostfix(String channel, String postfix, ByteData? message) async {
    final TimelineTask task = TimelineTask();
    _debugRecordUpStream(channelTypeName, '$channel$postfix', codecTypeName, message);
    task.start('Platform Channel send $channel$postfix');
    final ByteData? result;
    try {
      result = await proxy.send(channel, message);
    } finally {
      task.finish();
    }
    _debugRecordDownStream(channelTypeName, '$channel$postfix', codecTypeName, result);
    return result;
  }

  @override
  Future<ByteData?>? send(String channel, ByteData? message) =>
    sendWithPostfix(channel, '', message);

  @override
  void setMessageHandler(String channel, MessageHandler? handler) {
    proxy.setMessageHandler(channel, handler);
  }
}

class _PlatformChannelStats {
  _PlatformChannelStats(this.channel, this.codec, this.type);

  final String channel;
  final String codec;
  final String type;

  int _upCount = 0;
  int _upBytes = 0;
  int get upBytes => _upBytes;
  void addUpStream(int bytes) {
    _upCount += 1;
    _upBytes += bytes;
  }

  int _downCount = 0;
  int _downBytes = 0;
  int get downBytes => _downBytes;
  void addDownStream(int bytes) {
    _downCount += 1;
    _downBytes += bytes;
  }

  double get averageUpPayload => _upBytes / _upCount;
  double get averageDownPayload => _downBytes / _downCount;
}

final Map<String, _PlatformChannelStats> _debugProfilePlatformChannelsStats = <String, _PlatformChannelStats>{};

Future<void> _debugLaunchProfilePlatformChannels() async {
  if (!_debugProfilePlatformChannelsIsRunning) {
    _debugProfilePlatformChannelsIsRunning = true;
    await Future<dynamic>.delayed(_debugProfilePlatformChannelsRate);
    _debugProfilePlatformChannelsIsRunning = false;
    final StringBuffer log = StringBuffer();
    log.writeln('Platform Channel Stats:');
    final List<_PlatformChannelStats> allStats =
        _debugProfilePlatformChannelsStats.values.toList();
    // Sort highest combined bandwidth first.
    allStats.sort((_PlatformChannelStats x, _PlatformChannelStats y) =>
        (y.upBytes + y.downBytes) - (x.upBytes + x.downBytes));
    for (final _PlatformChannelStats stats in allStats) {
      log.writeln(
          '  (name:"${stats.channel}" type:"${stats.type}" codec:"${stats.codec}" upBytes:${stats.upBytes} upBytes_avg:${stats.averageUpPayload.toStringAsFixed(1)} downBytes:${stats.downBytes} downBytes_avg:${stats.averageDownPayload.toStringAsFixed(1)})');
    }
    debugPrint(log.toString());
    _debugProfilePlatformChannelsStats.clear();
  }
}

void _debugRecordUpStream(String channelTypeName, String name,
    String codecTypeName, ByteData? bytes) {
  final _PlatformChannelStats stats =
      _debugProfilePlatformChannelsStats[name] ??=
          _PlatformChannelStats(name, codecTypeName, channelTypeName);
  stats.addUpStream(bytes?.lengthInBytes ?? 0);
  _debugLaunchProfilePlatformChannels();
}

void _debugRecordDownStream(String channelTypeName, String name,
    String codecTypeName, ByteData? bytes) {
  final _PlatformChannelStats stats =
      _debugProfilePlatformChannelsStats[name] ??=
          _PlatformChannelStats(name, codecTypeName, channelTypeName);
  stats.addDownStream(bytes?.lengthInBytes ?? 0);
  _debugLaunchProfilePlatformChannels();
}

/// A named channel for communicating with platform plugins using asynchronous
/// message passing.
///
/// Messages are encoded into binary before being sent, and binary messages
/// received are decoded into Dart values. The [MessageCodec] used must be
/// compatible with the one used by the platform plugin. This can be achieved
/// by creating a basic message channel counterpart of this channel on the
/// platform side. The Dart type of messages sent and received is [T],
/// but only the values supported by the specified [MessageCodec] can be used.
/// The use of unsupported values should be considered programming errors, and
/// will result in exceptions being thrown. The null message is supported
/// for all codecs.
///
/// The logical identity of the channel is given by its name. Identically named
/// channels will interfere with each other's communication.
///
/// All [BasicMessageChannel]s provided by the Flutter framework guarantee FIFO
/// ordering. Applications can assume messages sent via a built-in
/// [BasicMessageChannel] are delivered in the same order as they're sent.
///
/// See: <https://flutter.dev/platform-channels/>
class BasicMessageChannel<T> {
  /// Creates a [BasicMessageChannel] with the specified [name], [codec] and [binaryMessenger].
  ///
  /// The [name] and [codec] arguments cannot be null. The default [ServicesBinding.defaultBinaryMessenger]
  /// instance is used if [binaryMessenger] is null.
  const BasicMessageChannel(this.name, this.codec, { BinaryMessenger? binaryMessenger })
      : assert(name != null),
        assert(codec != null),
        _binaryMessenger = binaryMessenger;

  /// The logical channel on which communication happens, not null.
  final String name;

  /// The message codec used by this channel, not null.
  final MessageCodec<T> codec;

  /// The messenger which sends the bytes for this channel, not null.
  BinaryMessenger get binaryMessenger {
    final BinaryMessenger result =
        _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger;
    return !kReleaseMode && debugProfilePlatformChannels
        ? _debugBinaryMessengers[this] ??= _ProfiledBinaryMessenger(
            // ignore: no_runtimetype_tostring
            result, runtimeType.toString(), codec.runtimeType.toString())
        : result;
  }
  final BinaryMessenger? _binaryMessenger;

  /// Sends the specified [message] to the platform plugins on this channel.
  ///
  /// Returns a [Future] which completes to the received response, which may
  /// be null.
  Future<T?> send(T message) async {
    return codec.decodeMessage(await binaryMessenger.send(name, codec.encodeMessage(message)));
  }

  /// Sets a callback for receiving messages from the platform plugins on this
  /// channel. Messages may be null.
  ///
  /// The given callback will replace the currently registered callback for this
  /// channel, if any. To remove the handler, pass null as the `handler`
  /// argument.
  ///
  /// The handler's return value is sent back to the platform plugins as a
  /// message reply. It may be null.
  void setMessageHandler(Future<T> Function(T? message)? handler) {
    if (handler == null) {
      binaryMessenger.setMessageHandler(name, null);
    } else {
      binaryMessenger.setMessageHandler(name, (ByteData? message) async {
        return codec.encodeMessage(await handler(codec.decodeMessage(message)));
      });
    }
  }

  // Looking for setMockMessageHandler?
  // See this shim package: packages/flutter_test/lib/src/deprecated.dart
}

/// A named channel for communicating with platform plugins using asynchronous
/// method calls.
///
/// Method calls are encoded into binary before being sent, and binary results
/// received are decoded into Dart values. The [MethodCodec] used must be
/// compatible with the one used by the platform plugin. This can be achieved
/// by creating a method channel counterpart of this channel on the
/// platform side. The Dart type of arguments and results is `dynamic`,
/// but only values supported by the specified [MethodCodec] can be used.
/// The use of unsupported values should be considered programming errors, and
/// will result in exceptions being thrown. The null value is supported
/// for all codecs.
///
/// The logical identity of the channel is given by its name. Identically named
/// channels will interfere with each other's communication.
///
/// {@template flutter.services.method_channel.FIFO}
/// All [MethodChannel]s provided by the Flutter framework guarantee FIFO
/// ordering. Applications can assume method calls sent via a built-in
/// [MethodChannel] are received by the platform plugins in the same order as
/// they're sent.
/// {@endtemplate}
///
/// See: <https://flutter.dev/platform-channels/>
class MethodChannel {
  /// Creates a [MethodChannel] with the specified [name].
  ///
  /// The [codec] used will be [StandardMethodCodec], unless otherwise
  /// specified.
  ///
  /// The [name] and [codec] arguments cannot be null. The default [ServicesBinding.defaultBinaryMessenger]
  /// instance is used if [binaryMessenger] is null.
  const MethodChannel(this.name, [this.codec = const StandardMethodCodec(), BinaryMessenger? binaryMessenger ])
      : assert(name != null),
        assert(codec != null),
        _binaryMessenger = binaryMessenger;

  /// The logical channel on which communication happens, not null.
  final String name;

  /// The message codec used by this channel, not null.
  final MethodCodec codec;

  /// The messenger used by this channel to send platform messages.
  ///
  /// The messenger may not be null.
  BinaryMessenger get binaryMessenger {
    final BinaryMessenger result =
        _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger;
    return !kReleaseMode && debugProfilePlatformChannels
        ? _debugBinaryMessengers[this] ??= _ProfiledBinaryMessenger(
            // ignore: no_runtimetype_tostring
            result, runtimeType.toString(), codec.runtimeType.toString())
        : result;
  }
  final BinaryMessenger? _binaryMessenger;

  /// Backend implementation of [invokeMethod].
  ///
  /// The `method` and `arguments` arguments are used to create a [MethodCall]
  /// object that is passed to the [codec]'s [MethodCodec.encodeMethodCall]
  /// method. The resulting message is then sent to the embedding using the
  /// [binaryMessenger]'s [BinaryMessenger.send] method.
  ///
  /// If the result is null and `missingOk` is true, this returns null. (This is
  /// the behaviour of [OptionalMethodChannel.invokeMethod].)
  ///
  /// If the result is null and `missingOk` is false, this throws a
  /// [MissingPluginException]. (This is the behaviour of
  /// [MethodChannel.invokeMethod].)
  ///
  /// Otherwise, the result is decoded using the [codec]'s
  /// [MethodCodec.decodeEnvelope] method.
  ///
  /// The `T` type argument is the expected return type. It is treated as
  /// nullable.
  @optionalTypeArgs
  Future<T?> _invokeMethod<T>(String method, { required bool missingOk, dynamic arguments }) async {
    assert(method != null);
    final ByteData input = codec.encodeMethodCall(MethodCall(method, arguments));
    final ByteData? result =
      !kReleaseMode && debugProfilePlatformChannels ?
        await (binaryMessenger as _ProfiledBinaryMessenger).sendWithPostfix(name, '#$method', input) :
        await binaryMessenger.send(name, input);
    if (result == null) {
      if (missingOk) {
        return null;
      }
      throw MissingPluginException('No implementation found for method $method on channel $name');
    }
    return codec.decodeEnvelope(result) as T?;
  }

  /// Invokes a [method] on this channel with the specified [arguments].
  ///
  /// The static type of [arguments] is `dynamic`, but only values supported by
  /// the [codec] of this channel can be used. The same applies to the returned
  /// result. The values supported by the default codec and their platform-specific
  /// counterparts are documented with [StandardMessageCodec].
  ///
  /// The generic argument `T` of the method can be inferred by the surrounding
  /// context, or provided explicitly. If it does not match the returned type of
  /// the channel, a [TypeError] will be thrown at runtime. `T` cannot be a class
  /// with generics other than `dynamic`. For example, `Map<String, String>`
  /// is not supported but `Map<dynamic, dynamic>` or `Map` is.
  ///
  /// Returns a [Future] which completes to one of the following:
  ///
  /// * a result (possibly null), on successful invocation;
  /// * a [PlatformException], if the invocation failed in the platform plugin;
  /// * a [MissingPluginException], if the method has not been implemented by a
  ///   platform plugin.
  ///
  /// The following code snippets demonstrate how to invoke platform methods
  /// in Dart using a MethodChannel and how to implement those methods in Java
  /// (for Android) and Objective-C (for iOS).
  ///
  /// {@tool snippet}
  ///
  /// The code might be packaged up as a musical plugin, see
  /// <https://flutter.dev/developing-packages/>:
  ///
  /// ```dart
  /// class Music {
  ///   // Class cannot be instantiated.
  ///   const Music._();
  ///
  ///   static const MethodChannel _channel = MethodChannel('music');
  ///
  ///   static Future<bool> isLicensed() async {
  ///     // invokeMethod returns a Future<T?>, so we handle the case where
  ///     // the return value is null by treating null as false.
  ///     return _channel.invokeMethod<bool>('isLicensed').then<bool>((bool? value) => value ?? false);
  ///   }
  ///
  ///   static Future<List<Song>> songs() async {
  ///     // invokeMethod here returns a Future<dynamic> that completes to a
  ///     // List<dynamic> with Map<dynamic, dynamic> entries. Post-processing
  ///     // code thus cannot assume e.g. List<Map<String, String>> even though
  ///     // the actual values involved would support such a typed container.
  ///     // The correct type cannot be inferred with any value of `T`.
  ///     final List<dynamic>? songs = await _channel.invokeMethod<List<dynamic>>('getSongs');
  ///     return songs?.cast<Map<String, Object?>>().map<Song>(Song.fromJson).toList() ?? <Song>[];
  ///   }
  ///
  ///   static Future<void> play(Song song, double volume) async {
  ///     // Errors occurring on the platform side cause invokeMethod to throw
  ///     // PlatformExceptions.
  ///     try {
  ///       return _channel.invokeMethod('play', <String, dynamic>{
  ///         'song': song.id,
  ///         'volume': volume,
  ///       });
  ///     } on PlatformException catch (e) {
  ///       throw ArgumentError('Unable to play ${song.title}: ${e.message}');
  ///     }
  ///   }
  /// }
  ///
  /// class Song {
  ///   Song(this.id, this.title, this.artist);
  ///
  ///   final String id;
  ///   final String title;
  ///   final String artist;
  ///
  ///   static Song fromJson(Map<String, Object?> json) {
  ///     return Song(json['id']! as String, json['title']! as String, json['artist']! as String);
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// {@tool snippet}
  ///
  /// Java (for Android):
  ///
  /// ```java
  /// // Assumes existence of an Android MusicApi.
  /// public class MusicPlugin implements MethodCallHandler {
  ///   @Override
  ///   public void onMethodCall(MethodCall call, Result result) {
  ///     switch (call.method) {
  ///       case "isLicensed":
  ///         result.success(MusicApi.checkLicense());
  ///         break;
  ///       case "getSongs":
  ///         final List<MusicApi.Track> tracks = MusicApi.getTracks();
  ///         final List<Object> json = ArrayList<>(tracks.size());
  ///         for (MusicApi.Track track : tracks) {
  ///           json.add(track.toJson()); // Map<String, Object> entries
  ///         }
  ///         result.success(json);
  ///         break;
  ///       case "play":
  ///         final String song = call.argument("song");
  ///         final double volume = call.argument("volume");
  ///         try {
  ///           MusicApi.playSongAtVolume(song, volume);
  ///           result.success(null);
  ///         } catch (MusicalException e) {
  ///           result.error("playError", e.getMessage(), null);
  ///         }
  ///         break;
  ///       default:
  ///         result.notImplemented();
  ///     }
  ///   }
  ///   // Other methods elided.
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// {@tool snippet}
  ///
  /// Objective-C (for iOS):
  ///
  /// ```objectivec
  /// @interface MusicPlugin : NSObject<FlutterPlugin>
  /// @end
  ///
  /// // Assumes existence of an iOS Broadway Play Api.
  /// @implementation MusicPlugin
  /// - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  ///   if ([@"isLicensed" isEqualToString:call.method]) {
  ///     result([NSNumber numberWithBool:[BWPlayApi isLicensed]]);
  ///   } else if ([@"getSongs" isEqualToString:call.method]) {
  ///     NSArray* items = [BWPlayApi items];
  ///     NSMutableArray* json = [NSMutableArray arrayWithCapacity:items.count];
  ///     for (final BWPlayItem* item in items) {
  ///       [json addObject:@{ @"id":item.itemId, @"title":item.name, @"artist":item.artist }];
  ///     }
  ///     result(json);
  ///   } else if ([@"play" isEqualToString:call.method]) {
  ///     NSString* itemId = call.arguments[@"song"];
  ///     NSNumber* volume = call.arguments[@"volume"];
  ///     NSError* error = nil;
  ///     BOOL success = [BWPlayApi playItem:itemId volume:volume.doubleValue error:&error];
  ///     if (success) {
  ///       result(nil);
  ///     } else {
  ///       result([FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code]
  ///                                  message:error.domain
  ///                                  details:error.localizedDescription]);
  ///     }
  ///   } else {
  ///     result(FlutterMethodNotImplemented);
  ///   }
  /// }
  /// // Other methods elided.
  /// @end
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [invokeListMethod], for automatically returning typed lists.
  ///  * [invokeMapMethod], for automatically returning typed maps.
  ///  * [StandardMessageCodec] which defines the payload values supported by
  ///    [StandardMethodCodec].
  ///  * [JSONMessageCodec] which defines the payload values supported by
  ///    [JSONMethodCodec].
  ///  * <https://api.flutter.dev/javadoc/io/flutter/plugin/common/MethodCall.html>
  ///    for how to access method call arguments on Android.
  @optionalTypeArgs
  Future<T?> invokeMethod<T>(String method, [ dynamic arguments ]) {
    return _invokeMethod<T>(method, missingOk: false, arguments: arguments);
  }

  /// An implementation of [invokeMethod] that can return typed lists.
  ///
  /// Dart generics are reified, meaning that an untyped `List<dynamic>` cannot
  /// masquerade as a `List<T>`. Since [invokeMethod] can only return dynamic
  /// maps, we instead create a new typed list using [List.cast].
  ///
  /// See also:
  ///
  ///  * [invokeMethod], which this call delegates to.
  Future<List<T>?> invokeListMethod<T>(String method, [ dynamic arguments ]) async {
    final List<dynamic>? result = await invokeMethod<List<dynamic>>(method, arguments);
    return result?.cast<T>();
  }

  /// An implementation of [invokeMethod] that can return typed maps.
  ///
  /// Dart generics are reified, meaning that an untyped `Map<dynamic, dynamic>`
  /// cannot masquerade as a `Map<K, V>`. Since [invokeMethod] can only return
  /// dynamic maps, we instead create a new typed map using [Map.cast].
  ///
  /// See also:
  ///
  ///  * [invokeMethod], which this call delegates to.
  Future<Map<K, V>?> invokeMapMethod<K, V>(String method, [ dynamic arguments ]) async {
    final Map<dynamic, dynamic>? result = await invokeMethod<Map<dynamic, dynamic>>(method, arguments);
    return result?.cast<K, V>();
  }

  /// Sets a callback for receiving method calls on this channel.
  ///
  /// The given callback will replace the currently registered callback for this
  /// channel, if any. To remove the handler, pass null as the
  /// `handler` argument.
  ///
  /// If the future returned by the handler completes with a result, that value
  /// is sent back to the platform plugin caller wrapped in a success envelope
  /// as defined by the [codec] of this channel. If the future completes with
  /// a [PlatformException], the fields of that exception will be used to
  /// populate an error envelope which is sent back instead. If the future
  /// completes with a [MissingPluginException], an empty reply is sent
  /// similarly to what happens if no method call handler has been set.
  /// Any other exception results in an error envelope being sent.
  void setMethodCallHandler(Future<dynamic> Function(MethodCall call)? handler) {
    assert(
      _binaryMessenger != null || ServicesBinding.instance != null,
      'Cannot set the method call handler before the binary messenger has been initialized. '
      'This happens when you call setMethodCallHandler() before the WidgetsFlutterBinding '
      'has been initialized. You can fix this by either calling WidgetsFlutterBinding.ensureInitialized() '
      'before this or by passing a custom BinaryMessenger instance to MethodChannel().',
    );
    binaryMessenger.setMessageHandler(
      name,
      handler == null
        ? null
        : (ByteData? message) => _handleAsMethodCall(message, handler),
    );
  }

  Future<ByteData?> _handleAsMethodCall(ByteData? message, Future<dynamic> Function(MethodCall call) handler) async {
    final MethodCall call = codec.decodeMethodCall(message);
    try {
      return codec.encodeSuccessEnvelope(await handler(call));
    } on PlatformException catch (e) {
      return codec.encodeErrorEnvelope(
        code: e.code,
        message: e.message,
        details: e.details,
      );
    } on MissingPluginException {
      return null;
    } catch (error) {
      return codec.encodeErrorEnvelope(code: 'error', message: error.toString());
    }
  }

  // Looking for setMockMethodCallHandler or checkMethodCallHandler?
  // See this shim package: packages/flutter_test/lib/src/deprecated.dart
}

/// A [MethodChannel] that ignores missing platform plugins.
///
/// When [invokeMethod] fails to find the platform plugin, it returns null
/// instead of throwing an exception.
///
/// {@macro flutter.services.method_channel.FIFO}
class OptionalMethodChannel extends MethodChannel {
  /// Creates a [MethodChannel] that ignores missing platform plugins.
  const OptionalMethodChannel(super.name, [super.codec, super.binaryMessenger]);

  @override
  Future<T?> invokeMethod<T>(String method, [ dynamic arguments ]) async {
    return super._invokeMethod<T>(method, missingOk: true, arguments: arguments);
  }
}

/// A named channel for communicating with platform plugins using event streams.
///
/// Stream setup requests are encoded into binary before being sent,
/// and binary events and errors received are decoded into Dart values.
/// The [MethodCodec] used must be compatible with the one used by the platform
/// plugin. This can be achieved by creating an `EventChannel` counterpart of
/// this channel on the platform side. The Dart type of events sent and received
/// is `dynamic`, but only values supported by the specified [MethodCodec] can
/// be used.
///
/// The logical identity of the channel is given by its name. Identically named
/// channels will interfere with each other's communication.
///
/// See: <https://flutter.dev/platform-channels/>
class EventChannel {
  /// Creates an [EventChannel] with the specified [name].
  ///
  /// The [codec] used will be [StandardMethodCodec], unless otherwise
  /// specified.
  ///
  /// Neither [name] nor [codec] may be null. The default [ServicesBinding.defaultBinaryMessenger]
  /// instance is used if [binaryMessenger] is null.
  const EventChannel(this.name, [this.codec = const StandardMethodCodec(), BinaryMessenger? binaryMessenger])
      : assert(name != null),
        assert(codec != null),
        _binaryMessenger = binaryMessenger;

  /// The logical channel on which communication happens, not null.
  final String name;

  /// The message codec used by this channel, not null.
  final MethodCodec codec;

  /// The messenger used by this channel to send platform messages, not null.
  BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance.defaultBinaryMessenger;
  final BinaryMessenger? _binaryMessenger;

  /// Sets up a broadcast stream for receiving events on this channel.
  ///
  /// Returns a broadcast [Stream] which emits events to listeners as follows:
  ///
  /// * a decoded data event (possibly null) for each successful event
  ///   received from the platform plugin;
  /// * an error event containing a [PlatformException] for each error event
  ///   received from the platform plugin.
  ///
  /// Errors occurring during stream activation or deactivation are reported
  /// through the [FlutterError] facility. Stream activation happens only when
  /// stream listener count changes from 0 to 1. Stream deactivation happens
  /// only when stream listener count changes from 1 to 0.
  Stream<dynamic> receiveBroadcastStream([ dynamic arguments ]) {
    final MethodChannel methodChannel = MethodChannel(name, codec);
    late StreamController<dynamic> controller;
    controller = StreamController<dynamic>.broadcast(onListen: () async {
      binaryMessenger.setMessageHandler(name, (ByteData? reply) async {
        if (reply == null) {
          controller.close();
        } else {
          try {
            controller.add(codec.decodeEnvelope(reply));
          } on PlatformException catch (e) {
            controller.addError(e);
          }
        }
        return null;
      });
      try {
        await methodChannel.invokeMethod<void>('listen', arguments);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'services library',
          context: ErrorDescription('while activating platform stream on channel $name'),
        ));
      }
    }, onCancel: () async {
      binaryMessenger.setMessageHandler(name, null);
      try {
        await methodChannel.invokeMethod<void>('cancel', arguments);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'services library',
          context: ErrorDescription('while de-activating platform stream on channel $name'),
        ));
      }
    });
    return controller.stream;
  }
}
