Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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#import "flutter/fml/trace_event.h"
8#import "flutter/lib/ui/window/platform_message.h"
9#import "flutter/shell/platform/darwin/common/buffer_conversions.h"
10#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
11
12static uint64_t platform_message_counter = 1;
13
15@property(nonatomic, strong) dispatch_queue_t queue;
16@end
17
18@implementation FLTSerialTaskQueue
19- (instancetype)init {
20 self = [super init];
21 if (self) {
22 _queue = dispatch_queue_create("FLTSerialTaskQueue", DISPATCH_QUEUE_SERIAL);
23 }
24 return self;
25}
26
27- (void)dealloc {
28 dispatch_release(_queue);
29 [super dealloc];
30}
31
32- (void)dispatch:(dispatch_block_t)block {
33 dispatch_async(self.queue, block);
34}
35@end
36
37namespace flutter {
38
39NSObject<FlutterTaskQueue>* PlatformMessageHandlerIos::MakeBackgroundTaskQueue() {
40 return [[[FLTSerialTaskQueue alloc] init] autorelease];
41}
42
43PlatformMessageHandlerIos::PlatformMessageHandlerIos(
44 fml::RefPtr<fml::TaskRunner> platform_task_runner)
45 : platform_task_runner_(std::move(platform_task_runner)) {}
46
47void PlatformMessageHandlerIos::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
48 // This can be called from any isolate's thread.
49 @autoreleasepool {
51 HandlerInfo handler_info;
52 {
53 // TODO(gaaclarke): This mutex is a bottleneck for multiple isolates sending
54 // messages at the same time. This could be potentially changed to a
55 // read-write lock.
56 std::lock_guard lock(message_handlers_mutex_);
57 auto it = message_handlers_.find(message->channel());
58 if (it != message_handlers_.end()) {
59 handler_info = it->second;
60 }
61 }
62 if (handler_info.handler) {
63 FlutterBinaryMessageHandler handler = handler_info.handler;
64 NSData* data = nil;
65 if (message->hasData()) {
66 data = ConvertMappingToNSData(message->releaseData());
67 }
68
69 uint64_t platform_message_id = platform_message_counter++;
70 TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id,
71 "channel", message->channel().c_str());
72 dispatch_block_t run_handler = ^{
73 handler(data, ^(NSData* reply) {
74 TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id);
75 // Called from any thread.
76 if (completer) {
77 if (reply) {
78 completer->Complete(ConvertNSDataToMappingPtr(reply));
79 } else {
80 completer->CompleteEmpty();
81 }
82 }
83 });
84 };
85
86 if (handler_info.task_queue.get()) {
87 [handler_info.task_queue.get() dispatch:run_handler];
88 } else {
89 dispatch_async(dispatch_get_main_queue(), run_handler);
90 }
91 } else {
92 if (completer) {
93 completer->CompleteEmpty();
94 }
95 }
96 }
97}
98
102
104 int response_id,
105 std::unique_ptr<fml::Mapping> mapping) {
106 // Called from any thread.
107 // TODO(gaaclarke): This vestigal from the Android implementation, find a way
108 // to migrate this to PlatformMessageHandlerAndroid.
109}
110
112 // Called from any thread.
113 // TODO(gaaclarke): This vestigal from the Android implementation, find a way
114 // to migrate this to PlatformMessageHandlerAndroid.
115}
116
117void PlatformMessageHandlerIos::SetMessageHandler(const std::string& channel,
119 NSObject<FlutterTaskQueue>* task_queue) {
120 FML_CHECK(platform_task_runner_->RunsTasksOnCurrentThread());
121 // Use `respondsToSelector` instead of `conformsToProtocol` to accomodate
122 // injecting your own `FlutterTaskQueue`. This is not a supported usage but
123 // not one worth breaking.
124 FML_CHECK(!task_queue || [task_queue respondsToSelector:@selector(dispatch:)]);
125 /// TODO(gaaclarke): This should be migrated to a lockfree datastructure.
126 std::lock_guard lock(message_handlers_mutex_);
127 message_handlers_.erase(channel);
128 if (handler) {
129 message_handlers_[channel] = {
130 .task_queue = fml::scoped_nsprotocol(
131 [static_cast<NSObject<FlutterTaskQueueDispatch>*>(task_queue) retain]),
132 .handler =
135 };
136 }
137}
138} // 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
T get() const __attribute((ns_returns_not_retained))
virtual bool RunsTasksOnCurrentThread()
#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 uint64_t platform_message_counter
static std::atomic< 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)
#define TRACE_EVENT_ASYNC_END0(category_group, name, id)