Revert "Reland "[ package:dds ] Add support for caching CPU samples based on UserTag""

This reverts commit 17961606060fa36971fdc40cee8105a13262e97e.

Reason for revert: Still seeing failures.

Original change's description:
> Reland "[ package:dds ] Add support for caching CPU samples based on UserTag"
>
> This reverts commit 4160747ef63d4a7071242b50382a2b8f3c559d1f.
>
> It seems like 9397b8ff055b3b97275e17aaf651bbb176b2b306 should have fixed the original failures we were seeing and the failing bots in question seem to be passing when running try jobs.
>
> TBR=asiva@ (discussed offline)
>
> TEST=Existing service tests + get_cached_cpu_samples_test
> Change-Id: I1c50c0e79375df819a0bd68e68ac28c3064874c8
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208441
> Reviewed-by: Ben Konyi <bkonyi@google.com>
> Commit-Queue: Ben Konyi <bkonyi@google.com>

TBR=bkonyi@google.com,asiva@google.com

Change-Id: Ic522ab61b430673533c94ecd0c91bee569a0add6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208960
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index d40b3a4..8ede85a 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -250,7 +250,7 @@
       "name": "dds",
       "rootUri": "../pkg/dds",
       "packageUri": "lib/",
-      "languageVersion": "2.14"
+      "languageVersion": "2.12"
     },
     {
       "name": "dev_compiler",
diff --git a/pkg/dds/dds_protocol.md b/pkg/dds/dds_protocol.md
index 9224302..b690c1a 100644
--- a/pkg/dds/dds_protocol.md
+++ b/pkg/dds/dds_protocol.md
@@ -1,6 +1,6 @@
-# Dart Development Service Protocol 1.3
+# Dart Development Service Protocol 1.2
 
-This document describes _version 1.3_ of the Dart Development Service Protocol.
+This document describes _version 1.2_ of the Dart Development Service Protocol.
 This protocol is an extension of the Dart VM Service Protocol and implements it
 in it's entirety. For details on the VM Service Protocol, see the [Dart VM Service Protocol Specification][service-protocol].
 
@@ -67,29 +67,6 @@
 
 The DDS Protocol supports all [public RPCs defined in the VM Service protocol][service-protocol-public-rpcs].
 
-### getAvailableCachedCpuSamples
-
-```
-AvailableCachedCpuSamples getAvailableCachedCpuSamples();
-```
-
-The _getAvailableCachedCpuSamples_ RPC is used to determine which caches of CPU samples
-are available. Caches are associated with individual _UserTag_ names and are specified
-when DDS is started via the _cachedUserTags_ parameter.
-
-See [AvailableCachedCpuSamples](#availablecachedcpusamples).
-
-### getCachedCpuSamples
-
-```
-CachedCpuSamples getCachedCpuSamples(string isolateId, string userTag);
-```
-
-The _getCachedCpuSamples_ RPC is used to retrieve a cache of CPU samples collected
-under a _UserTag_ with name _userTag_.
-
-See [CachedCpuSamples](#cachedcpusamples).
-
 ### getClientName
 
 ```
@@ -204,37 +181,6 @@
 
 The DDS Protocol supports all [public types defined in the VM Service protocol][service-protocol-public-types].
 
-### AvailableCachedCpuSamples
-
-```
-class AvailableCachedCpuSamples extends Response {
-  // A list of UserTag names associated with CPU sample caches.
-  string[] cacheNames;
-}
-```
-
-A collection of [UserTag] names associated with caches of CPU samples.
-
-See [getAvailableCachedCpuSamples](#getavailablecachedcpusamples).
-
-### CachedCpuSamples
-
-```
-class CachedCpuSamples extends CpuSamples {
-  // The name of the UserTag associated with this cache of samples.
-  string userTag;
-
-  // Provided if the CPU sample cache has filled and older samples have been
-  // dropped.
-  bool truncated [optional];
-}
-```
-
-An extension of [CpuSamples](#cpu-samples) which represents a set of cached
-samples, associated with a particular [UserTag] name.
-
-See [getCachedCpuSamples](#getcachedcpusamples).
-
 ### ClientName
 
 ```
@@ -274,12 +220,10 @@
 1.0 | Initial revision
 1.1 | Added `getDartDevelopmentServiceVersion` RPC.
 1.2 | Added `getStreamHistory` RPC.
-1.3 | Added `getAvailableCachedCpuSamples` and `getCachedCpuSamples` RPCs.
 
 [resume]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#resume
 [success]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#success
 [version]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#version
-[cpu-samples]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#cpusamples
 
 [service-protocol]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md
 [service-protocol-rpcs-requests-and-responses]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#rpcs-requests-and-responses
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart
index f31e447..e8f05bb 100644
--- a/pkg/dds/lib/dds.dart
+++ b/pkg/dds/lib/dds.dart
@@ -42,7 +42,6 @@
     Uri? serviceUri,
     bool enableAuthCodes = true,
     bool ipv6 = false,
-    List<String> cachedUserTags = const [],
     DevToolsConfiguration? devToolsConfiguration,
     bool logRequests = false,
   }) async {
@@ -80,7 +79,6 @@
       remoteVmServiceUri,
       serviceUri,
       enableAuthCodes,
-      cachedUserTags,
       ipv6,
       devToolsConfiguration,
       logRequests,
@@ -138,13 +136,9 @@
   /// requests.
   bool get isRunning;
 
-  /// The list of [UserTag]s used to determine which CPU samples are cached by
-  /// DDS.
-  List<String> get cachedUserTags;
-
   /// The version of the DDS protocol supported by this [DartDevelopmentService]
   /// instance.
-  static const String protocolVersion = '1.3';
+  static const String protocolVersion = '1.2';
 }
 
 class DartDevelopmentServiceException implements Exception {
diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart
index 771ccee..1df3a3a 100644
--- a/pkg/dds/lib/src/client.dart
+++ b/pkg/dds/lib/src/client.dart
@@ -206,19 +206,6 @@
       return supportedProtocols;
     });
 
-    _clientPeer.registerMethod(
-      'getAvailableCachedCpuSamples',
-      (_) => {
-        'type': 'AvailableCachedCpuSamples',
-        'cacheNames': dds.cachedUserTags,
-      },
-    );
-
-    _clientPeer.registerMethod(
-      'getCachedCpuSamples',
-      dds.isolateManager.getCachedCpuSamples,
-    );
-
     // `evaluate` and `evaluateInFrame` actually consist of multiple RPC
     // invocations, including a call to `compileExpression` which can be
     // overridden by clients which provide their own implementation (e.g.,
diff --git a/pkg/dds/lib/src/common/ring_buffer.dart b/pkg/dds/lib/src/common/ring_buffer.dart
deleted file mode 100644
index 9ae802d..0000000
--- a/pkg/dds/lib/src/common/ring_buffer.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:math';
-
-class RingBuffer<T> {
-  RingBuffer(this._bufferSize) {
-    _buffer = List<T?>.filled(
-      _bufferSize,
-      null,
-    );
-  }
-
-  Iterable<T> call() sync* {
-    for (int i = _size - 1; i >= 0; --i) {
-      yield _buffer[(_count - i - 1) % _bufferSize]!;
-    }
-  }
-
-  /// Inserts a new element into the [RingBuffer].
-  /// 
-  /// Returns the element evicted as a result of adding the new element if the
-  /// buffer is as max capacity, null otherwise.
-  T? add(T e) {
-    if (_buffer.isEmpty) {
-      return null;
-    }
-    T? evicted;
-    final index = _count % _bufferSize;
-    if (isTruncated) {
-      evicted = _buffer[index];
-    }
-    _buffer[index] = e;
-    _count++;
-    return evicted;
-  }
-
-  void resize(int size) {
-    assert(size >= 0);
-    if (size == _bufferSize) {
-      return;
-    }
-    final resized = List<T?>.filled(
-      size,
-      null,
-    );
-    int count = 0;
-    if (size > 0) {
-      for (final e in this()) {
-        resized[count++ % size] = e;
-      }
-    }
-    _count = count;
-    _bufferSize = size;
-    _buffer = resized;
-  }
-
-  bool get isTruncated => _count % bufferSize < _count;
-
-  int get bufferSize => _bufferSize;
-
-  int get _size => min(_count, _bufferSize);
-
-  int _bufferSize;
-  int _count = 0;
-  late List<T?> _buffer;
-}
diff --git a/pkg/dds/lib/src/cpu_samples_manager.dart b/pkg/dds/lib/src/cpu_samples_manager.dart
deleted file mode 100644
index 1fe5084..0000000
--- a/pkg/dds/lib/src/cpu_samples_manager.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:dds/src/common/ring_buffer.dart';
-import 'package:vm_service/vm_service.dart';
-
-import 'dds_impl.dart';
-
-/// Manages CPU sample caches for an individual [Isolate].
-class CpuSamplesManager {
-  CpuSamplesManager(this.dds, this.isolateId) {
-    for (final userTag in dds.cachedUserTags) {
-      cpuSamplesCaches[userTag] = CpuSamplesRepository(userTag);
-    }
-  }
-
-  void handleUserTagEvent(Event event) {
-    assert(event.kind! == EventKind.kUserTagChanged);
-    _currentTag = event.updatedTag!;
-    final previousTag = event.previousTag!;
-    if (cpuSamplesCaches.containsKey(previousTag)) {
-      _lastCachedTag = previousTag;
-    }
-  }
-
-  void handleCpuSamplesEvent(Event event) {
-    assert(event.kind! == EventKind.kCpuSamples);
-    // There might be some samples left in the buffer for the previously set
-    // user tag. We'll check for them here and then close out the cache.
-    if (_lastCachedTag != null) {
-      cpuSamplesCaches[_lastCachedTag]!.cacheSamples(
-        event.cpuSamples!,
-      );
-      _lastCachedTag = null;
-    }
-    cpuSamplesCaches[_currentTag]?.cacheSamples(event.cpuSamples!);
-  }
-
-  final DartDevelopmentServiceImpl dds;
-  final String isolateId;
-  final cpuSamplesCaches = <String, CpuSamplesRepository>{};
-
-  String _currentTag = '';
-  String? _lastCachedTag;
-}
-
-class CpuSamplesRepository extends RingBuffer<CpuSample> {
-  // TODO: math to figure out proper buffer sizes.
-  CpuSamplesRepository(
-    this.tag, [
-    int bufferSize = 1000000,
-  ]) : super(bufferSize);
-
-  void cacheSamples(CpuSamples samples) {
-    String getFunctionId(ProfileFunction function) {
-      final functionObject = function.function;
-      if (functionObject is NativeFunction) {
-        return 'native/${functionObject.name}';
-      }
-      return functionObject.id!;
-    }
-
-    // Initialize upon seeing our first samples.
-    if (functions.isEmpty) {
-      samplePeriod = samples.samplePeriod!;
-      maxStackDepth = samples.maxStackDepth!;
-      pid = samples.pid!;
-      functions.addAll(samples.functions!);
-
-      // Build the initial id to function index mapping. This allows for us to
-      // lookup a ProfileFunction in the global function list stored in this
-      // cache. This works since most ProfileFunction objects will have an
-      // associated function with a *typically* stable service ID that we can
-      // use as a key.
-      //
-      // TODO(bkonyi): investigate creating some form of stable ID for
-      // Functions tied to closures.
-      for (int i = 0; i < functions.length; ++i) {
-        idToFunctionIndex[getFunctionId(functions[i])] = i;
-      }
-
-      // Clear tick information as we'll need to recalculate these values later
-      // when a request for samples from this repository is received.
-      for (final f in functions) {
-        f.inclusiveTicks = 0;
-        f.exclusiveTicks = 0;
-      }
-
-      _firstSampleTimestamp = samples.timeOriginMicros!;
-    } else {
-      final newFunctions = samples.functions!;
-      final indexMapping = <int, int>{};
-
-      // Check to see if we've got a function object we've never seen before.
-      for (int i = 0; i < newFunctions.length; ++i) {
-        final key = getFunctionId(newFunctions[i]);
-        if (!idToFunctionIndex.containsKey(key)) {
-          idToFunctionIndex[key] = functions.length;
-          // Keep track of the original index and the location of the function
-          // in the master function list so we can update the function indicies
-          // for each sample in this batch.
-          indexMapping[i] = functions.length;
-          functions.add(newFunctions[i]);
-
-          // Reset tick state as we'll recalculate later.
-          functions.last.inclusiveTicks = 0;
-          functions.last.exclusiveTicks = 0;
-        }
-      }
-
-      // Update the indicies into the function table for functions that were
-      // newly processed in the most recent event.
-      for (final sample in samples.samples!) {
-        final stack = sample.stack!;
-        for (int i = 0; i < stack.length; ++i) {
-          if (indexMapping.containsKey(stack[i])) {
-            stack[i] = indexMapping[stack[i]]!;
-          }
-        }
-      }
-    }
-
-    final relevantSamples = samples.samples!.where((s) => s.userTag == tag);
-    for (final sample in relevantSamples) {
-      add(sample);
-    }
-  }
-
-  @override
-  CpuSample? add(CpuSample sample) {
-    final evicted = super.add(sample);
-
-    void updateTicksForSample(CpuSample sample, int increment) {
-      final stack = sample.stack!;
-      for (int i = 0; i < stack.length; ++i) {
-        final function = functions[stack[i]];
-        function.inclusiveTicks = function.inclusiveTicks! + increment;
-        if (i + 1 == stack.length) {
-          function.exclusiveTicks = function.exclusiveTicks! + increment;
-        }
-      }
-    }
-
-    if (evicted != null) {
-      // If a sample is evicted from the cache, we need to decrement the tick
-      // counters for each function in the sample's stack.
-      updateTicksForSample(sample, -1);
-
-      // We also need to change the first timestamp to that of the next oldest
-      // sample.
-      _firstSampleTimestamp = call().first.timestamp!;
-    }
-    _lastSampleTimestamp = sample.timestamp!;
-
-    // Update function ticks to include the new sample.
-    updateTicksForSample(sample, 1);
-
-    return evicted;
-  }
-
-  Map<String, dynamic> toJson() {
-    return {
-      'type': 'CachedCpuSamples',
-      'userTag': tag,
-      'truncated': isTruncated,
-      if (functions.isNotEmpty) ...{
-        'samplePeriod': samplePeriod,
-        'maxStackDepth': maxStackDepth,
-      },
-      'timeOriginMicros': _firstSampleTimestamp,
-      'timeExtentMicros': _lastSampleTimestamp - _firstSampleTimestamp,
-      'functions': [
-        // TODO(bkonyi): remove functions with no ticks and update sample stacks.
-        for (final f in functions) f.toJson(),
-      ],
-      'sampleCount': call().length,
-      'samples': [
-        for (final s in call()) s.toJson(),
-      ]
-    };
-  }
-
-  /// The UserTag associated with all samples stored in this repository.
-  final String tag;
-
-  /// The list of function references with corresponding profiler tick data.
-  /// ** NOTE **: The tick values here need to be updated as new CpuSamples
-  /// events are delivered.
-  final functions = <ProfileFunction>[];
-  final idToFunctionIndex = <String, int>{};
-
-  /// Assume sample period and max stack depth won't change.
-  late final int samplePeriod;
-  late final int maxStackDepth;
-
-  late final int pid;
-
-  int _firstSampleTimestamp = 0;
-  int _lastSampleTimestamp = 0;
-}
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index 87ed83d..4360bcc 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
 import 'dart:math';
