Revert "Reland "Java Heap Profiler for Perfetto.""

This reverts commit 5a446bd6c72d25ed2435fb2279bd8617ad003d2e.

Reason for revert: Multiple gtests failing

Change-Id: I07abd641d49518a48aed7e401c1927aa7c027937
diff --git a/Android.mk b/Android.mk
index 64d72c1..1904f65 100644
--- a/Android.mk
+++ b/Android.mk
@@ -426,7 +426,6 @@
     libopenjdkjvmti \
     profman \
     libadbconnection \
-    libperfetto_hprof \
 
 # Potentially add in debug variants:
 #
@@ -449,7 +448,6 @@
     libopenjdkjvmtid \
     profmand \
     libadbconnectiond \
-    libperfetto_hprofd \
 
 endif
 endif
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 284cc18..a7366c9 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -40,11 +40,6 @@
     "libopenjdkjvm",
     "libopenjdkjvmti",
 ]
-
-art_runtime_base_native_device_only_shared_libs = [
-    "libperfetto_hprof",
-]
-
 bionic_native_shared_libs = [
     // External API (having APEX stubs).
     "libc",
@@ -86,10 +81,6 @@
     "libopenjdkjvmtid",
 ]
 
-art_runtime_base_native_device_only_debug_shared_libs = [
-  "libperfetto_hprofd",
-]
-
 // Tools common to both device APEX and host APEX. Derived from art-tools in art/Android.mk.
 art_tools_common_binaries = [
     "dexdump",
@@ -257,7 +248,6 @@
     manifest: "manifest-art.json",
     java_libs: libcore_java_libs,
     native_shared_libs: art_runtime_base_native_shared_libs +
-        art_runtime_base_native_device_only_shared_libs +
         libcore_native_device_only_shared_libs +
         libcore_native_shared_libs,
     multilib: {
@@ -291,8 +281,7 @@
 apex_defaults {
     name: "com.android.art-dev-defaults",
     defaults: ["com.android.art-defaults"],
-    native_shared_libs: art_runtime_base_native_device_only_debug_shared_libs +
-        art_runtime_debug_native_shared_libs +
+    native_shared_libs: art_runtime_debug_native_shared_libs +
         libcore_debug_native_shared_libs,
     multilib: {
         both: {
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 2b42404..7a992e6 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -528,7 +528,6 @@
 
     # Check internal libraries for ART.
     self._checker.check_prefer64_library('libart-disassembler')
-    self._checker.check_native_library('libperfetto_hprof')
 
     # Check exported native libraries for Managed Core Library.
     self._checker.check_native_library('libandroidicu')
@@ -622,7 +621,6 @@
     # Check ART internal libraries.
     self._checker.check_native_library('libdexfiled_external')
     self._checker.check_prefer64_library('libartd-disassembler')
-    self._checker.check_native_library('libperfetto_hprofd')
 
     # Check internal native library dependencies.
     #
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index b0a7f1f..f2ae996 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -122,13 +122,12 @@
     }
     if (!started) {
       // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
-      // started here; this includes the hprof_listener signal handler thread for perfetto_hprof.
+      // started here.
       if (art::kIsDebugBuild) {
         std::string name;
         self->GetThreadName(name);
         if (name != "JDWP" &&
             name != "Signal Catcher" &&
-            name != "hprof_listener" &&
             !android::base::StartsWith(name, "Jit thread pool") &&
             !android::base::StartsWith(name, "Runtime worker thread")) {
           LOG(FATAL) << "Unexpected thread before start: " << name << " id: "
diff --git a/perfetto_hprof/Android.bp b/perfetto_hprof/Android.bp
deleted file mode 100644
index 07024e2..0000000
--- a/perfetto_hprof/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// Build variants {target} x {debug,ndebug} x {32,64}
-
-// This depends on the Perfetto client API. This uses the ProducerPort to
-// communicate to the system trace. This is an API whose ABI is maintained
-// to be backwards compatible, see
-// https://android.googlesource.com/platform/external/perfetto/+/refs/heads/master/protos/perfetto/ipc/producer_port.proto.
-
-cc_defaults {
-    name: "perfetto_hprof-defaults",
-    host_supported: false,
-    srcs: ["perfetto_hprof.cc"],
-    defaults: ["art_defaults"],
-    include_dirs: [
-        "external/perfetto/include",
-    ],
-
-    // Note that this tool needs to be built for both 32-bit and 64-bit since it requires
-    // to be same ISA as what it is attached to.
-    compile_multilib: "both",
-
-    shared_libs: [
-        "libbase",
-        "liblog",
-    ],
-    static_libs: [
-        "libperfetto_client_experimental",
-        "perfetto_src_tracing_ipc",
-        "perfetto_trace_protos",
-        // TODO(132880619): Remove this as soon as the Perfetto client API no
-        // longer depends on this.
-        "libprotobuf-cpp-lite",
-    ],
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-    header_libs: [
-        "libnativehelper_header_only",
-    ],
-}
-
-art_cc_library {
-    name: "libperfetto_hprof",
-    defaults: ["perfetto_hprof-defaults"],
-    shared_libs: [
-        "libart",
-        "libartbase",
-    ],
-}
-
-art_cc_library {
-    name: "libperfetto_hprofd",
-    defaults: [
-        "art_debug_defaults",
-        "perfetto_hprof-defaults",
-    ],
-    shared_libs: [
-        "libartd",
-        "libartbased",
-    ],
-}
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
deleted file mode 100644
index 23d61ce..0000000
--- a/perfetto_hprof/perfetto_hprof.cc
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "perfetto_hprof"
-
-#include <android-base/logging.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sched.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <thread>
-
-#include "gc/heap-visit-objects-inl.h"
-#include "gc/heap.h"
-#include "gc/scoped_gc_critical_section.h"
-#include "mirror/object-refvisitor-inl.h"
-#include "nativehelper/scoped_local_ref.h"
-#include "perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "perfetto/trace/profiling/heap_graph.pbzero.h"
-#include "perfetto/trace/profiling/profile_common.pbzero.h"
-#include "perfetto/tracing.h"
-#include "runtime-inl.h"
-#include "runtime_callbacks.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread_list.h"
-#include "well_known_classes.h"
-
-// There are three threads involved in this:
-// * listener thread: this is idle in the background when this plugin gets loaded, and waits
-//   for data on on g_signal_pipe_fds.
-// * signal thread: an arbitrary thread that handles the signal and writes data to
-//   g_signal_pipe_fds.
-// * perfetto producer thread: once the signal is received, the app forks. In the newly forked
-//   child, the Perfetto Client API spawns a thread to communicate with traced.
-
-namespace perfetto_hprof {
-
-constexpr int kJavaHeapprofdSignal = __SIGRTMIN + 6;
-constexpr time_t kWatchdogTimeoutSec = 120;
-constexpr size_t kObjectsPerPacket = 100;
-constexpr char kByte[1] = {'x'};
-
-enum class State {
-  kWaitForListener,
-  kWaitForStart,
-  kStart,
-  kEnd,
-};
-
-static art::Mutex& GetStateMutex() {
-  static art::Mutex state_mutex("perfetto_hprof_state_mutex", art::LockLevel::kGenericBottomLock);
-  return state_mutex;
-}
-
-static art::ConditionVariable& GetStateCV() {
-  static art::ConditionVariable state_cv("perfetto_hprof_state_cv", GetStateMutex());
-  return state_cv;
-}
-
-static State g_state = State::kWaitForListener;
-
-// Pipe to signal from the signal handler into a worker thread that handles the
-// dump requests.
-int g_signal_pipe_fds[2];
-static struct sigaction g_orig_act = {};
-
-uint64_t FindOrAppend(std::map<std::string, uint64_t>* m,
-                      const std::string& s) {
-  auto it = m->find(s);
-  if (it == m->end()) {
-    std::tie(it, std::ignore) = m->emplace(s, m->size());
-  }
-  return it->second;
-}
-
-void ArmWatchdogOrDie() {
-  timer_t timerid{};
-  struct sigevent sev {};
-  sev.sigev_notify = SIGEV_SIGNAL;
-  sev.sigev_signo = SIGKILL;
-
-  if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) == -1) {
-    // This only gets called in the child, so we can fatal without impacting
-    // the app.
-    PLOG(FATAL) << "failed to create watchdog timer";
-  }
-
-  struct itimerspec its {};
-  its.it_value.tv_sec = kWatchdogTimeoutSec;
-
-  if (timer_settime(timerid, 0, &its, nullptr) == -1) {
-    // This only gets called in the child, so we can fatal without impacting
-    // the app.
-    PLOG(FATAL) << "failed to arm watchdog timer";
-  }
-}
-
-class JavaHprofDataSource : public perfetto::DataSource<JavaHprofDataSource> {
- public:
-  // TODO(fmayer): Change Client API and reject configs that do not target
-  // this process.
-  void OnSetup(const SetupArgs&) override {}
-
-  void OnStart(const StartArgs&) override {
-    art::MutexLock lk(art_thread(), GetStateMutex());
-    if (g_state == State::kWaitForStart) {
-      g_state = State::kStart;
-      GetStateCV().Broadcast(art_thread());
-    }
-  }
-
-  void OnStop(const StopArgs&) override {}
-
-  static art::Thread* art_thread() {
-    // TODO(fmayer): Attach the Perfetto producer thread to ART and give it a name. This is
-    // not trivial, we cannot just attach the first time this method is called, because
-    // AttachCurrentThread deadlocks with the ConditionVariable::Wait in WaitForDataSource.
-    //
-    // We should attach the thread as soon as the Client API spawns it, but that needs more
-    // complicated plumbing.
-    return nullptr;
-  }
-
- private:
-  static art::Thread* self_;
-};
-
-art::Thread* JavaHprofDataSource::self_ = nullptr;
-
-
-void WaitForDataSource(art::Thread* self) {
-  perfetto::TracingInitArgs args;
-  args.backends = perfetto::BackendType::kSystemBackend;
-  perfetto::Tracing::Initialize(args);
-
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("android.java_hprof");
-  JavaHprofDataSource::Register(dsd);
-
-  LOG(INFO) << "waiting for data source";
-
-  art::MutexLock lk(self, GetStateMutex());
-  while (g_state != State::kStart) {
-    GetStateCV().Wait(self);
-  }
-}
-
-class Writer {
- public:
-  Writer(pid_t parent_pid, JavaHprofDataSource::TraceContext* ctx)
-      : parent_pid_(parent_pid), ctx_(ctx) {}
-
-  perfetto::protos::pbzero::HeapGraph* GetHeapGraph() {
-    if (!heap_graph_ || ++objects_written_ % kObjectsPerPacket == 0) {
-      if (heap_graph_) {
-        heap_graph_->set_continued(true);
-      }
-      Finalize();
-
-      trace_packet_ = ctx_->NewTracePacket();
-      heap_graph_ = trace_packet_->set_heap_graph();
-      heap_graph_->set_pid(parent_pid_);
-      heap_graph_->set_index(index_++);
-    }
-    return heap_graph_;
-  }
-
-  void Finalize() {
-    if (trace_packet_) {
-      trace_packet_->Finalize();
-    }
-    heap_graph_ = nullptr;
-  }
-
-  ~Writer() { Finalize(); }
-
- private:
-  const pid_t parent_pid_;
-  JavaHprofDataSource::TraceContext* const ctx_;
-
-  perfetto::DataSource<JavaHprofDataSource>::TraceContext::TracePacketHandle
-      trace_packet_;
-  perfetto::protos::pbzero::HeapGraph* heap_graph_ = nullptr;
-
-  uint64_t index_ = 0;
-  size_t objects_written_ = 0;
-};
-
-class ReferredObjectsFinder {
- public:
-  explicit ReferredObjectsFinder(
-      std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects)
-      REQUIRES_SHARED(art::Locks::mutator_lock_)
-      : referred_objects_(referred_objects) {}
-
-  // For art::mirror::Object::VisitReferences.
-  void operator()(art::ObjPtr<art::mirror::Object> obj, art::MemberOffset offset,
-                  bool is_static) const
-      REQUIRES_SHARED(art::Locks::mutator_lock_) {
-    art::mirror::Object* ref = obj->GetFieldObject<art::mirror::Object>(offset);
-    art::ArtField* field;
-    if (is_static) {
-      field = art::ArtField::FindStaticFieldWithOffset(obj->AsClass(), offset.Uint32Value());
-    } else {
-      field = art::ArtField::FindInstanceFieldWithOffset(obj->GetClass(), offset.Uint32Value());
-    }
-    std::string field_name = "";
-    if (field != nullptr) {
-      field_name = field->PrettyField(/*with_type=*/false);
-    }
-    referred_objects_->emplace_back(std::move(field_name), ref);
-  }
-
-  void VisitRootIfNonNull(art::mirror::CompressedReference<art::mirror::Object>* root
-                              ATTRIBUTE_UNUSED) const {}
-  void VisitRoot(art::mirror::CompressedReference<art::mirror::Object>* root
-                     ATTRIBUTE_UNUSED) const {}
-
- private:
-  // We can use a raw Object* pointer here, because there are no concurrent GC threads after the
-  // fork.
-  std::vector<std::pair<std::string, art::mirror::Object*>>* referred_objects_;
-};
-
-void DumpPerfetto(art::Thread* self) {
-  pid_t parent_pid = getpid();
-  LOG(INFO) << "preparing to dump heap for " << parent_pid;
-
-  // Need to take a heap dump while GC isn't running. See the comment in
-  // Heap::VisitObjects(). Also we need the critical section to avoid visiting
-  // the same object twice. See b/34967844.
-  //
-  // We need to do this before the fork, because otherwise it can deadlock
-  // waiting for the GC, as all other threads get terminated by the clone, but
-  // their locks are not released.
-  art::gc::ScopedGCCriticalSection gcs(self, art::gc::kGcCauseHprof,
-                                       art::gc::kCollectorTypeHprof);
-
-  art::ScopedSuspendAll ssa(__FUNCTION__, /* long_suspend=*/ true);
-
-  pid_t pid = fork();
-  if (pid != 0) {
-    return;
-  }
-
-  // Make sure that this is the first thing we do after forking, so if anything
-  // below hangs, the fork will go away from the watchdog.
-  ArmWatchdogOrDie();
-
-  WaitForDataSource(self);
-
-  JavaHprofDataSource::Trace(
-      [parent_pid](JavaHprofDataSource::TraceContext ctx)
-          NO_THREAD_SAFETY_ANALYSIS {
-            LOG(INFO) << "dumping heap for " << parent_pid;
-            Writer writer(parent_pid, &ctx);
-            // Make sure that intern ID 0 (default proto value for a uint64_t) always maps to ""
-            // (default proto value for a string).
-            std::map<std::string, uint64_t> interned_fields{{"", 0}};
-            std::map<std::string, uint64_t> interned_types{{"", 0}};
-
-            art::Runtime::Current()->GetHeap()->VisitObjectsPaused(
-                [&writer, &interned_types, &interned_fields](
-                    art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
-                  perfetto::protos::pbzero::HeapGraphObject* object_proto =
-                    writer.GetHeapGraph()->add_objects();
-                  object_proto->set_id(reinterpret_cast<uintptr_t>(obj));
-                  object_proto->set_type_id(
-                      FindOrAppend(&interned_types, obj->PrettyTypeOf()));
-                  object_proto->set_self_size(obj->SizeOf());
-
-                  std::vector<std::pair<std::string, art::mirror::Object*>>
-                      referred_objects;
-                  ReferredObjectsFinder objf(&referred_objects);
-                  obj->VisitReferences(objf, art::VoidFunctor());
-                  for (const auto& p : referred_objects) {
-                    object_proto->add_reference_field_id(
-                        FindOrAppend(&interned_fields, p.first));
-                    object_proto->add_reference_object_id(
-                        reinterpret_cast<uintptr_t>(p.second));
-                  }
-                });
-
-            for (const auto& p : interned_fields) {
-              const std::string& str = p.first;
-              uint64_t id = p.second;
-
-              perfetto::protos::pbzero::InternedString* field_proto =
-                writer.GetHeapGraph()->add_field_names();
-              field_proto->set_iid(id);
-              field_proto->set_str(
-                  reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
-            }
-            for (const auto& p : interned_types) {
-              const std::string& str = p.first;
-              uint64_t id = p.second;
-
-              perfetto::protos::pbzero::InternedString* type_proto =
-                writer.GetHeapGraph()->add_type_names();
-              type_proto->set_iid(id);
-              type_proto->set_str(reinterpret_cast<const uint8_t*>(str.c_str()),
-                                  str.size());
-            }
-
-            writer.Finalize();
-
-            ctx.Flush([] {
-              {
-                art::MutexLock lk(JavaHprofDataSource::art_thread(), GetStateMutex());
-                g_state = State::kEnd;
-                GetStateCV().Broadcast(JavaHprofDataSource::art_thread());
-              }
-            });
-          });
-
-  art::MutexLock lk(self, GetStateMutex());
-  while (g_state != State::kEnd) {
-    GetStateCV().Wait(self);
-  }
-  LOG(INFO) << "finished dumping heap for " << parent_pid;
-  // Prevent the atexit handlers to run. We do not want to call cleanup
-  // functions the parent process has registered.
-  _exit(0);
-}
-
-// The plugin initialization function.
-extern "C" bool ArtPlugin_Initialize() {
-  if (art::Runtime::Current() == nullptr) {
-    return false;
-  }
-
-  if (pipe(g_signal_pipe_fds) == -1) {
-    PLOG(ERROR) << "Failed to pipe";
-    return false;
-  }
-
-  struct sigaction act = {};
-  act.sa_sigaction = [](int, siginfo_t*, void*) {
-    if (write(g_signal_pipe_fds[1], kByte, sizeof(kByte)) == -1) {
-      PLOG(ERROR) << "Failed to trigger heap dump";
-    }
-  };
-
-  // TODO(fmayer): We can probably use the SignalCatcher thread here to not
-  // have an idle thread.
-  if (sigaction(kJavaHeapprofdSignal, &act, &g_orig_act) != 0) {
-    close(g_signal_pipe_fds[0]);
-    close(g_signal_pipe_fds[1]);
-    PLOG(ERROR) << "Failed to sigaction";
-    return false;
-  }
-
-  std::thread th([] {
-    art::Runtime* runtime = art::Runtime::Current();
-    if (!runtime->AttachCurrentThread("hprof_listener", /*as_daemon=*/ true,
-                                      runtime->GetSystemThreadGroup(), /*create_peer=*/ false)) {
-      LOG(ERROR) << "failed to attach thread.";
-      return;
-    }
-    art::Thread* self = art::Thread::Current();
-    {
-      art::MutexLock lk(self, GetStateMutex());
-      if (g_state == State::kWaitForListener) {
-        g_state = State::kWaitForStart;
-        GetStateCV().Broadcast(self);
-      }
-    }
-    char buf[1];
-    for (;;) {
-      int res;
-      do {
-        res = read(g_signal_pipe_fds[0], buf, sizeof(buf));
-      } while (res == -1 && errno == EINTR);
-
-      if (res <= 0) {
-        if (res == -1) {
-          PLOG(ERROR) << "failed to read";
-        }
-        close(g_signal_pipe_fds[0]);
-        return;
-      }
-
-      perfetto_hprof::DumpPerfetto(self);
-    }
-  });
-  th.detach();
-
-  art::MutexLock lk(art::Thread::Current(), GetStateMutex());
-  while (g_state == State::kWaitForListener) {
-    GetStateCV().Wait(art::Thread::Current());
-  }
-  return true;
-}
-
-extern "C" bool ArtPlugin_Deinitialize() {
-  if (sigaction(kJavaHeapprofdSignal, &g_orig_act, nullptr) != 0) {
-    PLOG(ERROR) << "failed to reset signal handler";
-    // We cannot close the pipe if the signal handler wasn't unregistered,
-    // to avoid receiving SIGPIPE.
-    return false;
-  }
-  close(g_signal_pipe_fds[1]);
-  return true;
-}
-
-}  // namespace perfetto_hprof
-
-namespace perfetto {
-
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(perfetto_hprof::JavaHprofDataSource);
-
-}
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 156895d..ca331df 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -149,7 +149,6 @@
   HIDDEN_API_ENFORCEMENT_POLICY_MASK = (1 << 12)
                                      | (1 << 13),
   PROFILE_SYSTEM_SERVER              = 1 << 14,
-  PROFILE_FROM_SHELL                 = 1 << 15,
   USE_APP_IMAGE_STARTUP_CACHE        = 1 << 16,
   DEBUG_IGNORE_APP_SIGNAL_HANDLER    = 1 << 17,
 
@@ -242,9 +241,6 @@
     runtime_flags &= ~DEBUG_IGNORE_APP_SIGNAL_HANDLER;
   }
 
-  runtime->SetProfileableFromShell((runtime_flags & PROFILE_FROM_SHELL) != 0);
-  runtime_flags &= ~PROFILE_FROM_SHELL;
-
   return runtime_flags;
 }
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c5d87fc..e7ce33a 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1027,14 +1027,6 @@
   // this to come last.
   ScopedObjectAccess soa(Thread::Current());
   GetRuntimeCallbacks()->StartDebugger();
-
-  if (Dbg::IsJdwpAllowed() || IsProfileableFromShell() || IsJavaDebuggable()) {
-    std::string err;
-    ScopedThreadSuspension sts(Thread::Current(), ThreadState::kNative);
-    if (!EnsurePerfettoPlugin(&err)) {
-      LOG(WARNING) << "Failed to load perfetto_hprof: " << err;
-    }
-  }
 }
 
 void Runtime::StartSignalCatcher() {
@@ -1773,30 +1765,18 @@
   return true;
 }
 
-bool Runtime::EnsurePluginLoaded(const char* plugin_name, std::string* error_msg) {
+static bool EnsureJvmtiPlugin(Runtime* runtime,
+                              std::vector<Plugin>* plugins,
+                              std::string* error_msg) {
+  constexpr const char* plugin_name = kIsDebugBuild ? "libopenjdkjvmtid.so" : "libopenjdkjvmti.so";
+
   // Is the plugin already loaded?
-  for (const Plugin& p : plugins_) {
+  for (const Plugin& p : *plugins) {
     if (p.GetLibrary() == plugin_name) {
       return true;
     }
   }
-  Plugin new_plugin = Plugin::Create(plugin_name);
 
-  if (!new_plugin.Load(error_msg)) {
-    return false;
-  }
-  plugins_.push_back(std::move(new_plugin));
-  return true;
-}
-
-bool Runtime::EnsurePerfettoPlugin(std::string* error_msg) {
-  constexpr const char* plugin_name = kIsDebugBuild ?
-    "libperfetto_hprofd.so" : "libperfetto_hprof.so";
-  return EnsurePluginLoaded(plugin_name, error_msg);
-}
-
-static bool EnsureJvmtiPlugin(Runtime* runtime,
-                              std::string* error_msg) {
   // TODO Rename Dbg::IsJdwpAllowed is IsDebuggingAllowed.
   DCHECK(Dbg::IsJdwpAllowed() || !runtime->IsJavaDebuggable())
       << "Being debuggable requires that jdwp (i.e. debugging) is allowed.";
@@ -1807,8 +1787,14 @@
     return false;
   }
 
-  constexpr const char* plugin_name = kIsDebugBuild ? "libopenjdkjvmtid.so" : "libopenjdkjvmti.so";
-  return runtime->EnsurePluginLoaded(plugin_name, error_msg);
+  Plugin new_plugin = Plugin::Create(plugin_name);
+
+  if (!new_plugin.Load(error_msg)) {
+    return false;
+  }
+
+  plugins->push_back(std::move(new_plugin));
+  return true;
 }
 
 // Attach a new agent and add it to the list of runtime agents
@@ -1819,7 +1805,7 @@
 //
 void Runtime::AttachAgent(JNIEnv* env, const std::string& agent_arg, jobject class_loader) {
   std::string error_msg;
-  if (!EnsureJvmtiPlugin(this, &error_msg)) {
+  if (!EnsureJvmtiPlugin(this, &plugins_, &error_msg)) {
     LOG(WARNING) << "Could not load plugin: " << error_msg;
     ScopedObjectAccess soa(Thread::Current());
     ThrowIOException("%s", error_msg.c_str());
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 120ca66..6735216 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -125,9 +125,6 @@
   static bool Create(const RuntimeOptions& raw_options, bool ignore_unrecognized)
       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
 
-  bool EnsurePluginLoaded(const char* plugin_name, std::string* error_msg);
-  bool EnsurePerfettoPlugin(std::string* error_msg);
-
   // IsAotCompiler for compilers that don't have a running runtime. Only dex2oat currently.
   bool IsAotCompiler() const {
     return !UseJitCompilation() && IsCompiler();
@@ -694,14 +691,6 @@
     return is_java_debuggable_;
   }
 
-  void SetProfileableFromShell(bool value) {
-    is_profileable_from_shell_ = value;
-  }
-
-  bool IsProfileableFromShell() const {
-    return is_profileable_from_shell_;
-  }
-
   void SetJavaDebuggable(bool value);
 
   // Deoptimize the boot image, called for Java debuggable apps.
@@ -1168,8 +1157,6 @@
   // Whether Java code needs to be debuggable.
   bool is_java_debuggable_;
 
-  bool is_profileable_from_shell_ = false;
-
   // The maximum number of failed boots we allow before pruning the dalvik cache
   // and trying again. This option is only inspected when we're running as a
   // zygote.