Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 5 additions & 29 deletions dev/devicelab/bin/tasks/flutter_attach_test_android.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,10 @@ Future<void> testReload(Process process, { Future<void> Function() onListening }
}

await eventOrExit(listening.future);
await eventOrExit(ready.future).timeout(const Duration(seconds: 5), onTimeout: () {
// If it can't attach in 5 seconds, it's not capable of finding the
// observatory URL in the logs.
throw TaskResult.failure('Failed to attach to running Flutter process');
});
await eventOrExit(ready.future);

if (exitCode != null)
throw TaskResult.failure('Failed to attach to test app; command unexpected exited, with exit code $exitCode.');
throw 'Failed to attach to test app; command unexpected exited, with exit code $exitCode.';

process.stdin.write('r');
process.stdin.flush();
Expand All @@ -79,10 +75,10 @@ Future<void> testReload(Process process, { Future<void> Function() onListening }
await process.exitCode;

if (stderr.isNotEmpty)
throw TaskResult.failure('flutter attach had output on standard error.');
throw 'flutter attach had output on standard error.';

if (exitCode != 0)
throw TaskResult.failure('exit code was not 0');
throw 'exit code was not 0';
}

void main() {
Expand Down Expand Up @@ -124,7 +120,7 @@ void main() {
// After the delay, force-stopping it shouldn't do anything, but doesn't hurt.
await device.shellExec('am', <String>['force-stop', kAppId]);

String currentTime = (await device.shellEval('date', <String>['"+%F %R:%S.000"'])).trim();
final String currentTime = (await device.shellEval('date', <String>['"+%F %R:%S.000"'])).trim();
print('Start time on device: $currentTime');
section('Relaunching application');
await device.shellExec('am', <String>['start', '-n', kActivityId]);
Expand All @@ -144,26 +140,6 @@ void main() {
);
await testReload(attachProcess);

// Give the device the time to really shut down the app.
await Future<void>.delayed(const Duration(milliseconds: 200));
// After the delay, force-stopping it shouldn't do anything, but doesn't hurt.
await device.shellExec('am', <String>['force-stop', kAppId]);

section('Attaching after relaunching application');
await device.shellExec('am', <String>['start', '-n', kActivityId]);

// Let the application launch. Sync to the next time an observatory is ready.
currentTime = (await device.shellEval('date', <String>['"+%F %R:%S.000"'])).trim();
await device.adb(<String>['logcat', '-e', 'Observatory listening on http:', '-m', '1', '-T', currentTime]);

// Attach again now that the VM is already running.
attachProcess = await startProcess(
path.join(flutterDirectory.path, 'bin', 'flutter'),
<String>['--suppress-analytics', 'attach', '-d', device.deviceId],
isBot: false, // we just want to test the output, not have any debugging info
);
// Verify that it can discover the observatory port from past logs.
await testReload(attachProcess);
} finally {
section('Uninstalling');
await device.adb(<String>['uninstall', kAppId]);
Expand Down
16 changes: 9 additions & 7 deletions packages/flutter_tools/doc/attach.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ without `flutter run` and provides a HotRunner (enabling hot reload/restart).

There are four ways for the attach command to discover a running app:

1. If the app is already running and the observatory port is known, it can be
explicitly provided to attach via the command-line, e.g. `$ flutter attach
--debug-port 12345`
1. If the app is already running and the platform is iOS, attach can use mDNS
to lookup the observatory port via the application ID, with just `$ flutter
attach`
1. If the platform is Fuchsia the module name must be provided, e.g. `$
flutter attach --module=mod_name`. This can be called either before or after
the application is started, attach will poll the device if it cannot
immediately discover the port
1. On Android and iOS, just running `flutter attach` suffices. Flutter tools
will search for an already running Flutter app or module if available.
Otherwise, the tool will wait for the next Flutter app or module to launch
before attaching.
1. If the app or module is already running and the specific observatory port is
known, it can be explicitly provided to attach via the command-line, e.g.
`$ flutter attach --debug-port 12345`
1. On other platforms (i.e. Android), if the app is not yet running attach
will listen and wait for the app to be (manually) started with the default
command: `$ flutter attach`

## Source

Expand Down
32 changes: 4 additions & 28 deletions packages/flutter_tools/lib/src/android/android_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ class AndroidDevice extends Device {
Future<String> get apiVersion => _getProperty('ro.build.version.sdk');

AdbLogReader _logReader;
AdbLogReader _pastLogReader;
_AndroidDevicePortForwarder _portForwarder;

List<String> adbCommandForDevice(List<String> args) {
Expand Down Expand Up @@ -674,23 +673,9 @@ class AndroidDevice extends Device {
}

@override
FutureOr<DeviceLogReader> getLogReader({
AndroidApk app,
bool includePastLogs = false,
}) async {
// The Android log reader isn't app-specific. The `app` parameter isn't used.
if (includePastLogs) {
return _pastLogReader ??= await AdbLogReader.createLogReader(
this,
globals.processManager,
includePastLogs: true,
);
} else {
return _logReader ??= await AdbLogReader.createLogReader(
this,
globals.processManager,
);
}
FutureOr<DeviceLogReader> getLogReader({ AndroidApk app }) async {
// The Android log reader isn't app-specific.
return _logReader ??= await AdbLogReader.createLogReader(this, globals.processManager);
}

@override
Expand Down Expand Up @@ -739,7 +724,6 @@ class AndroidDevice extends Device {
@override
Future<void> dispose() async {
_logReader?._stop();
_pastLogReader?._stop();
await _portForwarder?.dispose();
}
}
Expand Down Expand Up @@ -917,9 +901,6 @@ class AdbLogReader extends DeviceLogReader {
static Future<AdbLogReader> createLogReader(
AndroidDevice device,
ProcessManager processManager,
{
bool includePastLogs = false,
}
) async {
// logcat -T is not supported on Android releases before Lollipop.
const int kLollipopVersionCode = 21;
Expand All @@ -934,12 +915,7 @@ class AdbLogReader extends DeviceLogReader {
'logcat',
'-v',
'time',
// If we include logs from the past, filter for 'flutter' logs only.
if (includePastLogs) ...<String>[
'-s',
'flutter',
] else if (apiVersion != null && apiVersion >= kLollipopVersionCode) ...<String>[
// Otherwise, filter for logs appearing past the present.
if (apiVersion != null && apiVersion >= kLollipopVersionCode) ...<String>[
// Empty `-T` means the timestamp of the logcat command invocation.
'-T',
device.lastLogcatTimestamp ?? '',
Expand Down
5 changes: 1 addition & 4 deletions packages/flutter_tools/lib/src/commands/attach.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'dart:async';

import 'package:meta/meta.dart';

import '../android/android_device.dart';
import '../artifacts.dart';
import '../base/common.dart';
import '../base/context.dart';
Expand Down Expand Up @@ -246,9 +245,7 @@ class AttachCommand extends FlutterCommand {
if (observatoryUri == null) {
final ProtocolDiscovery observatoryDiscovery =
ProtocolDiscovery.observatory(
// If it's an Android device, attaching relies on past log searching
// to find the service protocol.
await device.getLogReader(includePastLogs: device is AndroidDevice),
await device.getLogReader(),
portForwarder: device.portForwarder,
ipv6: ipv6,
devicePort: deviceVmservicePort,
Expand Down
6 changes: 1 addition & 5 deletions packages/flutter_tools/lib/src/desktop_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ abstract class DesktopDevice extends Device {
Future<String> get sdkNameAndVersion async => globals.os.name;

@override
DeviceLogReader getLogReader({
ApplicationPackage app,
bool includePastLogs = false,
}) {
assert(!includePastLogs, 'Past log reading not supported on desktop.');
DeviceLogReader getLogReader({ ApplicationPackage app }) {
return _deviceLogReader;
}

Expand Down
12 changes: 2 additions & 10 deletions packages/flutter_tools/lib/src/device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -415,17 +415,9 @@ abstract class Device {
Future<String> get sdkNameAndVersion;

/// Get a log reader for this device.
///
/// If `app` is specified, this will return a log reader specific to that
/// If [app] is specified, this will return a log reader specific to that
/// application. Otherwise, a global log reader will be returned.
///
/// If `includePastLogs` is true and the device type supports it, the log
/// reader will also include log messages from before the invocation time.
/// Defaults to false.
FutureOr<DeviceLogReader> getLogReader({
covariant ApplicationPackage app,
bool includePastLogs = false,
});
FutureOr<DeviceLogReader> getLogReader({ covariant ApplicationPackage app });

/// Get the port forwarder for this device.
DevicePortForwarder get portForwarder;
Expand Down
9 changes: 2 additions & 7 deletions packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -508,13 +508,8 @@ class FuchsiaDevice extends Device {
}

@override
DeviceLogReader getLogReader({
ApplicationPackage app,
bool includePastLogs = false,
}) {
assert(!includePastLogs, 'Past log reading not supported on Fuchsia.');
return _logReader ??= _FuchsiaLogReader(this, app);
}
DeviceLogReader getLogReader({ApplicationPackage app}) =>
_logReader ??= _FuchsiaLogReader(this, app);
_FuchsiaLogReader _logReader;

@override
Expand Down
6 changes: 1 addition & 5 deletions packages/flutter_tools/lib/src/ios/devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,7 @@ class IOSDevice extends Device {
Future<String> get sdkNameAndVersion async => 'iOS $_sdkVersion';

@override
DeviceLogReader getLogReader({
IOSApp app,
bool includePastLogs = false,
}) {
assert(!includePastLogs, 'Past log reading not supported on iOS devices.');
DeviceLogReader getLogReader({ IOSApp app }) {
_logReaders ??= <IOSApp, DeviceLogReader>{};
return _logReaders.putIfAbsent(app, () => IOSDeviceLogReader.create(
device: this,
Expand Down
6 changes: 1 addition & 5 deletions packages/flutter_tools/lib/src/ios/simulators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -519,12 +519,8 @@ class IOSSimulator extends Device {
}

@override
DeviceLogReader getLogReader({
covariant IOSApp app,
bool includePastLogs = false,
}) {
DeviceLogReader getLogReader({ covariant IOSApp app }) {
assert(app is IOSApp);
assert(!includePastLogs, 'Past log reading not supported on iOS simulators.');
_logReaders ??= <ApplicationPackage, _IOSSimulatorLogReader>{};
return _logReaders.putIfAbsent(app, () => _IOSSimulatorLogReader(this, app));
}
Expand Down
7 changes: 1 addition & 6 deletions packages/flutter_tools/lib/src/tester/flutter_tester.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,7 @@ class FlutterTesterDevice extends Device {
_FlutterTesterDeviceLogReader();

@override
DeviceLogReader getLogReader({
ApplicationPackage app,
bool includePastLogs = false,
}) {
return _logReader;
}
DeviceLogReader getLogReader({ ApplicationPackage app }) => _logReader;

@override
Future<bool> installApp(ApplicationPackage app) async => true;
Expand Down
10 changes: 2 additions & 8 deletions packages/flutter_tools/lib/src/web/web_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ class ChromeDevice extends Device {
DeviceLogReader _logReader;

@override
DeviceLogReader getLogReader({
ApplicationPackage app,
bool includePastLogs = false,
}) {
DeviceLogReader getLogReader({ApplicationPackage app}) {
return _logReader ??= NoOpDeviceLogReader(app?.name);
}

Expand Down Expand Up @@ -224,10 +221,7 @@ class WebServerDevice extends Device {
DeviceLogReader _logReader;

@override
DeviceLogReader getLogReader({
ApplicationPackage app,
bool includePastLogs = false,
}) {
DeviceLogReader getLogReader({ApplicationPackage app}) {
return _logReader ??= NoOpDeviceLogReader(app?.name);
}

Expand Down
Loading