Unverified Commit 5adfd38d authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] Move service methods to VmService extension methods (#54337)

parent 4987210a
......@@ -305,7 +305,11 @@ class FlutterDevice {
globals.fs.path.toUri(getAssetBuildDirectory()));
assert(deviceAssetsDirectoryUri != null);
await Future.wait<void>(views.map<Future<void>>(
(FlutterView view) => view.setAssetDirectory(deviceAssetsDirectoryUri)
(FlutterView view) => vmService.setAssetDirectory(
assetsDirectory: deviceAssetsDirectoryUri,
uiIsolateId: view.uiIsolate.id,
viewId: view.id,
)
));
}
......@@ -748,7 +752,9 @@ abstract class ResidentRunner {
if (!supportsWriteSkSL) {
throw Exception('writeSkSL is not supported by this runner.');
}
final Map<String, Object> data = await flutterDevices.first.views.first.getSkSLs();
final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs(
viewId: flutterDevices.first.views.first.id,
);
if (data.isEmpty) {
globals.logger.printStatus(
'No data was receieved. To ensure SkSL data can be generated use a '
......
......@@ -486,7 +486,8 @@ class HotRunner extends ResidentRunner {
futures.clear();
for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) {
futures.add(view.flushUIThreadTasks());
futures.add(device.vmService
.flushUIThreadTasks(uiIsolateId: view.uiIsolate.id));
}
}
await Future.wait(futures);
......
......@@ -17,6 +17,10 @@ import 'device.dart';
import 'globals.dart' as globals;
import 'version.dart';
const String kGetSkSLsMethod = '_flutter.getSkSLs';
const String kSetAssetBundlePathMethod = '_flutter.setAssetBundlePath';
const String kFlushUIThreadTasksMethod = '_flutter.flushUIThreadTasks';
/// Override `WebSocketConnector` in [context] to use a different constructor
/// for [WebSocket]s (used by tests).
typedef WebSocketConnector = Future<io.WebSocket> Function(String url, {io.CompressionOptions compression});
......@@ -443,6 +447,14 @@ class VMService implements vm_service.VmService {
return _delegateService.onEvent(streamId);
}
@override
Future<vm_service.Response> callMethod(String method, {
String isolateId,
Map<dynamic, dynamic> args,
}) {
return _delegateService.callMethod(method, isolateId: isolateId, args: args);
}
StreamController<ServiceEvent> _getEventController(String eventName) {
StreamController<ServiceEvent> controller = _eventControllers[eventName];
if (controller == null) {
......@@ -1536,43 +1548,56 @@ class FlutterView extends ServiceObject {
await subscription.cancel();
}
Future<void> setAssetDirectory(Uri assetsDirectory) async {
bool get hasIsolate => _uiIsolate != null;
@override
String toString() => id;
}
/// Flutter specific VM Service functionality.
extension FlutterVmService on vm_service.VmService {
/// Set the asset directory for the an attached Flutter view.
Future<void> setAssetDirectory({
@required Uri assetsDirectory,
@required String viewId,
@required String uiIsolateId,
}) async {
assert(assetsDirectory != null);
await owner.vmService.vm.invokeRpc<ServiceObject>('_flutter.setAssetBundlePath',
params: <String, dynamic>{
'isolateId': _uiIsolate.id,
'viewId': id,
'assetDirectory': assetsDirectory.toFilePath(windows: false),
});
}
Future<void> setSemanticsEnabled(bool enabled) async {
assert(enabled != null);
await owner.vmService.vm.invokeRpc<ServiceObject>('_flutter.setSemanticsEnabled',
params: <String, dynamic>{
'isolateId': _uiIsolate.id,
'viewId': id,
'enabled': enabled,
});
}
Future<Map<String, Object>> getSkSLs() async {
final Map<String, dynamic> response = await owner.vmService.vm.invokeRpcRaw(
'_flutter.getSkSLs',
params: <String, dynamic>{
'viewId': id,
await callMethod(kSetAssetBundlePathMethod,
isolateId: uiIsolateId,
args: <String, dynamic>{
'viewId': viewId,
'assetDirectory': assetsDirectory.toFilePath(windows: false),
});
}
/// Retreive the cached SkSL shaders from an attached Flutter view.
///
/// This method will only return data if `--cache-sksl` was provided as a
/// flutter run agument, and only then on physical devices.
Future<Map<String, Object>> getSkSLs({
@required String viewId,
}) async {
final vm_service.Response response = await callMethod(
kGetSkSLsMethod,
args: <String, String>{
'viewId': viewId,
},
);
return response['SkSLs'] as Map<String, Object>;
return response.json['SkSLs'] as Map<String, Object>;
}
bool get hasIsolate => _uiIsolate != null;
Future<void> flushUIThreadTasks() async {
await owner.vm.invokeRpcRaw('_flutter.flushUIThreadTasks',
params: <String, dynamic>{'isolateId': _uiIsolate.id});
/// Flush all tasks on the UI thead for an attached Flutter view.
///
/// This method is currently used only for benchmarking.
Future<void> flushUIThreadTasks({
@required String uiIsolateId,
}) async {
await callMethod(
kFlushUIThreadTasksMethod,
args: <String, String>{
'isolateId': uiIsolateId,
},
);
}
@override
String toString() => id;
}
......@@ -426,8 +426,13 @@ void main() {
}));
test('ResidentRunner handles writeSkSL returning no data', () => testbed.run(() async {
when(mockFlutterView.getSkSLs()).thenAnswer((Invocation invocation) async {
return <String, Object>{};
when(mockVMService.callMethod(
kGetSkSLsMethod,
args: anyNamed('args'),
)).thenAnswer((Invocation invocation) async {
return vm_service.Response.parse(<String, Object>{
'SkSLs': <String, Object>{}
});
});
await residentRunner.writeSkSL();
......@@ -439,10 +444,15 @@ void main() {
return TargetPlatform.android_arm;
});
when(mockDevice.name).thenReturn('test device');
when(mockFlutterView.getSkSLs()).thenAnswer((Invocation invocation) async {
return <String, Object>{
'A': 'B',
};
when(mockVMService.callMethod(
kGetSkSLsMethod,
args: anyNamed('args'),
)).thenAnswer((Invocation invocation) async {
return vm_service.Response.parse(<String, Object>{
'SkSLs': <String, Object>{
'A': 'B',
}
});
});
await residentRunner.writeSkSL();
......
......@@ -4,6 +4,8 @@
import 'dart:async';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/base/logger.dart';
......@@ -211,6 +213,73 @@ void main() {
}, overrides: <Type, Generator>{
FlutterVersion: () => MockFlutterVersion(),
});
testWithoutContext('setAssetDirectory forwards arguments correctly', () async {
final Completer<String> completer = Completer<String>();
final vm_service.VmService vmService = vm_service.VmService(
const Stream<String>.empty(),
completer.complete,
);
unawaited(vmService.setAssetDirectory(
assetsDirectory: Uri(path: 'abc', scheme: 'file'),
viewId: 'abc',
uiIsolateId: 'def',
));
final Map<String, Object> rawRequest = json.decode(await completer.future) as Map<String, Object>;
expect(rawRequest, allOf(<Matcher>[
containsPair('method', kSetAssetBundlePathMethod),
containsPair('params', allOf(<Matcher>[
containsPair('viewId', 'abc'),
containsPair('assetDirectory', '/abc'),
containsPair('isolateId', 'def'),
]))
]));
});
testWithoutContext('getSkSLs forwards arguments correctly', () async {
final Completer<String> completer = Completer<String>();
final vm_service.VmService vmService = vm_service.VmService(
const Stream<String>.empty(),
completer.complete,
);
unawaited(vmService.getSkSLs(
viewId: 'abc',
));
final Map<String, Object> rawRequest = json.decode(await completer.future) as Map<String, Object>;
expect(rawRequest, allOf(<Matcher>[
containsPair('method', kGetSkSLsMethod),
containsPair('params', allOf(<Matcher>[
containsPair('viewId', 'abc'),
]))
]));
});
testWithoutContext('flushUIThreadTasks forwards arguments correctly', () async {
final Completer<String> completer = Completer<String>();
final vm_service.VmService vmService = vm_service.VmService(
const Stream<String>.empty(),
completer.complete,
);
unawaited(vmService.flushUIThreadTasks(
uiIsolateId: 'def',
));
final Map<String, Object> rawRequest = json.decode(await completer.future) as Map<String, Object>;
expect(rawRequest, allOf(<Matcher>[
containsPair('method', kFlushUIThreadTasksMethod),
containsPair('params', allOf(<Matcher>[
containsPair('isolateId', 'def'),
]))
]));
});
}
class MockDevice extends Mock implements Device {}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment