Flutter Engine
The Flutter Engine
platform_message_handler_ios.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "flutter/shell/platform/darwin/ios/platform_message_handler_ios.h"
6
7#include "flutter/fml/trace_event.h"
8#include "flutter/lib/ui/window/platform_message.h"
9#include "flutter/lib/ui/window/platform_message_response.h"
10#include "flutter/shell/platform/darwin/common/buffer_conversions.h"
11
13
14static uint64_t platform_message_counter = 1;
15
17@property(nonatomic, readonly) dispatch_queue_t queue;
18@end
19
20@implementation FLTSerialTaskQueue
21- (instancetype)init {
22 self = [super init];
23 if (self) {
24 _queue = dispatch_queue_create("FLTSerialTaskQueue", DISPATCH_QUEUE_SERIAL);
25 }
26 return self;
27}
28
29- (void)dispatch:(dispatch_block_t)block {
30 dispatch_async(self.queue, block);
31}
32@end
33
34namespace flutter {
35
36NSObject<FlutterTaskQueue>* PlatformMessageHandlerIos::MakeBackgroundTaskQueue() {
37 return [[FLTSerialTaskQueue alloc] init];
38}
39
40PlatformMessageHandlerIos::PlatformMessageHandlerIos(
41 fml::RefPtr<fml::TaskRunner> platform_task_runner)
42 : platform_task_runner_(std::move(platform_task_runner)) {}
43
44void PlatformMessageHandlerIos::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
45 // This can be called from any isolate's thread.
46 @autoreleasepool {
48 HandlerInfo handler_info;
49 {
50 // TODO(gaaclarke): This mutex is a bottleneck for multiple isolates sending
51 // messages at the same time. This could be potentially changed to a
52 // read-write lock.
53 std::lock_guard lock(message_handlers_mutex_);
54 auto it = message_handlers_.find(message->channel());
55 if (it != message_handlers_.end()) {
56 handler_info = it->second;
57 }
58 }
59 if (handler_info.handler) {
60 FlutterBinaryMessageHandler handler = handler_info.handler;
61 NSData* data = nil;
62 if (message->hasData()) {
63 data = ConvertMappingToNSData(message->releaseData());
64 }
65
66 uint64_t platform_message_id = platform_message_counter++;
67 TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id,
68 "channel", message->channel().c_str());
69 dispatch_block_t run_handler = ^{
70 handler(data, ^(NSData* reply) {
71 TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id);
72 // Called from any thread.
73 if (completer) {
74 if (reply) {
75 completer->Complete(ConvertNSDataToMappingPtr(reply));
76 } else {
77 completer->CompleteEmpty();
78 }
79 }
80 });
81 };
82
83 if (handler_info.task_queue.get()) {
84 [handler_info.task_queue.get() dispatch:run_handler];
85 } else {
86 dispatch_async(dispatch_get_main_queue(), run_handler);
87 }
88 } else {
89 if (completer) {
90 completer->CompleteEmpty();
91 }
92 }
93 }
94}
95
97 return false;
98}
99
101 int response_id,
102 std::unique_ptr<fml::Mapping> mapping) {
103 // Called from any thread.
104 // TODO(gaaclarke): This vestigal from the Android implementation, find a way
105 // to migrate this to PlatformMessageHandlerAndroid.
106}
107
109 // Called from any thread.
110 // TODO(gaaclarke): This vestigal from the Android implementation, find a way
111 // to migrate this to PlatformMessageHandlerAndroid.
112}
113
114void PlatformMessageHandlerIos::SetMessageHandler(const std::string& channel,
116 NSObject<FlutterTaskQueue>* task_queue) {
117 FML_CHECK(platform_task_runner_->RunsTasksOnCurrentThread());
118 // Use `respondsToSelector` instead of `conformsToProtocol` to accomodate
119 // injecting your own `FlutterTaskQueue`. This is not a supported usage but
120 // not one worth breaking.
121 FML_CHECK(!task_queue || [task_queue respondsToSelector:@selector(dispatch:)]);
122 /// TODO(gaaclarke): This should be migrated to a lockfree datastructure.
123 std::lock_guard lock(message_handlers_mutex_);
124 message_handlers_.erase(channel);
125 if (handler) {
126 message_handlers_[channel] = {
127 .task_queue =
128 fml::scoped_nsprotocol(static_cast<NSObject<FlutterTaskQueueDispatch>*>(task_queue)),
129 .handler =
132 };
133 }
134}
135} // namespace flutter
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
void HandlePlatformMessage(std::unique_ptr< PlatformMessage > message) override
bool DoesHandlePlatformMessageOnPlatformThread() const override
void InvokePlatformMessageEmptyResponseCallback(int response_id) override
void SetMessageHandler(const std::string &channel, FlutterBinaryMessageHandler handler, NSObject< FlutterTaskQueue > *task_queue)
void InvokePlatformMessageResponseCallback(int response_id, std::unique_ptr< fml::Mapping > mapping) override
virtual void Complete(std::unique_ptr< fml::Mapping > data)=0
virtual bool RunsTasksOnCurrentThread()
Definition: task_runner.cc:43
#define FML_CHECK(condition)
Definition: logging.h:85
Win32Message message
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition: switches.h:41
std::unique_ptr< fml::Mapping > ConvertNSDataToMappingPtr(NSData *data)
NSData * ConvertMappingToNSData(fml::MallocMapping buffer)
Definition: ref_ptr.h:256
static FLUTTER_ASSERT_ARC uint64_t platform_message_counter
fml::ScopedBlock< FlutterBinaryMessageHandler > handler
fml::scoped_nsprotocol< NSObject< FlutterTaskQueueDispatch > * > task_queue
#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, arg1_val)
Definition: trace_event.h:164
#define TRACE_EVENT_ASYNC_END0(category_group, name, id)
Definition: trace_event.h:161