Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
1ad27570
Unverified
Commit
1ad27570
authored
Sep 12, 2022
by
gaaclarke
Committed by
GitHub
Sep 12, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reland: Started handling messages from background isolates. (#111320)
parent
6b566548
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
173 additions
and
10 deletions
+173
-10
AndroidManifest.xml
...n_tests/channels/android/app/src/main/AndroidManifest.xml
+1
-0
AppDelegate.m
dev/integration_tests/channels/ios/Runner/AppDelegate.m
+12
-1
main.dart
dev/integration_tests/channels/lib/main.dart
+2
-0
basic_messaging.dart
dev/integration_tests/channels/lib/src/basic_messaging.dart
+36
-0
test_step.dart
dev/integration_tests/channels/lib/src/test_step.dart
+2
-0
binding.dart
packages/flutter/lib/src/services/binding.dart
+9
-0
platform_channel.dart
packages/flutter/lib/src/services/platform_channel.dart
+111
-9
No files found.
dev/integration_tests/channels/android/app/src/main/AndroidManifest.xml
View file @
1ad27570
...
...
@@ -18,6 +18,7 @@ found in the LICENSE file. -->
Application and put your custom class here. -->
<application
android:name=
"${applicationName}"
android:label=
"channels"
android:icon=
"@mipmap/ic_launcher"
>
<activity
android:name=
".MainActivity"
android:exported=
"true"
android:launchMode=
"singleTop"
android:theme=
"@android:style/Theme.Black.NoTitleBar"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
...
...
dev/integration_tests/channels/ios/Runner/AppDelegate.m
View file @
1ad27570
...
...
@@ -114,7 +114,18 @@ const UInt8 PAIR = 129;
[
FlutterMethodChannel
methodChannelWithName
:
@"std-method"
binaryMessenger
:
flutterController
codec
:[
FlutterStandardMethodCodec
codecWithReaderWriter
:
extendedReaderWriter
]]];
return
[
super
application
:
application
didFinishLaunchingWithOptions
:
launchOptions
];
[[
FlutterBasicMessageChannel
messageChannelWithName
:
@"std-echo"
binaryMessenger
:
flutterController
codec
:[
FlutterStandardMessageCodec
codecWithReaderWriter
:
extendedReaderWriter
]]
setMessageHandler:
^
(
id
message
,
FlutterReply
reply
)
{
reply
(
message
);
}];
return
[
super
application
:
application
didFinishLaunchingWithOptions
:
launchOptions
];
}
-
(
void
)
setupMessagingHandshakeOnChannel
:(
FlutterBasicMessageChannel
*
)
channel
{
...
...
dev/integration_tests/channels/lib/main.dart
View file @
1ad27570
...
...
@@ -173,6 +173,8 @@ class _TestAppState extends State<TestApp> {
()
=>
basicStringMessageToUnknownChannel
(),
()
=>
basicJsonMessageToUnknownChannel
(),
()
=>
basicStandardMessageToUnknownChannel
(),
if
(
Platform
.
isIOS
)
()
=>
basicBackgroundStandardEcho
(
123
),
];
Future
<
TestStepResult
>?
_result
;
int
_step
=
0
;
...
...
dev/integration_tests/channels/lib/src/basic_messaging.dart
View file @
1ad27570
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:isolate'
;
import
'package:flutter/services.dart'
;
...
...
@@ -78,6 +79,41 @@ Future<TestStepResult> basicStandardHandshake(dynamic message) async {
'Standard >
${toString(message)}
<'
,
channel
,
message
);
}
Future
<
void
>
_basicBackgroundStandardEchoMain
(
List
<
Object
>
args
)
async
{
final
SendPort
sendPort
=
args
[
2
]
as
SendPort
;
final
Object
message
=
args
[
1
];
final
String
name
=
'Background Echo >
${toString(message)}
<'
;
const
String
description
=
'Uses a platform channel from a background isolate.'
;
try
{
BackgroundIsolateBinaryMessenger
.
ensureInitialized
(
args
[
0
]
as
RootIsolateToken
);
const
BasicMessageChannel
<
dynamic
>
channel
=
BasicMessageChannel
<
dynamic
>(
'std-echo'
,
ExtendedStandardMessageCodec
(),
);
final
Object
response
=
await
channel
.
send
(
message
)
as
Object
;
final
TestStatus
testStatus
=
TestStepResult
.
deepEquals
(
message
,
response
)
?
TestStatus
.
ok
:
TestStatus
.
failed
;
sendPort
.
send
(
TestStepResult
(
name
,
description
,
testStatus
));
}
catch
(
ex
)
{
sendPort
.
send
(
TestStepResult
(
name
,
description
,
TestStatus
.
failed
,
error:
ex
.
toString
()));
}
}
Future
<
TestStepResult
>
basicBackgroundStandardEcho
(
Object
message
)
async
{
final
ReceivePort
receivePort
=
ReceivePort
();
Isolate
.
spawn
(
_basicBackgroundStandardEchoMain
,
<
Object
>[
ServicesBinding
.
instance
.
rootIsolateToken
!,
message
,
receivePort
.
sendPort
,
]);
return
await
receivePort
.
first
as
TestStepResult
;
}
Future
<
TestStepResult
>
basicBinaryMessageToUnknownChannel
()
async
{
const
BasicMessageChannel
<
ByteData
?>
channel
=
BasicMessageChannel
<
ByteData
?>(
...
...
dev/integration_tests/channels/lib/src/test_step.dart
View file @
1ad27570
...
...
@@ -90,6 +90,8 @@ class TestStepResult {
],
);
}
static
bool
deepEquals
(
dynamic
a
,
dynamic
b
)
=>
_deepEquals
(
a
,
b
);
}
Future
<
TestStepResult
>
resultOfHandshake
(
...
...
packages/flutter/lib/src/services/binding.dart
View file @
1ad27570
...
...
@@ -82,6 +82,15 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
BinaryMessenger
get
defaultBinaryMessenger
=>
_defaultBinaryMessenger
;
late
final
BinaryMessenger
_defaultBinaryMessenger
;
/// A token that represents the root isolate, used for coordinating with background
/// isolates.
///
/// This property is primarily intended for use with
/// [BackgroundIsolateBinaryMessenger.ensureInitialized], which takes a
/// [RootIsolateToken] as its argument. The value `null` is returned when
/// executed from background isolates.
ui
.
RootIsolateToken
?
get
rootIsolateToken
=>
ui
.
RootIsolateToken
.
instance
;
/// The low level buffering and dispatch mechanism for messages sent by
/// plugins on the engine side to their corresponding plugin code on
/// the framework side.
...
...
packages/flutter/lib/src/services/platform_channel.dart
View file @
1ad27570
...
...
@@ -4,6 +4,8 @@
import
'dart:async'
;
import
'dart:developer'
;
import
'dart:isolate'
show
ReceivePort
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
...
...
@@ -13,6 +15,7 @@ import 'debug.dart' show debugProfilePlatformChannels;
import
'message_codec.dart'
;
import
'message_codecs.dart'
;
export
'dart:ui'
show
RootIsolateToken
;
export
'binary_messenger.dart'
show
BinaryMessenger
;
export
'message_codec.dart'
show
MessageCodec
,
MethodCall
,
MethodCodec
;
...
...
@@ -123,6 +126,93 @@ void _debugRecordDownStream(String channelTypeName, String name,
_debugLaunchProfilePlatformChannels
();
}
/// A [BinaryMessenger] for use on background (non-root) isolates.
class
BackgroundIsolateBinaryMessenger
extends
BinaryMessenger
{
BackgroundIsolateBinaryMessenger
.
_
();
final
ReceivePort
_receivePort
=
ReceivePort
();
final
Map
<
int
,
Completer
<
ByteData
?>>
_completers
=
<
int
,
Completer
<
ByteData
?>>{};
int
_messageCount
=
0
;
/// The existing instance of this class, if any.
///
/// Throws if [ensureInitialized] has not been called at least once.
static
BinaryMessenger
get
instance
{
if
(
_instance
==
null
)
{
throw
StateError
(
'The BackgroundIsolateBinaryMessenger.instance value is invalid '
'until BackgroundIsolateBinaryMessenger.ensureInitialized is '
'executed.'
);
}
return
_instance
!;
}
static
BinaryMessenger
?
_instance
;
/// Ensures that [BackgroundIsolateBinaryMessenger.instance] has been initialized.
///
/// The argument should be the value obtained from [ServicesBinding.rootIsolateToken]
/// on the root isolate.
///
/// This function is idempotent (calling it multiple times is harmless but has no effect).
static
void
ensureInitialized
(
ui
.
RootIsolateToken
token
)
{
if
(
_instance
==
null
)
{
ui
.
PlatformDispatcher
.
instance
.
registerBackgroundIsolate
(
token
);
final
BackgroundIsolateBinaryMessenger
portBinaryMessenger
=
BackgroundIsolateBinaryMessenger
.
_
();
_instance
=
portBinaryMessenger
;
portBinaryMessenger
.
_receivePort
.
listen
((
dynamic
message
)
{
try
{
final
List
<
dynamic
>
args
=
message
as
List
<
dynamic
>;
final
int
identifier
=
args
[
0
]
as
int
;
final
Uint8List
bytes
=
args
[
1
]
as
Uint8List
;
final
ByteData
byteData
=
ByteData
.
sublistView
(
bytes
);
portBinaryMessenger
.
_completers
.
remove
(
identifier
)!.
complete
(
byteData
);
}
catch
(
exception
,
stack
)
{
FlutterError
.
reportError
(
FlutterErrorDetails
(
exception:
exception
,
stack:
stack
,
library
:
'services library'
,
context:
ErrorDescription
(
'during a platform message response callback'
),
));
}
});
}
}
@override
Future
<
void
>
handlePlatformMessage
(
String
channel
,
ByteData
?
data
,
ui
.
PlatformMessageResponseCallback
?
callback
)
{
throw
UnimplementedError
(
'handlePlatformMessage is deprecated.'
);
}
@override
Future
<
ByteData
?>?
send
(
String
channel
,
ByteData
?
message
)
{
final
Completer
<
ByteData
?>
completer
=
Completer
<
ByteData
?>();
_messageCount
+=
1
;
final
int
messageIdentifier
=
_messageCount
;
_completers
[
messageIdentifier
]
=
completer
;
ui
.
PlatformDispatcher
.
instance
.
sendPortPlatformMessage
(
channel
,
message
,
messageIdentifier
,
_receivePort
.
sendPort
,
);
return
completer
.
future
;
}
@override
void
setMessageHandler
(
String
channel
,
MessageHandler
?
handler
)
{
throw
UnsupportedError
(
'Background isolates do not support setMessageHandler(). Messages from the host platform always go to the root isolate.'
);
}
}
BinaryMessenger
_findBinaryMessenger
(
)
{
return
!
kIsWeb
&&
ui
.
RootIsolateToken
.
instance
==
null
?
BackgroundIsolateBinaryMessenger
.
instance
:
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
}
/// A named channel for communicating with platform plugins using asynchronous
/// message passing.
///
...
...
@@ -160,10 +250,14 @@ class BasicMessageChannel<T> {
/// The message codec used by this channel, not null.
final
MessageCodec
<
T
>
codec
;
/// The messenger which sends the bytes for this channel, not null.
/// The messenger which sends the bytes for this channel.
///
/// On the root isolate or web, this defaults to the
/// [ServicesBinding.defaultBinaryMessenger]. In other contexts the default
/// value is a [BackgroundIsolateBinaryMessenger] from
/// [BackgroundIsolateBinaryMessenger.ensureInitialized].
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
final
BinaryMessenger
result
=
_binaryMessenger
??
_findBinaryMessenger
();
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
...
...
@@ -246,12 +340,14 @@ class MethodChannel {
/// The message codec used by this channel, not null.
final
MethodCodec
codec
;
/// The messenger
used by this channel to send platform messages
.
/// The messenger
which sends the bytes for this channel
.
///
/// The messenger may not be null.
/// On the root isolate or web, this defaults to the
/// [ServicesBinding.defaultBinaryMessenger]. In other contexts the default
/// value is a [BackgroundIsolateBinaryMessenger] from
/// [BackgroundIsolateBinaryMessenger.ensureInitialized].
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
final
BinaryMessenger
result
=
_binaryMessenger
??
_findBinaryMessenger
();
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
...
...
@@ -600,8 +696,14 @@ class EventChannel {
/// 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
;
/// The messenger which sends the bytes for this channel.
///
/// On the root isolate or web, this defaults to the
/// [ServicesBinding.defaultBinaryMessenger]. In other contexts the default
/// value is a [BackgroundIsolateBinaryMessenger] from
/// [BackgroundIsolateBinaryMessenger.ensureInitialized].
BinaryMessenger
get
binaryMessenger
=>
_binaryMessenger
??
_findBinaryMessenger
();
final
BinaryMessenger
?
_binaryMessenger
;
/// Sets up a broadcast stream for receiving events on this channel.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment