[flutter_tools] move service extensions off of deprecated vm service (#55012)

diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index e856412..26f1dbd 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -34,6 +34,7 @@
 import '../reporting/reporting.dart';
 import '../resident_runner.dart';
 import '../run_hot.dart';
+import '../vmservice.dart';
 import '../web/chrome.dart';
 import '../web/compile.dart';
 import '../web/web_device.dart';
@@ -195,9 +196,10 @@
   @override
   Future<void> debugDumpApp() async {
     try {
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugDumpApp',
-      );
+      await _vmService
+        ?.flutterDebugDumpApp(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -206,9 +208,10 @@
   @override
   Future<void> debugDumpRenderTree() async {
     try {
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugDumpRenderTree',
-      );
+      await _vmService
+        ?.flutterDebugDumpRenderTree(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -217,9 +220,10 @@
   @override
   Future<void> debugDumpLayerTree() async {
     try {
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugDumpLayerTree',
-      );
+      await _vmService
+        ?.flutterDebugDumpLayerTree(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -228,8 +232,10 @@
   @override
   Future<void> debugDumpSemanticsTreeInTraversalOrder() async {
     try {
-      await _vmService?.callServiceExtension(
-          'ext.flutter.debugDumpSemanticsTreeInTraversalOrder');
+      await _vmService
+        ?.flutterDebugDumpSemanticsTreeInTraversalOrder(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -238,14 +244,16 @@
   @override
   Future<void> debugTogglePlatform() async {
     try {
-      final vmservice.Response response = await _vmService
-          ?.callServiceExtension('ext.flutter.platformOverride');
-      final String currentPlatform = response.json['value'] as String;
+      final String currentPlatform = await _vmService
+        ?.flutterPlatformOverride(
+          isolateId: null,
+        );
       final String platform = nextPlatform(currentPlatform, featureFlags);
-      await _vmService?.callServiceExtension('ext.flutter.platformOverride',
-          args: <String, Object>{
-            'value': platform,
-          });
+      await _vmService
+        ?.flutterPlatformOverride(
+            platform: platform,
+            isolateId: null,
+          );
       globals.printStatus('Switched operating system to $platform');
     } on vmservice.RPCError {
       return;
@@ -261,8 +269,10 @@
   @override
   Future<void> debugDumpSemanticsTreeInInverseHitTestOrder() async {
     try {
-      await _vmService?.callServiceExtension(
-          'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder');
+      await _vmService
+        ?.flutterDebugDumpSemanticsTreeInInverseHitTestOrder(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -271,16 +281,10 @@
   @override
   Future<void> debugToggleDebugPaintSizeEnabled() async {
     try {
-      final vmservice.Response response =
-          await _vmService?.callServiceExtension(
-        'ext.flutter.debugPaint',
-      );
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugPaint',
-        args: <dynamic, dynamic>{
-          'enabled': !(response.json['enabled'] == 'true')
-        },
-      );
+      await _vmService
+        ?.flutterToggleDebugPaintSizeEnabled(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -289,16 +293,10 @@
   @override
   Future<void> debugToggleDebugCheckElevationsEnabled() async {
     try {
-      final vmservice.Response response =
-          await _vmService?.callServiceExtension(
-        'ext.flutter.debugCheckElevationsEnabled',
-      );
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugCheckElevationsEnabled',
-        args: <dynamic, dynamic>{
-          'enabled': !(response.json['enabled'] == 'true')
-        },
-      );
+      await _vmService
+        ?.flutterToggleDebugCheckElevationsEnabled(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -307,14 +305,10 @@
   @override
   Future<void> debugTogglePerformanceOverlayOverride() async {
     try {
-      final vmservice.Response response = await _vmService
-          ?.callServiceExtension('ext.flutter.showPerformanceOverlay');
-      await _vmService?.callServiceExtension(
-        'ext.flutter.showPerformanceOverlay',
-        args: <dynamic, dynamic>{
-          'enabled': !(response.json['enabled'] == 'true')
-        },
-      );
+      await _vmService
+        ?.flutterTogglePerformanceOverlayOverride(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -323,14 +317,10 @@
   @override
   Future<void> debugToggleWidgetInspector() async {
     try {
-      final vmservice.Response response = await _vmService
-          ?.callServiceExtension('ext.flutter.debugToggleWidgetInspector');
-      await _vmService?.callServiceExtension(
-        'ext.flutter.debugToggleWidgetInspector',
-        args: <dynamic, dynamic>{
-          'enabled': !(response.json['enabled'] == 'true')
-        },
-      );
+      await _vmService
+        ?.flutterToggleWidgetInspector(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -339,14 +329,10 @@
   @override
   Future<void> debugToggleProfileWidgetBuilds() async {
     try {
-      final vmservice.Response response = await _vmService
-          ?.callServiceExtension('ext.flutter.profileWidgetBuilds');
-      await _vmService?.callServiceExtension(
-        'ext.flutter.profileWidgetBuilds',
-        args: <dynamic, dynamic>{
-          'enabled': !(response.json['enabled'] == 'true')
-        },
-      );
+      await _vmService
+        ?.flutterToggleProfileWidgetBuilds(
+          isolateId: null,
+        );
     } on vmservice.RPCError {
       return;
     }
@@ -674,6 +660,14 @@
       _connectionResult = await webDevFS.connect(useDebugExtension);
       unawaited(_connectionResult.debugConnection.onDone.whenComplete(_cleanupAndExit));
 
+      _stdOutSub = _vmService.onStdoutEvent.listen((vmservice.Event log) {
+        final String message = utf8.decode(base64.decode(log.bytes));
+        globals.printStatus(message, newline: false);
+      });
+      _stdErrSub = _vmService.onStderrEvent.listen((vmservice.Event log) {
+        final String message = utf8.decode(base64.decode(log.bytes));
+        globals.printStatus(message, newline: false);
+      });
       try {
         await _vmService.streamListen(vmservice.EventStreams.kStdout);
       } on vmservice.RPCError {
@@ -692,14 +686,6 @@
         // It is safe to ignore this error because we expect an error to be
         // thrown if we're not already subscribed.
       }
-      _stdOutSub = _vmService.onStdoutEvent.listen((vmservice.Event log) {
-        final String message = utf8.decode(base64.decode(log.bytes));
-        globals.printStatus(message, newline: false);
-      });
-      _stdErrSub = _vmService.onStderrEvent.listen((vmservice.Event log) {
-        final String message = utf8.decode(base64.decode(log.bytes));
-        globals.printStatus(message, newline: false);
-      });
       unawaited(_vmService.registerService('reloadSources', 'FlutterTools'));
       _vmService.registerServiceCallback('reloadSources', (Map<String, Object> params) async {
         final bool pause = params['pause'] as bool ?? false;
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 3286a17..976e941 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -6,6 +6,7 @@
 import 'dart:math' as math;
 
 import 'package:meta/meta.dart';
+import 'package:vm_service/vm_service.dart' as vm_service;
 
 import 'android/android_device_discovery.dart';
 import 'android/android_workflow.dart';
@@ -25,7 +26,6 @@
 import 'macos/macos_device.dart';
 import 'project.dart';
 import 'tester/flutter_tester.dart';
-import 'vmservice.dart';
 import 'web/web_device.dart';
 import 'windows/windows_device.dart';
 
@@ -755,7 +755,7 @@
 
   /// Some logs can be obtained from a VM service stream.
   /// Set this after the VM services are connected.
-  VMService connectedVMService;
+  vm_service.VmService connectedVMService;
 
   @override
   String toString() => name;
@@ -785,7 +785,7 @@
   int appPid;
 
   @override
-  VMService connectedVMService;
+  vm_service.VmService connectedVMService;
 
   @override
   Stream<String> get logLines => const Stream<String>.empty();
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index 4a35480..0bfd341 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -24,7 +24,6 @@
 import '../mdns_discovery.dart';
 import '../project.dart';
 import '../protocol_discovery.dart';
-import '../vmservice.dart';
 import 'fallback_discovery.dart';
 import 'ios_deploy.dart';
 import 'ios_workflow.dart';
@@ -561,18 +560,18 @@
   Stream<String> get logLines => _linesController.stream;
 
   @override
-  VMService get connectedVMService => _connectedVMService;
-  VMService _connectedVMService;
+  vm_service.VmService get connectedVMService => _connectedVMService;
+  vm_service.VmService _connectedVMService;
 
   @override
-  set connectedVMService(VMService connectedVmService) {
+  set connectedVMService(vm_service.VmService connectedVmService) {
     _listenToUnifiedLoggingEvents(connectedVmService);
     _connectedVMService = connectedVmService;
   }
 
   static const int _minimumUniversalLoggingSdkVersion = 13;
 
-  Future<void> _listenToUnifiedLoggingEvents(VMService connectedVmService) async {
+  Future<void> _listenToUnifiedLoggingEvents(vm_service.VmService connectedVmService) async {
     if (_majorSdkVersion < _minimumUniversalLoggingSdkVersion) {
       return;
     }
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 816e488..0650e27 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -152,7 +152,7 @@
   final ResidentCompiler generator;
   final BuildInfo buildInfo;
   Stream<Uri> observatoryUris;
-  VMService vmService;
+  vm_service.VmService vmService;
   DevFS devFS;
   ApplicationPackage package;
   List<String> fileSystemRoots;
@@ -226,24 +226,28 @@
     return completer.future;
   }
 
+  // TODO(jonahwilliams): remove once all callsites are updated.
+  VMService get flutterDeprecatedVmService => vmService as VMService;
+
   Future<void> refreshViews() async {
     if (vmService == null) {
       return;
     }
-    await vmService.vm.refreshViews(waitForViews: true);
+    await flutterDeprecatedVmService.vm.refreshViews(waitForViews: true);
   }
 
   List<FlutterView> get views {
-    if (vmService == null || vmService.isClosed) {
+    if (vmService == null || flutterDeprecatedVmService.isClosed) {
       return <FlutterView>[];
     }
 
+
     return (viewFilter != null
-        ? vmService.vm.allViewsWithName(viewFilter)
-        : vmService.vm.views).toList();
+        ? flutterDeprecatedVmService.vm.allViewsWithName(viewFilter)
+        : flutterDeprecatedVmService.vm.views).toList();
   }
 
-  Future<void> getVMs() => vmService.getVMOld();
+  Future<void> getVMs() => flutterDeprecatedVmService.getVMOld();
 
   Future<void> exitApps() async {
     if (!device.supportsFlutterExit) {
@@ -270,7 +274,9 @@
     for (final FlutterView view in flutterViews) {
       if (view != null && view.uiIsolate != null) {
         assert(!view.uiIsolate.pauseEvent.isPauseEvent);
-        futures.add(view.uiIsolate.flutterExit());
+        futures.add(vmService.flutterExit(
+          isolateId: view.uiIsolate.id,
+        ));
       }
     }
     // The flutterExit message only returns if it fails, so just wait a few
@@ -286,7 +292,7 @@
   }) {
     // One devFS per device. Shared by all running instances.
     devFS = DevFS(
-      vmService,
+      flutterDeprecatedVmService,
       fsName,
       rootDirectory,
       osUtils: globals.os,
@@ -301,7 +307,7 @@
     final String deviceEntryUri = devFS.baseUri
       .resolveUri(globals.fs.path.toUri(entryPath)).toString();
     return <Future<vm_service.ReloadReport>>[
-      for (final Isolate isolate in vmService.vm.isolates)
+      for (final Isolate isolate in flutterDeprecatedVmService.vm.isolates)
         vmService.reloadSources(
           isolate.id,
           pause: pause,
@@ -325,68 +331,91 @@
 
   Future<void> debugDumpApp() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterDebugDumpApp();
+      await vmService.flutterDebugDumpApp(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> debugDumpRenderTree() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterDebugDumpRenderTree();
+      await vmService.flutterDebugDumpRenderTree(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> debugDumpLayerTree() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterDebugDumpLayerTree();
+      await vmService.flutterDebugDumpLayerTree(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> debugDumpSemanticsTreeInTraversalOrder() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterDebugDumpSemanticsTreeInTraversalOrder();
+      await vmService.flutterDebugDumpSemanticsTreeInTraversalOrder(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> debugDumpSemanticsTreeInInverseHitTestOrder() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterDebugDumpSemanticsTreeInInverseHitTestOrder();
+      await vmService.flutterDebugDumpSemanticsTreeInInverseHitTestOrder(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> toggleDebugPaintSizeEnabled() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterToggleDebugPaintSizeEnabled();
+      await vmService.flutterToggleDebugPaintSizeEnabled(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> toggleDebugCheckElevationsEnabled() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterToggleDebugCheckElevationsEnabled();
+      await vmService.flutterToggleDebugCheckElevationsEnabled(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> debugTogglePerformanceOverlayOverride() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterTogglePerformanceOverlayOverride();
+      await vmService.flutterTogglePerformanceOverlayOverride(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> toggleWidgetInspector() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterToggleWidgetInspector();
+      await vmService.flutterToggleWidgetInspector(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<void> toggleProfileWidgetBuilds() async {
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterToggleProfileWidgetBuilds();
+      await vmService.flutterToggleProfileWidgetBuilds(
+        isolateId: view.uiIsolate.id,
+      );
     }
   }
 
   Future<String> togglePlatform({ String from }) async {
     final String to = nextPlatform(from, featureFlags);
     for (final FlutterView view in views) {
-      await view.uiIsolate.flutterPlatformOverride(to);
+      await vmService.flutterPlatformOverride(
+        platform: to,
+        isolateId: view.uiIsolate.id,
+      );
     }
     return to;
   }
@@ -416,7 +445,9 @@
   }
 
   Future<void> initLogReader() async {
-    (await device.getLogReader(app: package)).appPid = vmService.vm.pid;
+    final vm_service.VM vm = await vmService.getVM();
+    final DeviceLogReader logReader = await device.getLogReader(app: package);
+    logReader.appPid = vm.pid;
   }
 
   Future<int> runHot({
@@ -721,8 +752,16 @@
     String method, {
     Map<String, dynamic> params,
   }) {
-    return flutterDevices.first.views.first.uiIsolate
-        .invokeFlutterExtensionRpcRaw(method, params: params);
+    return flutterDevices
+      .first
+      .vmService
+      .invokeFlutterExtensionRpcRaw(
+        method,
+        args: params,
+        isolateId: flutterDevices
+          .first.views
+          .first.uiIsolate.id
+      );
   }
 
   /// Whether this runner can hot reload.
@@ -812,7 +851,7 @@
   void writeVmserviceFile() {
     if (debuggingOptions.vmserviceOutFile != null) {
       try {
-        final String address = flutterDevices.first.vmService.wsAddress.toString();
+        final String address = flutterDevices.first.flutterDeprecatedVmService.wsAddress.toString();
         final File vmserviceOutFile = globals.fs.file(debuggingOptions.vmserviceOutFile);
         vmserviceOutFile.createSync(recursive: true);
         vmserviceOutFile.writeAsStringSync(address);
@@ -944,7 +983,10 @@
         await device.refreshViews();
         try {
           for (final FlutterView view in device.views) {
-            await view.uiIsolate.flutterDebugAllowBanner(false);
+            await device.vmService.flutterDebugAllowBanner(
+              false,
+              isolateId: view.uiIsolate.id,
+            );
           }
         } on Exception catch (error) {
           status.cancel();
@@ -958,7 +1000,10 @@
         if (supportsServiceProtocol && isRunningDebug) {
           try {
             for (final FlutterView view in device.views) {
-              await view.uiIsolate.flutterDebugAllowBanner(true);
+              await device.vmService.flutterDebugAllowBanner(
+                true,
+                isolateId: view.uiIsolate.id,
+              );
             }
           } on Exception catch (error) {
             status.cancel();
@@ -980,7 +1025,12 @@
 
   Future<void> debugTogglePlatform() async {
     await refreshViews();
-    final String from = await flutterDevices[0].views[0].uiIsolate.flutterPlatformOverride();
+    final String isolateId = flutterDevices
+      .first.views.first.uiIsolate.id;
+    final String from = await flutterDevices
+      .first.vmService.flutterPlatformOverride(
+        isolateId: isolateId,
+      );
     String to;
     for (final FlutterDevice device in flutterDevices) {
       to = await device.togglePlatform(from: from);
@@ -1039,7 +1089,7 @@
       // This hooks up callbacks for when the connection stops in the future.
       // We don't want to wait for them. We don't handle errors in those callbacks'
       // futures either because they just print to logger and is not critical.
-      unawaited(device.vmService.done.then<void>(
+      unawaited(device.vmService.onDone.then<void>(
         _serviceProtocolDone,
         onError: _serviceProtocolError,
       ).whenComplete(_serviceDisconnected));
@@ -1056,7 +1106,7 @@
         <String, dynamic>{
           'reuseWindows': true,
         },
-        flutterDevices.first.vmService.httpAddress,
+        flutterDevices.first.flutterDeprecatedVmService.httpAddress,
         'http://${_devtoolsServer.address.host}:${_devtoolsServer.port}',
         false,  // headless mode,
         false,  // machine mode
diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart
index 1779426..1b84279 100644
--- a/packages/flutter_tools/lib/src/run_cold.dart
+++ b/packages/flutter_tools/lib/src/run_cold.dart
@@ -83,8 +83,8 @@
     if (flutterDevices.first.observatoryUris != null) {
       // For now, only support one debugger connection.
       connectionInfoCompleter?.complete(DebugConnectionInfo(
-        httpUri: flutterDevices.first.vmService.httpAddress,
-        wsUri: flutterDevices.first.vmService.wsAddress,
+        httpUri: flutterDevices.first.flutterDeprecatedVmService.httpAddress,
+        wsUri: flutterDevices.first.flutterDeprecatedVmService.wsAddress,
       ));
     }
 
@@ -105,7 +105,7 @@
       if (device.vmService != null) {
         globals.printStatus('Tracing startup on ${device.device.name}.');
         await downloadStartupTrace(
-          device.vmService,
+          device.flutterDeprecatedVmService,
           awaitFirstFrame: awaitFirstFrameWhenTracing,
         );
       }
@@ -197,7 +197,7 @@
         // Caution: This log line is parsed by device lab tests.
         globals.printStatus(
           'An Observatory debugger and profiler on $dname is available at: '
-          '${device.vmService.httpAddress}',
+          '${device.flutterDeprecatedVmService.httpAddress}',
         );
       }
     }
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index 55094f4..9b11efe 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -205,7 +205,10 @@
 
     for (final FlutterDevice device in flutterDevices) {
       for (final FlutterView view in device.views) {
-        await view.uiIsolate.flutterFastReassemble(classId);
+        await device.vmService.flutterFastReassemble(
+          classId,
+          isolateId: view.uiIsolate.id,
+        );
       }
     }
 
@@ -260,8 +263,8 @@
         // Only handle one debugger connection.
         connectionInfoCompleter.complete(
           DebugConnectionInfo(
-            httpUri: flutterDevices.first.vmService.httpAddress,
-            wsUri: flutterDevices.first.vmService.wsAddress,
+            httpUri: flutterDevices.first.flutterDeprecatedVmService.httpAddress,
+            wsUri: flutterDevices.first.flutterDeprecatedVmService.wsAddress,
             baseUri: baseUris.first.toString(),
           ),
         );
@@ -570,7 +573,7 @@
       // The engine handles killing and recreating isolates that it has spawned
       // ("uiIsolates"). The isolates that were spawned from these uiIsolates
       // will not be restared, and so they must be manually killed.
-      for (final Isolate isolate in device?.vmService?.vm?.isolates ?? <Isolate>[]) {
+      for (final Isolate isolate in device?.flutterDeprecatedVmService?.vm?.isolates ?? <Isolate>[]) {
         if (!uiIsolates.contains(isolate)) {
           operations.add(isolate.invokeRpcRaw('kill', params: <String, dynamic>{
             'isolateId': isolate.id,
@@ -938,10 +941,16 @@
     }
     await Future.wait(allDevices);
 
-    // Check if any isolates are paused.
+    globals.printTrace('Evicting dirty assets');
+    await _evictDirtyAssets();
+
+    // Check if any isolates are paused and reassemble those
+    // that aren't.
     final List<FlutterView> reassembleViews = <FlutterView>[];
+    final List<Future<void>> reassembleFutures = <Future<void>>[];
     String serviceEventKind;
     int pausedIsolatesFound = 0;
+    bool failedReassemble = false;
     for (final FlutterDevice device in flutterDevices) {
       for (final FlutterView view in device.views) {
         // Check if the isolate is paused, and if so, don't reassemble. Ignore the
@@ -956,6 +965,12 @@
           }
         } else {
           reassembleViews.add(view);
+          reassembleFutures.add(device.vmService.flutterReassemble(
+            isolateId: view.uiIsolate.id,
+          ).catchError((dynamic error) {
+            failedReassemble = true;
+            globals.printError('Reassembling ${view.uiIsolate.name} failed: $error');
+          }, test: (dynamic error) => error is Exception));
         }
       }
     }
@@ -968,24 +983,10 @@
         return OperationResult(OperationResult.ok.code, reloadMessage);
       }
     }
-    globals.printTrace('Evicting dirty assets');
-    await _evictDirtyAssets();
     assert(reassembleViews.isNotEmpty);
+
     globals.printTrace('Reassembling application');
-    bool failedReassemble = false;
-    final List<Future<void>> futures = <Future<void>>[
-      for (final FlutterView view in reassembleViews)
-        () async {
-          try {
-            await view.uiIsolate.flutterReassemble();
-          } on Exception catch (error) {
-            failedReassemble = true;
-            globals.printError('Reassembling ${view.uiIsolate.name} failed: $error');
-            return;
-          }
-        }(),
-    ];
-    final Future<void> reassembleFuture = Future.wait<void>(futures);
+    final Future<void> reassembleFuture = Future.wait<void>(reassembleFutures);
     await reassembleFuture.timeout(
       const Duration(seconds: 2),
       onTimeout: () async {
@@ -1128,7 +1129,7 @@
       // Caution: This log line is parsed by device lab tests.
       globals.printStatus(
         'An Observatory debugger and profiler on $dname is available at: '
-        '${device.vmService.httpAddress}',
+        '${device.flutterDeprecatedVmService.httpAddress}',
       );
     }
   }
@@ -1144,7 +1145,13 @@
         continue;
       }
       for (final String assetPath in device.devFS.assetPathsToEvict) {
-        futures.add(device.views.first.uiIsolate.flutterEvictAsset(assetPath));
+        futures.add(
+          device.views.first.uiIsolate.vmService
+            .flutterEvictAsset(
+              assetPath,
+              isolateId: device.views.first.uiIsolate.id,
+            )
+        );
       }
       device.devFS.assetPathsToEvict.clear();
     }
diff --git a/packages/flutter_tools/lib/src/tracing.dart b/packages/flutter_tools/lib/src/tracing.dart
index 5ea6cfb..aa41645 100644
--- a/packages/flutter_tools/lib/src/tracing.dart
+++ b/packages/flutter_tools/lib/src/tracing.dart
@@ -54,7 +54,10 @@
         });
         bool done = false;
         for (final FlutterView view in vmService.vm.views) {
-          if (await view.uiIsolate.flutterAlreadyPaintedFirstUsefulFrame()) {
+          if (await view.uiIsolate.vmService
+              .flutterAlreadyPaintedFirstUsefulFrame(
+                isolateId: view.uiIsolate.id,
+              )) {
             done = true;
             break;
           }
diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart
index 3de2238..75b6f92 100644
--- a/packages/flutter_tools/lib/src/vmservice.dart
+++ b/packages/flutter_tools/lib/src/vmservice.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:math' as math;
 
 import 'package:meta/meta.dart' show required;
 import 'package:vm_service/vm_service.dart' as vm_service;
@@ -476,6 +475,18 @@
     return _delegateService.callMethod(method, isolateId: isolateId, args: args);
   }
 
+  @override
+  Future<void> get onDone => _delegateService.onDone;
+
+  @override
+  Future<vm_service.Response> callServiceExtension(String method,
+      {String isolateId, Map<Object, Object> args}) {
+    return _delegateService.callServiceExtension(method, isolateId: isolateId, args: args);
+  }
+
+  @override
+  Future<vm_service.VM> getVM() => _delegateService.getVM();
+
   StreamController<ServiceEvent> _getEventController(String eventName) {
     StreamController<ServiceEvent> controller = _eventControllers[eventName];
     if (controller == null) {
@@ -890,7 +901,6 @@
     _upgradeCollection(map, this);
     _loaded = true;
 
-    _pid = map['pid'] as int;
     if (map['_heapAllocatedMemoryUsage'] != null) {
       _heapAllocatedMemoryUsage = map['_heapAllocatedMemoryUsage'] as int;
     }
@@ -910,10 +920,6 @@
   /// The set of live views.
   final Map<String, FlutterView> _viewCache = <String, FlutterView>{};
 
-  /// The pid of the VM's process.
-  int _pid;
-  int get pid => _pid;
-
   /// The number of bytes allocated (e.g. by malloc) in the native heap.
   int _heapAllocatedMemoryUsage;
   int get heapAllocatedMemoryUsage => _heapAllocatedMemoryUsage ?? 0;
@@ -1131,44 +1137,6 @@
   }
 }
 
-class HeapSpace extends ServiceObject {
-  HeapSpace._empty(ServiceObjectOwner owner) : super._empty(owner);
-
-  int _used = 0;
-  int _capacity = 0;
-  int _external = 0;
-  int _collections = 0;
-  double _totalCollectionTimeInSeconds = 0.0;
-  double _averageCollectionPeriodInMillis = 0.0;
-
-  int get used => _used;
-  int get capacity => _capacity;
-  int get external => _external;
-
-  Duration get avgCollectionTime {
-    final double mcs = _totalCollectionTimeInSeconds *
-      Duration.microsecondsPerSecond /
-      math.max(_collections, 1);
-    return Duration(microseconds: mcs.ceil());
-  }
-
-  Duration get avgCollectionPeriod {
-    final double mcs = _averageCollectionPeriodInMillis *
-                       Duration.microsecondsPerMillisecond;
-    return Duration(microseconds: mcs.ceil());
-  }
-
-  @override
-  void _update(Map<String, dynamic> map, bool mapIsRef) {
-    _used = map['used'] as int;
-    _capacity = map['capacity'] as int;
-    _external = map['external'] as int;
-    _collections = map['collections'] as int;
-    _totalCollectionTimeInSeconds = map['time'] as double;
-    _averageCollectionPeriodInMillis = map['avgCollectionPeriodMillis'] as double;
-  }
-}
-
 /// An isolate running inside the VM. Instances of the Isolate class are always
 /// canonicalized.
 class Isolate extends ServiceObjectOwner {
@@ -1250,118 +1218,6 @@
     pauseEvent = map['pauseEvent'] as ServiceEvent;
   }
 
-  // Flutter extension methods.
-
-  // Invoke a flutter extension method, if the flutter extension is not
-  // available, returns null.
-  Future<Map<String, dynamic>> invokeFlutterExtensionRpcRaw(
-    String method, {
-    Map<String, dynamic> params,
-  }) async {
-    try {
-      return await invokeRpcRaw(method, params: params);
-    } on vm_service.RPCError catch (err) {
-      // If an application is not using the framework
-      if (err.code == RPCErrorCodes.kMethodNotFound) {
-        return null;
-      }
-      rethrow;
-    }
-  }
-
-  Future<Map<String, dynamic>> flutterDebugDumpApp() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.debugDumpApp');
-  }
-
-  Future<Map<String, dynamic>> flutterDebugDumpRenderTree() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.debugDumpRenderTree');
-  }
-
-  Future<Map<String, dynamic>> flutterDebugDumpLayerTree() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.debugDumpLayerTree');
-  }
-
-  Future<Map<String, dynamic>> flutterDebugDumpSemanticsTreeInTraversalOrder() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.debugDumpSemanticsTreeInTraversalOrder');
-  }
-
-  Future<Map<String, dynamic>> flutterDebugDumpSemanticsTreeInInverseHitTestOrder() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder');
-  }
-
-  Future<Map<String, dynamic>> _flutterToggle(String name) async {
-    Map<String, dynamic> state = await invokeFlutterExtensionRpcRaw('ext.flutter.$name');
-    if (state != null && state.containsKey('enabled') && state['enabled'] is String) {
-      state = await invokeFlutterExtensionRpcRaw(
-        'ext.flutter.$name',
-        params: <String, dynamic>{'enabled': state['enabled'] == 'true' ? 'false' : 'true'},
-      );
-    }
-    return state;
-  }
-
-  Future<Map<String, dynamic>> flutterToggleDebugPaintSizeEnabled() => _flutterToggle('debugPaint');
-
-  Future<Map<String, dynamic>> flutterToggleDebugCheckElevationsEnabled() => _flutterToggle('debugCheckElevationsEnabled');
-
-  Future<Map<String, dynamic>> flutterTogglePerformanceOverlayOverride() => _flutterToggle('showPerformanceOverlay');
-
-  Future<Map<String, dynamic>> flutterToggleWidgetInspector() => _flutterToggle('inspector.show');
-
-  Future<Map<String, dynamic>> flutterToggleProfileWidgetBuilds() => _flutterToggle('profileWidgetBuilds');
-
-  Future<Map<String, dynamic>> flutterDebugAllowBanner(bool show) {
-    return invokeFlutterExtensionRpcRaw(
-      'ext.flutter.debugAllowBanner',
-      params: <String, dynamic>{'enabled': show ? 'true' : 'false'},
-    );
-  }
-
-  Future<Map<String, dynamic>> flutterReassemble() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.reassemble');
-  }
-
-  Future<Map<String, dynamic>> flutterFastReassemble(String classId) {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.fastReassemble', params: <String, Object>{
-      'class': classId,
-    });
-  }
-
-  Future<bool> flutterAlreadyPaintedFirstUsefulFrame() async {
-    final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw('ext.flutter.didSendFirstFrameRasterizedEvent');
-    // result might be null when the service extension is not initialized
-    return result != null && result['enabled'] == 'true';
-  }
-
-  Future<Map<String, dynamic>> uiWindowScheduleFrame() {
-    return invokeFlutterExtensionRpcRaw('ext.ui.window.scheduleFrame');
-  }
-
-  Future<Map<String, dynamic>> flutterEvictAsset(String assetPath) {
-    return invokeFlutterExtensionRpcRaw(
-      'ext.flutter.evict',
-      params: <String, dynamic>{
-        'value': assetPath,
-      },
-    );
-  }
-
-  // Application control extension methods.
-  Future<Map<String, dynamic>> flutterExit() {
-    return invokeFlutterExtensionRpcRaw('ext.flutter.exit');
-  }
-
-  Future<String> flutterPlatformOverride([ String platform ]) async {
-    final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
-      'ext.flutter.platformOverride',
-      params: platform != null ? <String, dynamic>{'value': platform} : <String, String>{},
-    );
-    if (result != null && result['value'] is String) {
-      return result['value'] as String;
-    }
-    return 'unknown';
-  }
-
   @override
   String toString() => 'Isolate $id';
 }
@@ -1523,4 +1379,213 @@
     );
     await onRunnable;
   }
+
+  Future<Map<String, dynamic>> flutterDebugDumpApp({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugDumpApp',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterDebugDumpRenderTree({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugDumpRenderTree',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterDebugDumpLayerTree({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugDumpLayerTree',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterDebugDumpSemanticsTreeInTraversalOrder({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugDumpSemanticsTreeInTraversalOrder',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterDebugDumpSemanticsTreeInInverseHitTestOrder({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> _flutterToggle(String name, {
+    @required String isolateId,
+  }) async {
+    Map<String, dynamic> state = await invokeFlutterExtensionRpcRaw(
+      'ext.flutter.$name',
+      isolateId: isolateId,
+    );
+    if (state != null && state.containsKey('enabled') && state['enabled'] is String) {
+      state = await invokeFlutterExtensionRpcRaw(
+        'ext.flutter.$name',
+        isolateId: isolateId,
+        args: <String, dynamic>{
+          'enabled': state['enabled'] == 'true' ? 'false' : 'true',
+        },
+      );
+    }
+
+    return state;
+  }
+
+  Future<Map<String, dynamic>> flutterToggleDebugPaintSizeEnabled({
+    @required String isolateId,
+  }) => _flutterToggle('debugPaint', isolateId: isolateId);
+
+  Future<Map<String, dynamic>> flutterToggleDebugCheckElevationsEnabled({
+    @required String isolateId,
+  }) => _flutterToggle('debugCheckElevationsEnabled', isolateId: isolateId);
+
+  Future<Map<String, dynamic>> flutterTogglePerformanceOverlayOverride({
+    @required String isolateId,
+  }) => _flutterToggle('showPerformanceOverlay', isolateId: isolateId);
+
+  Future<Map<String, dynamic>> flutterToggleWidgetInspector({
+    @required String isolateId,
+  }) => _flutterToggle('inspector.show', isolateId: isolateId);
+
+  Future<Map<String, dynamic>> flutterToggleProfileWidgetBuilds({
+    @required String isolateId,
+  }) => _flutterToggle('profileWidgetBuilds', isolateId: isolateId);
+
+  Future<Map<String, dynamic>> flutterDebugAllowBanner(bool show, {
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.debugAllowBanner',
+      isolateId: isolateId,
+      args: <String, dynamic>{'enabled': show ? 'true' : 'false'},
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterReassemble({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.reassemble',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterFastReassemble(String classId, {
+   @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.fastReassemble',
+      isolateId: isolateId,
+      args: <String, Object>{
+        'class': classId,
+      },
+    );
+  }
+
+  Future<bool> flutterAlreadyPaintedFirstUsefulFrame({
+    @required String isolateId,
+  }) async {
+    final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
+      'ext.flutter.didSendFirstFrameRasterizedEvent',
+      isolateId: isolateId,
+    );
+    // result might be null when the service extension is not initialized
+    return result != null && result['enabled'] == 'true';
+  }
+
+  Future<Map<String, dynamic>> uiWindowScheduleFrame({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.ui.window.scheduleFrame',
+      isolateId: isolateId,
+    );
+  }
+
+  Future<Map<String, dynamic>> flutterEvictAsset(String assetPath, {
+   @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.evict',
+      isolateId: isolateId,
+      args: <String, dynamic>{
+        'value': assetPath,
+      },
+    );
+  }
+
+  /// Exit the application by calling [exit] from `dart:io`.
+  ///
+  /// This method is only supported by certain embedders. This is
+  /// described by [Device.supportsFlutterExit].
+  Future<Map<String, dynamic>> flutterExit({
+    @required String isolateId,
+  }) {
+    return invokeFlutterExtensionRpcRaw(
+      'ext.flutter.exit',
+      isolateId: isolateId,
+    );
+  }
+
+  /// Return the current platform override for the flutter view running with
+  /// the main isolate [isolateId].
+  ///
+  /// If a non-null value is provided for [platform], the platform override
+  /// is updated with this value.
+  Future<String> flutterPlatformOverride({
+    String platform,
+    @required String isolateId,
+  }) async {
+    final Map<String, dynamic> result = await invokeFlutterExtensionRpcRaw(
+      'ext.flutter.platformOverride',
+      isolateId: isolateId,
+      args: platform != null
+        ? <String, dynamic>{'value': platform}
+        : <String, String>{},
+    );
+    if (result != null && result['value'] is String) {
+      return result['value'] as String;
+    }
+    return 'unknown';
+  }
+
+  /// Invoke a flutter extension method, if the flutter extension is not
+  /// available, returns null.
+  Future<Map<String, dynamic>> invokeFlutterExtensionRpcRaw(
+    String method, {
+    @required String isolateId,
+    Map<String, dynamic> args,
+  }) async {
+    try {
+
+      final vm_service.Response response = await callServiceExtension(
+        method,
+        args: <String, Object>{
+          'isolateId': isolateId,
+          ...?args,
+        },
+      );
+      return response.json;
+    } on vm_service.RPCError catch (err) {
+      // If an application is not using the framework
+      if (err.code == RPCErrorCodes.kMethodNotFound) {
+        return null;
+      }
+      rethrow;
+    }
+  }
 }