@@ -55,7 +54,6 @@
     this._remoteVmServiceUri,
     this._uri,
     this._authCodesEnabled,
-    this._cachedUserTags,
     this._ipv6,
     this._devToolsConfiguration,
     this.shouldLogRequests,
@@ -383,9 +381,6 @@
 
   final DevToolsConfiguration? _devToolsConfiguration;
 
-  List<String> get cachedUserTags => UnmodifiableListView(_cachedUserTags);
-  final List<String> _cachedUserTags;
-
   Future<void> get done => _done.future;
   Completer _done = Completer<void>();
   bool _shuttingDown = false;
diff --git a/pkg/dds/lib/src/isolate_manager.dart b/pkg/dds/lib/src/isolate_manager.dart
index 3a7a067..e9e14df 100644
--- a/pkg/dds/lib/src/isolate_manager.dart
+++ b/pkg/dds/lib/src/isolate_manager.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:dds/src/cpu_samples_manager.dart';
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:vm_service/vm_service.dart';
 
 import 'client.dart';
 import 'constants.dart';
@@ -37,11 +35,7 @@
 }
 
 class _RunningIsolate {
-  _RunningIsolate(this.isolateManager, this.id, this.name)
-      : cpuSamplesManager = CpuSamplesManager(
-          isolateManager.dds,
-          id,
-        );
+  _RunningIsolate(this.isolateManager, this.id, this.name);
 
   // State setters.
   void pausedOnExit() => _state = _IsolateState.pauseExit;
@@ -109,29 +103,6 @@
   /// Should always be called after an isolate is resumed.
   void clearResumeApprovals() => _resumeApprovalsByName.clear();
 
-  Map<String, dynamic> getCachedCpuSamples(String userTag) {
-    final repo = cpuSamplesManager.cpuSamplesCaches[userTag];
-    if (repo == null) {
-      throw json_rpc.RpcException.invalidParams(
-        'CPU sample caching is not enabled for tag: "$userTag"',
-      );
-    }
-    return repo.toJson();
-  }
-
-  void handleEvent(Event event) {
-    switch (event.kind) {
-      case EventKind.kUserTagChanged:
-        cpuSamplesManager.handleUserTagEvent(event);
-        return;
-      case EventKind.kCpuSamples:
-        cpuSamplesManager.handleCpuSamplesEvent(event);
-        return;
-      default:
-        return;
-    }
-  }
-
   int get _isolateStateMask => isolateStateToMaskMapping[_state] ?? 0;
 
   static const isolateStateToMaskMapping = {
@@ -141,7 +112,6 @@
   };
 
   final IsolateManager isolateManager;
-  final CpuSamplesManager cpuSamplesManager;
   final String name;
   final String id;
   final Set<String?> _resumeApprovalsByName = {};
@@ -152,25 +122,20 @@
   IsolateManager(this.dds);
 
   /// Handles state changes for isolates.
-  void handleIsolateEvent(Event event) {
+  void handleIsolateEvent(json_rpc.Parameters parameters) {
+    final event = parameters['event'];
+    final eventKind = event['kind'].asString;
+
     // There's no interesting information about isolate state associated with
     // and IsolateSpawn event.
-    // TODO(bkonyi): why isn't IsolateSpawn in package:vm_service
-    if (event.kind! == ServiceEvents.isolateSpawn) {
+    if (eventKind == ServiceEvents.isolateSpawn) {
       return;
     }
 
-    final isolateData = event.isolate!;
-    final id = isolateData.id!;
-    final name = isolateData.name!;
-    _updateIsolateState(id, name, event.kind!);
-  }
-
-  void routeEventToIsolate(Event event) {
-    final isolateId = event.isolate!.id!;
-    if (isolates.containsKey(isolateId)) {
-      isolates[isolateId]!.handleEvent(event);
-    }
+    final isolateData = event['isolate'];
+    final id = isolateData['id'].asString;
+    final name = isolateData['name'].asString;
+    _updateIsolateState(id, name, eventKind);
   }
 
   void _updateIsolateState(String id, String name, String eventKind) {
@@ -265,16 +230,6 @@
     return RPCResponses.success;
   }
 
-  Map<String, dynamic> getCachedCpuSamples(json_rpc.Parameters parameters) {
-    final isolateId = parameters['isolateId'].asString;
-    if (!isolates.containsKey(isolateId)) {
-      return RPCResponses.collectedSentinel;
-    }
-    final isolate = isolates[isolateId]!;
-    final userTag = parameters['userTag'].asString;
-    return isolate.getCachedCpuSamples(userTag);
-  }
-
   /// Forwards a `resume` request to the VM service.
   Future<Map<String, dynamic>> _sendResumeRequest(
     String isolateId,
diff --git a/pkg/dds/lib/src/logging_repository.dart b/pkg/dds/lib/src/logging_repository.dart
index 062529a..4537d7e 100644
--- a/pkg/dds/lib/src/logging_repository.dart
+++ b/pkg/dds/lib/src/logging_repository.dart
@@ -2,16 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:math';
+
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 
 import 'client.dart';
-import 'common/ring_buffer.dart';
 
 /// [LoggingRepository] is used to store historical log messages from the
 /// target VM service. Clients which connect to DDS and subscribe to the
 /// `Logging` stream will be sent all messages contained within this repository
 /// upon initial subscription.
-class LoggingRepository extends RingBuffer<Map<String, dynamic>> {
+class LoggingRepository extends _RingBuffer<Map<String, dynamic>> {
   LoggingRepository([int logHistoryLength = 10000]) : super(logHistoryLength) {
     // TODO(bkonyi): enforce log history limit when DartDevelopmentService
     // allows for this to be set via Dart code.
@@ -45,3 +46,53 @@
   static const int _kMaxLogBufferSize = 100000;
 }
 
+// TODO(bkonyi): move to standalone file if we decide to use this elsewhere.
+class _RingBuffer<T> {
+  _RingBuffer(this._bufferSize) {
+    _buffer = List<T?>.filled(
+      _bufferSize,
+      null,
+    );
+  }
+
+  Iterable<T> call() sync* {
+    for (int i = _size - 1; i >= 0; --i) {
+      yield _buffer[(_count - i - 1) % _bufferSize]!;
+    }
+  }
+
+  void add(T e) {
+    if (_buffer.isEmpty) {
+      return;
+    }
+    _buffer[_count++ % _bufferSize] = e;
+  }
+
+  void resize(int size) {
+    assert(size >= 0);
+    if (size == _bufferSize) {
+      return;
+    }
+    final resized = List<T?>.filled(
+      size,
+      null,
+    );
+    int count = 0;
+    if (size > 0) {
+      for (final e in this()) {
+        resized[count++ % size] = e;
+      }
+    }
+    _count = count;
+    _bufferSize = size;
+    _buffer = resized;
+  }
+
+  int get bufferSize => _bufferSize;
+
+  int get _size => min(_count, _bufferSize);
+
+  int _bufferSize;
+  int _count = 0;
+  late List<T?> _buffer;
+}
diff --git a/pkg/dds/lib/src/stream_manager.dart b/pkg/dds/lib/src/stream_manager.dart
index f396c04..94f791a 100644
--- a/pkg/dds/lib/src/stream_manager.dart
+++ b/pkg/dds/lib/src/stream_manager.dart
@@ -5,7 +5,6 @@
 import 'dart:typed_data';
 
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:vm_service/vm_service.dart';
 
 import 'client.dart';
 import 'dds_impl.dart';
@@ -108,31 +107,18 @@
         // Stdout and Stderr streams may not exist.
       }
     }
-    if (dds.cachedUserTags.isNotEmpty) {
-      await streamListen(null, EventStreams.kProfiler);
-    }
     dds.vmServiceClient.registerMethod(
       'streamNotify',
-      (json_rpc.Parameters parameters) {
+      (parameters) {
         final streamId = parameters['streamId'].asString;
-        final event =
-            Event.parse(parameters['event'].asMap.cast<String, dynamic>())!;
-
         // Forward events from the streams IsolateManager subscribes to.
         if (isolateManagerStreams.contains(streamId)) {
-          dds.isolateManager.handleIsolateEvent(event);
+          dds.isolateManager.handleIsolateEvent(parameters);
         }
         // Keep a history of messages to send to clients when they first
         // subscribe to a stream with an event history.
         if (loggingRepositories.containsKey(streamId)) {
-          loggingRepositories[streamId]!.add(
-            parameters.asMap.cast<String, dynamic>(),
-          );
-        }
-        // If the event contains an isolate, forward the event to the
-        // corresponding isolate to be handled.
-        if (event.isolate != null) {
-          dds.isolateManager.routeEventToIsolate(event);
+          loggingRepositories[streamId]!.add(parameters.asMap);
         }
         streamNotify(streamId, parameters.value);
       },
@@ -265,7 +251,6 @@
   static const kExtensionStream = 'Extension';
   static const kIsolateStream = 'Isolate';
   static const kLoggingStream = 'Logging';
-  static const kProfilerStream = 'Profiler';
   static const kStderrStream = 'Stderr';
   static const kStdoutStream = 'Stdout';
 
@@ -287,17 +272,10 @@
     kStdoutStream,
   };
 
-  // Never cancel the profiler stream as `CpuSampleRepository` requires
-  // `UserTagChanged` events to enable/disable sample caching.
-  static const cpuSampleRepositoryStreams = <String>{
-    kProfilerStream,
-  };
-
   // The set of streams that DDS requires to function.
   static final ddsCoreStreams = <String>{
     ...isolateManagerStreams,
     ...loggingRepositoryStreams,
-    ...cpuSampleRepositoryStreams,
   };
 
   final DartDevelopmentServiceImpl dds;
diff --git a/pkg/dds/lib/vm_service_extensions.dart b/pkg/dds/lib/vm_service_extensions.dart
index 09bda25..903c14a 100644
--- a/pkg/dds/lib/vm_service_extensions.dart
+++ b/pkg/dds/lib/vm_service_extensions.dart
@@ -13,46 +13,18 @@
   static bool _factoriesRegistered = false;
   static Version? _ddsVersion;
 
-  /// The [getDartDevelopmentServiceVersion] RPC is used to determine what version of
+  /// The _getDartDevelopmentServiceVersion_ RPC is used to determine what version of
   /// the Dart Development Service Protocol is served by a DDS instance.
   ///
   /// The result of this call is cached for subsequent invocations.
   Future<Version> getDartDevelopmentServiceVersion() async {
     if (_ddsVersion == null) {
-      _ddsVersion = await _callHelper<Version>(
-        'getDartDevelopmentServiceVersion',
-      );
+      _ddsVersion =
+          await _callHelper<Version>('getDartDevelopmentServiceVersion');
     }
     return _ddsVersion!;
   }
 
-  /// The [getCachedCpuSamples] RPC is used to retrieve a cache of CPU samples
-  /// collected under a [UserTag] with name `userTag`.
-  Future<CachedCpuSamples> getCachedCpuSamples(
-      String isolateId, String userTag) async {
-    if (!(await _versionCheck(1, 3))) {
-      throw UnimplementedError('getCachedCpuSamples requires DDS version 1.3');
-    }
-    return _callHelper<CachedCpuSamples>('getCachedCpuSamples', args: {
-      'isolateId': isolateId,
-      'userTag': userTag,
-    });
-  }
-
-  /// The [getAvailableCachedCpuSamples] RPC is used to determine which caches of CPU samples
-  /// are available. Caches are associated with individual [UserTag] names and are specified
-  /// when DDS is started via the `cachedUserTags` parameter.
-  Future<AvailableCachedCpuSamples> getAvailableCachedCpuSamples() async {
-    if (!(await _versionCheck(1, 3))) {
-      throw UnimplementedError(
-        'getAvailableCachedCpuSamples requires DDS version 1.3',
-      );
-    }
-    return _callHelper<AvailableCachedCpuSamples>(
-      'getAvailableCachedCpuSamples',
-    );
-  }
-
   /// Retrieve the event history for `stream`.
   ///
   /// If `stream` does not have event history collected, a parameter error is
@@ -154,11 +126,6 @@
 
   static void _registerFactories() {
     addTypeFactory('StreamHistory', StreamHistory.parse);
-    addTypeFactory(
-      'AvailableCachedCpuSamples',
-      AvailableCachedCpuSamples.parse,
-    );
-    addTypeFactory('CachedCpuSamples', CachedCpuSamples.parse);
     _factoriesRegistered = true;
   }
 }
@@ -187,86 +154,3 @@
   List<Event> get history => UnmodifiableListView(_history);
   final List<Event> _history;
 }
-
-/// An extension of [CpuSamples] which represents a set of cached samples,
-/// associated with a particular [UserTag] name.
-class CachedCpuSamples extends CpuSamples {
-  static CachedCpuSamples? parse(Map<String, dynamic>? json) =>
-      json == null ? null : CachedCpuSamples._fromJson(json);
-
-  CachedCpuSamples({
-    required this.userTag,
-    this.truncated,
-    required int? samplePeriod,
-    required int? maxStackDepth,
-    required int? sampleCount,
-    required int? timeSpan,
-    required int? timeOriginMicros,
-    required int? timeExtentMicros,
-    required int? pid,
-    required List<ProfileFunction>? functions,
-    required List<CpuSample>? samples,
-  }) : super(
-          samplePeriod: samplePeriod,
-          maxStackDepth: maxStackDepth,
-          sampleCount: sampleCount,
-          timeSpan: timeSpan,
-          timeOriginMicros: timeOriginMicros,
-          timeExtentMicros: timeExtentMicros,
-          pid: pid,
-          functions: functions,
-          samples: samples,
-        );
-
-  CachedCpuSamples._fromJson(Map<String, dynamic> json)
-      : userTag = json['userTag']!,
-        truncated = json['truncated'],
-        super(
-          samplePeriod: json['samplePeriod'] ?? -1,
-          maxStackDepth: json['maxStackDepth'] ?? -1,
-          sampleCount: json['sampleCount'] ?? -1,
-          timeSpan: json['timeSpan'] ?? -1,
-          timeOriginMicros: json['timeOriginMicros'] ?? -1,
-          timeExtentMicros: json['timeExtentMicros'] ?? -1,
-          pid: json['pid'] ?? -1,
-          functions: List<ProfileFunction>.from(
-            createServiceObject(json['functions'], const ['ProfileFunction'])
-                    as List? ??
-                [],
-          ),
-          samples: List<CpuSample>.from(
-            createServiceObject(json['samples'], const ['CpuSample'])
-                    as List? ??
-                [],
-          ),
-        );
-
-  @override
-  String get type => 'CachedCpuSamples';
-
-  /// The name of the [UserTag] associated with this cache of [CpuSamples].
-  final String userTag;
-
-  /// Provided if the CPU sample cache has filled and older samples have been
-  /// dropped.
-  final bool? truncated;
-}
-
-/// A collection of [UserTag] names associated with caches of CPU samples.
-class AvailableCachedCpuSamples extends Response {
-  static AvailableCachedCpuSamples? parse(Map<String, dynamic>? json) =>
-      json == null ? null : AvailableCachedCpuSamples._fromJson(json);
-
-  AvailableCachedCpuSamples({
-    required this.cacheNames,
-  });
-
-  AvailableCachedCpuSamples._fromJson(Map<String, dynamic> json)
-      : cacheNames = List<String>.from(json['cacheNames']);
-
-  @override
-  String get type => 'AvailableCachedUserTagCpuSamples';
-
-  /// A [List] of [UserTag] names associated with CPU sample caches.
-  final List<String> cacheNames;
-}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 5468e58..cfbf779 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,12 +3,12 @@
   A library used to spawn the Dart Developer Service, used to communicate with
   a Dart VM Service instance.
 
-version: 2.1.0
+version: 2.0.2
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
 environment:
-  sdk: '>=2.14.0-0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   async: ^2.4.1
@@ -26,7 +26,7 @@
   sse: ^4.0.0
   stream_channel: ^2.0.0
   usage: ^4.0.0
-  vm_service: ^7.2.0
+  vm_service: ^7.0.0
   web_socket_channel: ^2.0.0
 
 dev_dependencies:
diff --git a/pkg/dds/test/common/test_helper.dart b/pkg/dds/test/common/test_helper.dart
index 077e75a..9fc441b 100644
--- a/pkg/dds/test/common/test_helper.dart
+++ b/pkg/dds/test/common/test_helper.dart
@@ -24,7 +24,6 @@
     '--observe=0',
     if (pauseOnStart) '--pause-isolates-on-start',
     '--write-service-info=$serviceInfoUri',
-    '--sample-buffer-duration=1',
     ...Platform.executableArguments,
     Platform.script.resolve(script).toString(),
   ];
diff --git a/pkg/dds/test/get_cached_cpu_samples_script.dart b/pkg/dds/test/get_cached_cpu_samples_script.dart
deleted file mode 100644
index 5949574..0000000
--- a/pkg/dds/test/get_cached_cpu_samples_script.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:developer';
-
-fib(int n) {
-  if (n <= 1) {
-    return n;
-  }
-  return fib(n - 1) + fib(n - 2);
-}
-
-void main() {
-  UserTag('Testing').makeCurrent();
-  int i = 5;
-  while (true) {
-    ++i;
-    fib(i);
-  }
-}
diff --git a/pkg/dds/test/get_cached_cpu_samples_test.dart b/pkg/dds/test/get_cached_cpu_samples_test.dart
deleted file mode 100644
index fe8a223..0000000
--- a/pkg/dds/test/get_cached_cpu_samples_test.dart
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:dds/dds.dart';
-import 'package:dds/vm_service_extensions.dart';
-import 'package:test/test.dart';
-import 'package:vm_service/vm_service.dart';
-import 'package:vm_service/vm_service_io.dart';
-import 'common/test_helper.dart';
-
-void main() {
-  late Process process;
-  late DartDevelopmentService dds;
-
-  setUp(() async {
-    process = await spawnDartProcess(
-      'get_cached_cpu_samples_script.dart',
-    );
-  });
-
-  tearDown(() async {
-    await dds.shutdown();
-    process.kill();
-  });
-
-  test(
-    'No UserTags to cache',
-    () async {
-      dds = await DartDevelopmentService.startDartDevelopmentService(
-        remoteVmServiceUri,
-      );
-      expect(dds.isRunning, true);
-      final service = await vmServiceConnectUri(dds.wsUri.toString());
-
-      // We didn't provide `cachedUserTags` when starting DDS, so we shouldn't
-      // be caching anything.
-      final availableCaches = await service.getAvailableCachedCpuSamples();
-      expect(availableCaches.cacheNames.length, 0);
-
-      final isolate = (await service.getVM()).isolates!.first;
-
-      try {
-        await service.getCachedCpuSamples(isolate.id!, 'Fake');
-        fail('Invalid userTag did not cause an exception');
-      } on RPCError catch (e) {
-        expect(
-          e.message,
-          'CPU sample caching is not enabled for tag: "Fake"',
-        );
-      }
-    },
-    timeout: Timeout.none,
-  );
-
-  test(
-    'Cache CPU samples for provided UserTag name',
-    () async {
-      const kUserTag = 'Testing';
-      dds = await DartDevelopmentService.startDartDevelopmentService(
-        remoteVmServiceUri,
-        cachedUserTags: [kUserTag],
-      );
-      expect(dds.isRunning, true);
-      final service = await vmServiceConnectUri(dds.wsUri.toString());
-
-      // Ensure we're caching results for samples under the 'Testing' UserTag.
-      final availableCaches = await service.getAvailableCachedCpuSamples();
-      expect(availableCaches.cacheNames.length, 1);
-      expect(availableCaches.cacheNames.first, kUserTag);
-
-      final isolate = (await service.getVM()).isolates!.first;
-
-      final completer = Completer<void>();
-      int i = 0;
-      int count = 0;
-      service.onProfilerEvent.listen((event) async {
-        if (event.kind == EventKind.kCpuSamples &&
-            event.isolate!.id! == isolate.id!) {
-          // Pause so we don't evict another block of samples before we've
-          // retrieved the cached samples after this event.
-          await service.pause(isolate.id!);
-
-          // Ensure the number of CPU samples in the CpuSample event is
-          // is consistent with the number of samples in the cache.
-          expect(event.cpuSamples, isNotNull);
-          count += event.cpuSamples!.samples!
-              .where((e) => e.userTag == kUserTag)
-              .length;
-          final cache = await service.getCachedCpuSamples(
-            isolate.id!,
-            availableCaches.cacheNames.first,
-          );
-          expect(cache.sampleCount, count);
-
-          await service.resume(isolate.id!);
-          i++;
-          if (i == 3) {
-            completer.complete();
-          }
-        }
-      });
-      await service.streamListen(EventStreams.kProfiler);
-      await service.resume(isolate.id!);
-      await completer.future;
-    },
-    timeout: Timeout.none,
-  );
-}
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index d2a4144..3c1a964 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,12 +1,5 @@
 # Changelog
 
-## 7.2.0
-- Update to version `3.50` of the spec.
-- Added `CpuSamples` event kind, and `cpuSamples` property to `Event`.
-- Added `returnType`, `parameters`, and `typeParameters` to `InstanceRef`,
-  and `implicit` to `FunctionRef`.
-- Added `Parameter` type.
-
 ## 7.1.1
 - Update to version `3.48` of the spec.
 - Added `shows` and `hides` properties to `LibraryDependency`.
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 5677862..5aad6b6 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
   A library to communicate with a service implementing the Dart VM
   service protocol.
 
-version: 7.2.0
+version: 7.1.1
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 3ef9c62..b1a7315 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2493,25 +2493,6 @@
     ServiceIsolate::SendIsolateShutdownMessage();
 #if !defined(PRODUCT)
     debugger()->Shutdown();
-    // Cleanup profiler state.
-    SampleBlock* cpu_block = current_sample_block();
-    if (cpu_block != nullptr) {
-      cpu_block->release_block();
-    }
-    SampleBlock* allocation_block = current_allocation_sample_block();
-    if (allocation_block != nullptr) {
-      allocation_block->release_block();
-    }
-
-    // Process the previously assigned sample blocks if we're using the
-    // profiler's sample buffer. Some tests create their own SampleBlockBuffer
-    // and handle block processing themselves.
-    if ((cpu_block != nullptr || allocation_block != nullptr) &&
-        Profiler::sample_block_buffer() != nullptr) {
-      StackZone zone(thread);
-      HandleScope handle_scope(thread);
-      Profiler::sample_block_buffer()->ProcessCompletedBlocks();
-    }
 #endif
   }
 
@@ -2570,6 +2551,26 @@
   // requests anymore.
   Thread::ExitIsolate();
 
+#if !defined(PRODUCT)
+  // Cleanup profiler state.
+  SampleBlock* cpu_block = isolate->current_sample_block();
+  if (cpu_block != nullptr) {
+    cpu_block->release_block();
+  }
+  SampleBlock* allocation_block = isolate->current_allocation_sample_block();
+  if (allocation_block != nullptr) {
+    allocation_block->release_block();
+  }
+
+  // Process the previously assigned sample blocks if we're using the
+  // profiler's sample buffer. Some tests create their own SampleBlockBuffer
+  // and handle block processing themselves.
+  if ((cpu_block != nullptr || allocation_block != nullptr) &&
+      Profiler::sample_block_buffer() != nullptr) {
+    Profiler::sample_block_buffer()->ProcessCompletedBlocks();
+  }
+#endif  // !defined(PRODUCT)
+
   // Now it's safe to delete the isolate.
   delete isolate;
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index cdd8783..2436574 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -226,9 +226,7 @@
   int64_t start = Dart_TimelineGetMicros();
   for (intptr_t i = 0; i < capacity_; ++i) {
     SampleBlock* block = &blocks_[i];
-    // Only evict blocks owned by the current thread.
-    if (block->owner() == thread->isolate() && block->is_full() &&
-        !block->evictable()) {
+    if (block->is_full() && !block->evictable()) {
       if (Service::profiler_stream.enabled()) {
         Profile profile(block->owner());
         profile.Build(thread, nullptr, block);
@@ -332,12 +330,8 @@
     isolate->set_current_sample_block(next);
   }
   next->set_is_allocation_block(allocation_sample);
-  bool scheduled = can_process_block_.exchange(true);
-  // We don't process samples on the kernel isolate.
-  if (!isolate->is_kernel_isolate() && !isolate->is_service_isolate() &&
-      !scheduled) {
-    isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
-  }
+  can_process_block_.store(true);
+  isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
   return ReserveSampleImpl(isolate, allocation_sample);
 }
 
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 74217b6..09a3b25 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -450,15 +450,11 @@
     }
 
 #if !defined(PRODUCT)
-    // Don't block the kernel isolate to process CPU samples as we can
-    // potentially deadlock when trying to compile source for the main isolate.
-    if (!isolate()->is_kernel_isolate() && !isolate()->is_service_isolate()) {
-      // Processes completed SampleBlocks and sends CPU sample events over the
-      // service protocol when applicable.
-      SampleBlockBuffer* sample_buffer = Profiler::sample_block_buffer();
-      if (sample_buffer != nullptr && sample_buffer->process_blocks()) {
-        sample_buffer->ProcessCompletedBlocks();
-      }
+    // Processes completed SampleBlocks and sends CPU sample events over the
+    // service protocol when applicable.
+    SampleBlockBuffer* sample_buffer = Profiler::sample_block_buffer();
+    if (sample_buffer != nullptr && sample_buffer->process_blocks()) {
+      sample_buffer->ProcessCompletedBlocks();
     }
 #endif  // !defined(PRODUCT)
   }