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
6a51e0c2
Unverified
Commit
6a51e0c2
authored
Jul 12, 2021
by
michaellee8
Committed by
GitHub
Jul 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] Add support for launching fuchsia app using session_control (#85752)
parent
d3c3b891
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
294 additions
and
27 deletions
+294
-27
fuchsia_device.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+70
-21
session_control.dart
packages/flutter_tools/lib/src/fuchsia/session_control.dart
+56
-0
fuchsia_device_start_test.dart
...test/general.shard/fuchsia/fuchsia_device_start_test.dart
+168
-6
No files found.
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
View file @
6a51e0c2
...
...
@@ -32,6 +32,7 @@ import 'fuchsia_build.dart';
import
'fuchsia_pm.dart'
;
import
'fuchsia_sdk.dart'
;
import
'fuchsia_workflow.dart'
;
import
'session_control.dart'
;
import
'tiles_ctl.dart'
;
/// The [FuchsiaDeviceTools] instance.
...
...
@@ -44,6 +45,9 @@ class FuchsiaDeviceTools {
FuchsiaTilesCtl
_tilesCtl
;
FuchsiaTilesCtl
get
tilesCtl
=>
_tilesCtl
??=
FuchsiaTilesCtl
();
FuchsiaSessionControl
_sessionControl
;
FuchsiaSessionControl
get
sessionControl
=>
_sessionControl
??=
FuchsiaSessionControl
();
}
final
String
_ipv4Loopback
=
InternetAddress
.
loopbackIPv4
.
address
;
...
...
@@ -266,6 +270,22 @@ class FuchsiaDevice extends Device {
@override
bool
get
supportsStartPaused
=>
false
;
bool
_isSession
;
Future
<
bool
>
get
isSession
async
=>
_isSession
??=
await
_initIsSession
();
/// Determine if the Fuchsia device is running a session based build.
///
/// If the device is running a session based build, `session_control` should be
/// used to launch apps, otherwise `tiles_ctl` should be used.
Future
<
bool
>
_initIsSession
()
async
{
final
RunResult
result
=
await
shell
(
'which session_control'
);
if
(
result
.
exitCode
!=
0
)
{
return
false
;
}
return
true
;
}
@override
Future
<
bool
>
isAppInstalled
(
ApplicationPackage
app
,
{
...
...
@@ -304,6 +324,12 @@ class FuchsiaDevice extends Device {
bool
ipv6
=
false
,
String
userIdentifier
,
})
async
{
if
(
await
isSession
)
{
globals
.
printTrace
(
'Running on a session framework based build.'
);
}
else
{
globals
.
printTrace
(
'Running on a non session framework based build.'
);
}
if
(!
prebuiltApplication
)
{
await
buildFuchsia
(
fuchsiaProject:
FlutterProject
.
current
().
fuchsia
,
targetPlatform:
await
targetPlatform
,
...
...
@@ -341,7 +367,15 @@ class FuchsiaDevice extends Device {
);
FuchsiaPackageServer
fuchsiaPackageServer
;
bool
serverRegistered
=
false
;
String
fuchsiaUrl
;
try
{
if
(
await
isSession
)
{
// Prefetch session_control
if
(!
await
fuchsiaDeviceTools
.
amberCtl
.
getUp
(
this
,
'session_control'
))
{
globals
.
printError
(
'Failed to get amber to prefetch session_control'
);
return
LaunchResult
.
failed
();
}
}
else
{
// Ask amber to pre-fetch some things we'll need before setting up our own
// package server. This is to avoid relying on amber correctly using
// multiple package servers, support for which is in flux.
...
...
@@ -353,6 +387,7 @@ class FuchsiaDevice extends Device {
globals
.
printError
(
'Failed to get amber to prefetch tiles_ctl'
);
return
LaunchResult
.
failed
();
}
}
// Start up a package server.
const
String
packageServerName
=
FuchsiaPackageServer
.
toolHost
;
...
...
@@ -417,6 +452,15 @@ class FuchsiaDevice extends Device {
return
LaunchResult
.
failed
();
}
fuchsiaUrl
=
'fuchsia-pkg://
$packageServerName
/
$appName
#meta/
$appName
.cmx'
;
if
(
await
isSession
)
{
// Instruct session_control to start the app
if
(!
await
fuchsiaDeviceTools
.
sessionControl
.
add
(
this
,
fuchsiaUrl
))
{
globals
.
printError
(
'Failed to add the app to session_control'
);
return
LaunchResult
.
failed
();
}
}
else
{
// Ensure tiles_ctl is started, and start the app.
if
(!
await
FuchsiaTilesCtl
.
ensureStarted
(
this
))
{
globals
.
printError
(
'Failed to ensure that tiles is started on the device'
);
...
...
@@ -424,11 +468,11 @@ class FuchsiaDevice extends Device {
}
// Instruct tiles_ctl to start the app.
final
String
fuchsiaUrl
=
'fuchsia-pkg://
$packageServerName
/
$appName
#meta/
$appName
.cmx'
;
if
(!
await
fuchsiaDeviceTools
.
tilesCtl
.
add
(
this
,
fuchsiaUrl
,
<
String
>[]))
{
globals
.
printError
(
'Failed to add the app to tiles'
);
return
LaunchResult
.
failed
();
}
}
}
finally
{
// Try to un-teach the package controller about the package server if
// needed.
...
...
@@ -470,6 +514,11 @@ class FuchsiaDevice extends Device {
covariant
FuchsiaApp
app
,
{
String
userIdentifier
,
})
async
{
if
(
await
isSession
)
{
// Currently there are no way to close a running app programmatically
// using the session framework afaik. So this is a no-op.
return
true
;
}
final
int
appKey
=
await
FuchsiaTilesCtl
.
findAppKey
(
this
,
app
.
id
);
if
(
appKey
!=
-
1
)
{
if
(!
await
fuchsiaDeviceTools
.
tilesCtl
.
remove
(
this
,
appKey
))
{
...
...
packages/flutter_tools/lib/src/fuchsia/session_control.dart
0 → 100644
View file @
6a51e0c2
// 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.
// @dart = 2.8
import
'../base/process.dart'
;
import
'fuchsia_device.dart'
;
// Usage: session_control <command> [<args>]
//
// Various operations to control sessions.
//
// Options:
// --help display usage information
//
// Commands:
// launch Launch a new session.
// restart Restart the current session.
// add Add an element to the current session.
//
// Usage: session_control launch <session_url>
//
// Launch a new session.
//
// Options:
// --help display usage information
//
// Usage: session_control restart
//
// Restart the current session.
//
// Options:
// --help display usage information
//
//
// Usage: session_control add <element_url>
//
// Add an element to the current session.
//
// Options:
// --help display usage information
/// A simple wrapper around the 'session_control' tool running on the Fuchsia device.
class
FuchsiaSessionControl
{
/// Instructs session_control on the device to add the app at [url] as an element.
///
/// [url] should be formatted as a Fuchsia-style package URL, e.g.:
/// fuchsia-pkg://fuchsia.com/flutter_gallery#meta/flutter_gallery.cmx
/// Returns true on success and false on failure.
Future
<
bool
>
add
(
FuchsiaDevice
device
,
String
url
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'session_control add
$url
'
);
return
result
.
exitCode
==
0
;
}
}
packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart
View file @
6a51e0c2
...
...
@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/common.dart';
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/os.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/device.dart'
;
import
'package:flutter_tools/src/fuchsia/amber_ctl.dart'
;
...
...
@@ -23,6 +24,7 @@ import 'package:flutter_tools/src/fuchsia/fuchsia_ffx.dart';
import
'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_pm.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'
;
import
'package:flutter_tools/src/fuchsia/session_control.dart'
;
import
'package:flutter_tools/src/fuchsia/tiles_ctl.dart'
;
import
'package:flutter_tools/src/globals_null_migrated.dart'
as
globals
;
import
'package:flutter_tools/src/project.dart'
;
...
...
@@ -41,7 +43,8 @@ void main() {
FakeFuchsiaSdk
fuchsiaSdk
;
Artifacts
artifacts
;
FakeProcessManager
fakeSuccessfulProcessManager
;
FakeProcessManager
fakeFailedProcessManager
;
FakeProcessManager
fakeFailedProcessManagerForHostAddress
;
FakeProcessManager
fakeSuccessfulProcessManagerWithSession
;
File
sshConfig
;
setUp
(()
{
...
...
@@ -73,19 +76,32 @@ void main() {
).
createSync
();
}
fakeSuccessfulProcessManager
=
FakeProcessManager
.
list
(<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
'/ssh_config'
,
'123'
,
'which session_control'
],
exitCode:
1
,
),
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
sshConfig
.
absolute
.
path
,
'123'
,
r'echo $SSH_CONNECTION'
],
stdout:
'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22'
,
),
]);
fakeFailedProcessManager
=
FakeProcessManager
.
list
(<
FakeCommand
>[
fakeFailedProcessManager
ForHostAddress
=
FakeProcessManager
.
list
(<
FakeCommand
>[
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
sshConfig
.
absolute
.
path
,
'123'
,
r'echo $SSH_CONNECTION'
],
stdout:
''
,
stderr:
''
,
stdout:
'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22'
,
exitCode:
1
,
),
]);
fakeSuccessfulProcessManagerWithSession
=
FakeProcessManager
.
list
(<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
'/ssh_config'
,
'123'
,
'which session_control'
],
stdout:
'/bin/session_control'
,
),
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
sshConfig
.
absolute
.
path
,
'123'
,
r'echo $SSH_CONNECTION'
],
stdout:
'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22'
,
),
]);
});
Future
<
LaunchResult
>
setupAndStartApp
({
...
...
@@ -134,6 +150,21 @@ void main() {
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start prebuilt in release mode with session'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
true
,
mode:
BuildMode
.
release
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeSuccessfulProcessManagerWithSession
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start and stop prebuilt in release mode'
,
()
async
{
const
String
appName
=
'app_name'
;
final
FuchsiaDevice
device
=
FuchsiaDeviceWithFakeDiscovery
(
'123'
);
...
...
@@ -161,6 +192,33 @@ void main() {
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start and stop prebuilt in release mode with session'
,
()
async
{
const
String
appName
=
'app_name'
;
final
FuchsiaDevice
device
=
FuchsiaDeviceWithFakeDiscovery
(
'123'
);
globals
.
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
final
File
pubspecFile
=
globals
.
fs
.
file
(
'pubspec.yaml'
)..
createSync
();
pubspecFile
.
writeAsStringSync
(
'name:
$appName
'
);
final
File
far
=
globals
.
fs
.
file
(
'app_name-0.far'
)..
createSync
();
final
FuchsiaApp
app
=
FuchsiaApp
.
fromPrebuiltApp
(
far
);
final
DebuggingOptions
debuggingOptions
=
DebuggingOptions
.
disabled
(
const
BuildInfo
(
BuildMode
.
release
,
null
,
treeShakeIcons:
false
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
app
,
prebuiltApplication:
true
,
debuggingOptions:
debuggingOptions
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
expect
(
await
device
.
stopApp
(
app
),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeSuccessfulProcessManagerWithSession
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start prebuilt in debug mode'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
true
,
mode:
BuildMode
.
debug
);
...
...
@@ -176,6 +234,21 @@ void main() {
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start prebuilt in debug mode with session'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
true
,
mode:
BuildMode
.
debug
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isTrue
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeSuccessfulProcessManagerWithSession
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start buildable in release mode'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
false
,
mode:
BuildMode
.
release
);
...
...
@@ -185,6 +258,43 @@ void main() {
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
list
(<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
'/ssh_config'
,
'123'
,
'which session_control'
],
exitCode:
1
,
),
const
FakeCommand
(
command:
<
String
>[
'Artifact.genSnapshot.TargetPlatform.fuchsia_arm64.release'
,
'--deterministic'
,
'--snapshot_kind=app-aot-elf'
,
'--elf=build/fuchsia/elf.aotsnapshot'
,
'build/fuchsia/app_name.dil'
],
),
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
sshConfig
.
absolute
.
path
,
'123'
,
r'echo $SSH_CONNECTION'
],
stdout:
'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22'
,
),
]),
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start buildable in release mode with session'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
false
,
mode:
BuildMode
.
release
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
list
(<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'ssh'
,
'-F'
,
'/ssh_config'
,
'123'
,
'which session_control'
],
stdout:
'/bin/session_control'
,
),
const
FakeCommand
(
command:
<
String
>[
'Artifact.genSnapshot.TargetPlatform.fuchsia_arm64.release'
,
...
...
@@ -220,6 +330,21 @@ void main() {
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start buildable in debug mode with session'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
false
,
mode:
BuildMode
.
debug
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isTrue
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeSuccessfulProcessManagerWithSession
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'fail when cant get ssh config'
,
()
async
{
expect
(()
async
=>
setupAndStartApp
(
prebuilt:
true
,
mode:
BuildMode
.
release
),
...
...
@@ -240,10 +365,13 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeFailedProcessManager
,
ProcessManager:
()
=>
fakeFailedProcessManager
ForHostAddress
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
OperatingSystemUtils:
()
=>
osUtils
,
Platform:
()
=>
FakePlatform
(
operatingSystem:
'linux'
,
),
});
testUsingContext
(
'fail with correct LaunchResult when pm fails'
,
()
async
{
...
...
@@ -291,6 +419,21 @@ void main() {
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'fail with correct LaunchResult when tiles fails with session'
,
()
async
{
final
LaunchResult
launchResult
=
await
setupAndStartApp
(
prebuilt:
true
,
mode:
BuildMode
.
release
);
expect
(
launchResult
.
started
,
isFalse
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
artifacts
,
FileSystem:
()
=>
memoryFileSystem
,
ProcessManager:
()
=>
fakeSuccessfulProcessManagerWithSession
,
FuchsiaDeviceTools:
()
=>
FakeFuchsiaDeviceTools
(
sessionControl:
FailingFuchsiaSessionControl
()),
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
(
sshConfig:
sshConfig
),
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
});
}
...
...
@@ -474,18 +617,37 @@ class FailingTilesCtl implements FuchsiaTilesCtl {
}
}
class
FakeFuchsiaSessionControl
implements
FuchsiaSessionControl
{
@override
Future
<
bool
>
add
(
FuchsiaDevice
device
,
String
url
)
async
{
return
true
;
}
}
class
FailingFuchsiaSessionControl
implements
FuchsiaSessionControl
{
@override
Future
<
bool
>
add
(
FuchsiaDevice
device
,
String
url
)
async
{
return
false
;
}
}
class
FakeFuchsiaDeviceTools
implements
FuchsiaDeviceTools
{
FakeFuchsiaDeviceTools
({
FuchsiaAmberCtl
amber
,
FuchsiaTilesCtl
tiles
,
FuchsiaSessionControl
sessionControl
,
})
:
amberCtl
=
amber
??
FakeFuchsiaAmberCtl
(),
tilesCtl
=
tiles
??
FakeFuchsiaTilesCtl
();
tilesCtl
=
tiles
??
FakeFuchsiaTilesCtl
(),
sessionControl
=
sessionControl
??
FakeFuchsiaSessionControl
();
@override
final
FuchsiaAmberCtl
amberCtl
;
@override
final
FuchsiaTilesCtl
tilesCtl
;
@override
final
FuchsiaSessionControl
sessionControl
;
}
class
FakeFuchsiaPM
implements
FuchsiaPM
{
...
...
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