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
0d19d46b
Unverified
Commit
0d19d46b
authored
Sep 09, 2022
by
gaaclarke
Committed by
GitHub
Sep 09, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Started handling messages from background isolates. (#109005)
Started handling messages from background isolates.
parent
d671a834
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
182 additions
and
10 deletions
+182
-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
+15
-0
platform_channel.dart
packages/flutter/lib/src/services/platform_channel.dart
+111
-9
binding.dart
packages/flutter_test/lib/src/binding.dart
+3
-0
No files found.
dev/integration_tests/channels/android/app/src/main/AndroidManifest.xml
View file @
0d19d46b
...
@@ -18,6 +18,7 @@ found in the LICENSE file. -->
...
@@ -18,6 +18,7 @@ found in the LICENSE file. -->
Application and put your custom class here. -->
Application and put your custom class here. -->
<application
android:name=
"${applicationName}"
android:label=
"channels"
android:icon=
"@mipmap/ic_launcher"
>
<application
android:name=
"${applicationName}"
android:label=
"channels"
android:icon=
"@mipmap/ic_launcher"
>
<activity
android:name=
".MainActivity"
<activity
android:name=
".MainActivity"
android:exported=
"true"
android:launchMode=
"singleTop"
android:launchMode=
"singleTop"
android:theme=
"@android:style/Theme.Black.NoTitleBar"
android:theme=
"@android:style/Theme.Black.NoTitleBar"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:configChanges=
"orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
...
...
dev/integration_tests/channels/ios/Runner/AppDelegate.m
View file @
0d19d46b
...
@@ -114,7 +114,18 @@ const UInt8 PAIR = 129;
...
@@ -114,7 +114,18 @@ const UInt8 PAIR = 129;
[
FlutterMethodChannel
methodChannelWithName
:
@"std-method"
[
FlutterMethodChannel
methodChannelWithName
:
@"std-method"
binaryMessenger
:
flutterController
binaryMessenger
:
flutterController
codec
:[
FlutterStandardMethodCodec
codecWithReaderWriter
:
extendedReaderWriter
]]];
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
{
-
(
void
)
setupMessagingHandshakeOnChannel
:(
FlutterBasicMessageChannel
*
)
channel
{
...
...
dev/integration_tests/channels/lib/main.dart
View file @
0d19d46b
...
@@ -173,6 +173,8 @@ class _TestAppState extends State<TestApp> {
...
@@ -173,6 +173,8 @@ class _TestAppState extends State<TestApp> {
()
=>
basicStringMessageToUnknownChannel
(),
()
=>
basicStringMessageToUnknownChannel
(),
()
=>
basicJsonMessageToUnknownChannel
(),
()
=>
basicJsonMessageToUnknownChannel
(),
()
=>
basicStandardMessageToUnknownChannel
(),
()
=>
basicStandardMessageToUnknownChannel
(),
if
(
Platform
.
isIOS
)
()
=>
basicBackgroundStandardEcho
(
123
),
];
];
Future
<
TestStepResult
>?
_result
;
Future
<
TestStepResult
>?
_result
;
int
_step
=
0
;
int
_step
=
0
;
...
...
dev/integration_tests/channels/lib/src/basic_messaging.dart
View file @
0d19d46b
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:async'
;
import
'dart:isolate'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/services.dart'
;
...
@@ -78,6 +79,41 @@ Future<TestStepResult> basicStandardHandshake(dynamic message) async {
...
@@ -78,6 +79,41 @@ Future<TestStepResult> basicStandardHandshake(dynamic message) async {
'Standard >
${toString(message)}
<'
,
channel
,
message
);
'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
{
Future
<
TestStepResult
>
basicBinaryMessageToUnknownChannel
()
async
{
const
BasicMessageChannel
<
ByteData
?>
channel
=
const
BasicMessageChannel
<
ByteData
?>
channel
=
BasicMessageChannel
<
ByteData
?>(
BasicMessageChannel
<
ByteData
?>(
...
...
dev/integration_tests/channels/lib/src/test_step.dart
View file @
0d19d46b
...
@@ -90,6 +90,8 @@ class TestStepResult {
...
@@ -90,6 +90,8 @@ class TestStepResult {
],
],
);
);
}
}
static
bool
deepEquals
(
dynamic
a
,
dynamic
b
)
=>
_deepEquals
(
a
,
b
);
}
}
Future
<
TestStepResult
>
resultOfHandshake
(
Future
<
TestStepResult
>
resultOfHandshake
(
...
...
packages/flutter/lib/src/services/binding.dart
View file @
0d19d46b
...
@@ -82,6 +82,21 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
...
@@ -82,6 +82,21 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
BinaryMessenger
get
defaultBinaryMessenger
=>
_defaultBinaryMessenger
;
BinaryMessenger
get
defaultBinaryMessenger
=>
_defaultBinaryMessenger
;
late
final
BinaryMessenger
_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
;
/// Returns `true` if executed on a background (non-root) isolate.
///
/// The value `false` will always be returned on web since there is no notion
/// of root/background isolates on the web.
bool
get
useBackgroundIsolateBinaryMessenger
=>
!
kIsWeb
&&
rootIsolateToken
==
null
;
/// The low level buffering and dispatch mechanism for messages sent by
/// The low level buffering and dispatch mechanism for messages sent by
/// plugins on the engine side to their corresponding plugin code on
/// plugins on the engine side to their corresponding plugin code on
/// the framework side.
/// the framework side.
...
...
packages/flutter/lib/src/services/platform_channel.dart
View file @
0d19d46b
...
@@ -4,6 +4,8 @@
...
@@ -4,6 +4,8 @@
import
'dart:async'
;
import
'dart:async'
;
import
'dart:developer'
;
import
'dart:developer'
;
import
'dart:isolate'
show
ReceivePort
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
...
@@ -13,6 +15,7 @@ import 'debug.dart' show debugProfilePlatformChannels;
...
@@ -13,6 +15,7 @@ import 'debug.dart' show debugProfilePlatformChannels;
import
'message_codec.dart'
;
import
'message_codec.dart'
;
import
'message_codecs.dart'
;
import
'message_codecs.dart'
;
export
'dart:ui'
show
RootIsolateToken
;
export
'binary_messenger.dart'
show
BinaryMessenger
;
export
'binary_messenger.dart'
show
BinaryMessenger
;
export
'message_codec.dart'
show
MessageCodec
,
MethodCall
,
MethodCodec
;
export
'message_codec.dart'
show
MessageCodec
,
MethodCall
,
MethodCodec
;
...
@@ -123,6 +126,93 @@ void _debugRecordDownStream(String channelTypeName, String name,
...
@@ -123,6 +126,93 @@ void _debugRecordDownStream(String channelTypeName, String name,
_debugLaunchProfilePlatformChannels
();
_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
ServicesBinding
.
instance
.
useBackgroundIsolateBinaryMessenger
?
BackgroundIsolateBinaryMessenger
.
instance
:
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
}
/// A named channel for communicating with platform plugins using asynchronous
/// A named channel for communicating with platform plugins using asynchronous
/// message passing.
/// message passing.
///
///
...
@@ -160,10 +250,14 @@ class BasicMessageChannel<T> {
...
@@ -160,10 +250,14 @@ class BasicMessageChannel<T> {
/// The message codec used by this channel, not null.
/// The message codec used by this channel, not null.
final
MessageCodec
<
T
>
codec
;
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
{
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
final
BinaryMessenger
result
=
_binaryMessenger
??
_findBinaryMessenger
();
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
return
!
kReleaseMode
&&
debugProfilePlatformChannels
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
// ignore: no_runtimetype_tostring
...
@@ -246,12 +340,14 @@ class MethodChannel {
...
@@ -246,12 +340,14 @@ class MethodChannel {
/// The message codec used by this channel, not null.
/// The message codec used by this channel, not null.
final
MethodCodec
codec
;
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
{
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
final
BinaryMessenger
result
=
_binaryMessenger
??
_findBinaryMessenger
();
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
return
!
kReleaseMode
&&
debugProfilePlatformChannels
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
// ignore: no_runtimetype_tostring
...
@@ -600,8 +696,14 @@ class EventChannel {
...
@@ -600,8 +696,14 @@ class EventChannel {
/// The message codec used by this channel, not null.
/// The message codec used by this channel, not null.
final
MethodCodec
codec
;
final
MethodCodec
codec
;
/// The messenger used by this channel to send platform messages, not null.
/// The messenger which sends the bytes for this channel.
BinaryMessenger
get
binaryMessenger
=>
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
///
/// 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
;
final
BinaryMessenger
?
_binaryMessenger
;
/// Sets up a broadcast stream for receiving events on this channel.
/// Sets up a broadcast stream for receiving events on this channel.
...
...
packages/flutter_test/lib/src/binding.dart
View file @
0d19d46b
...
@@ -104,6 +104,9 @@ mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding {
...
@@ -104,6 +104,9 @@ mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding {
TestDefaultBinaryMessenger
createBinaryMessenger
()
{
TestDefaultBinaryMessenger
createBinaryMessenger
()
{
return
TestDefaultBinaryMessenger
(
super
.
createBinaryMessenger
());
return
TestDefaultBinaryMessenger
(
super
.
createBinaryMessenger
());
}
}
@override
bool
get
useBackgroundIsolateBinaryMessenger
=>
false
;
}
}
/// Base class for bindings used by widgets library tests.
/// Base class for bindings used by widgets library tests.
...
...
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