Add art support for sample profiling from traceview gui.

Change-Id: I6004bf143521b872084ca4aae873bea3524aa895
(cherry picked from commit 23009dca63c1699e28bfeaa8b45ca48fa0e86ace)
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index e3ec3bc..8a8b461 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -37,6 +37,7 @@
   std::vector<std::string> features;
   features.push_back("method-trace-profiling");
   features.push_back("method-trace-profiling-streaming");
+  features.push_back("method-sample-profiling");
   features.push_back("hprof-heap-dump");
   features.push_back("hprof-heap-dump-streaming");
   return toStringArray(env, features);
@@ -58,8 +59,9 @@
   Runtime::Current()->ResetStats(kinds);
 }
 
-static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags) {
-  Trace::Start("[DDMS]", -1, bufferSize, flags, true);
+static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
+                                               jboolean samplingEnabled, jint intervalUs) {
+  Trace::Start("[DDMS]", -1, bufferSize, flags, true, samplingEnabled, intervalUs);
 }
 
 static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -82,7 +84,7 @@
   if (traceFilename.c_str() == NULL) {
     return;
   }
-  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false);
+  Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, false, false, 0);
 }
 
 static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring javaTraceFilename,
@@ -91,7 +93,7 @@
   if (traceFilename.c_str() == NULL) {
     return;
   }
-  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false);
+  Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, false, false, 0);
 }
 
 static jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
@@ -322,7 +324,7 @@
   NATIVE_METHOD(VMDebug, startAllocCounting, "()V"),
   NATIVE_METHOD(VMDebug, startEmulatorTracing, "()V"),
   NATIVE_METHOD(VMDebug, startInstructionCounting, "()V"),
-  NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(II)V"),
+  NATIVE_METHOD(VMDebug, startMethodTracingDdmsImpl, "(IIZI)V"),
   NATIVE_METHOD(VMDebug, startMethodTracingFd, "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V"),
   NATIVE_METHOD(VMDebug, startMethodTracingFilename, "(Ljava/lang/String;II)V"),
   NATIVE_METHOD(VMDebug, stopAllocCounting, "()V"),
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 51a67c1..5679d4e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -925,7 +925,8 @@
   method_trace_file_size_ = options->method_trace_file_size_;
 
   if (options->method_trace_) {
-    Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0, false);
+    Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0,
+                 false, false, 0);
   }
 
   VLOG(startup) << "Runtime::Init exiting";
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 4c092fd..6d040e1 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -122,9 +122,6 @@
 #endif
 
 Trace* volatile Trace::the_trace_ = NULL;
-// TODO: Add way to enable sampling and set interval through gui.
-bool Trace::sampling_enabled_ = true;
-uint32_t Trace::sampling_interval_us_ = 1000;
 pthread_t Trace::sampling_pthread_ = 0U;
 UniquePtr<std::vector<mirror::ArtMethod*> > Trace::temp_stack_trace_;
 
@@ -301,11 +298,12 @@
 
 void* Trace::RunSamplingThread(void* arg) {
   Runtime* runtime = Runtime::Current();
+  int interval_us = reinterpret_cast<int>(arg);
   CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
                                      !runtime->IsCompiler()));
 
   while (true) {
-    usleep(sampling_interval_us_);
+    usleep(interval_us);
     ATRACE_BEGIN("Profile sampling");
     Thread* self = Thread::Current();
     Trace* the_trace;
@@ -331,7 +329,7 @@
 }
 
 void Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
-                  bool direct_to_ddms) {
+                  bool direct_to_ddms, bool sampling_enabled, int interval_us) {
   Thread* self = Thread::Current();
   {
     MutexLock mu(self, *Locks::trace_lock_);
@@ -367,16 +365,19 @@
     if (the_trace_ != NULL) {
       LOG(ERROR) << "Trace already in progress, ignoring this request";
     } else {
-      the_trace_ = new Trace(trace_file.release(), buffer_size, flags);
+      the_trace_ = new Trace(trace_file.release(), buffer_size, flags, sampling_enabled);
 
       // Enable count of allocs if specified in the flags.
       if ((flags && kTraceCountAllocs) != 0) {
         runtime->SetStatsEnabled(true);
       }
 
-      if (sampling_enabled_) {
-        CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread, NULL),
-                           "Sampling profiler thread");
+
+
+      if (sampling_enabled) {
+        CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread,
+                                            reinterpret_cast<void*>(interval_us)),
+                                            "Sampling profiler thread");
       } else {
         runtime->GetInstrumentation()->AddListener(the_trace_,
                                                    instrumentation::Instrumentation::kMethodEntered |
@@ -407,7 +408,7 @@
   if (the_trace != NULL) {
     the_trace->FinishTracing();
 
-    if (sampling_enabled_) {
+    if (the_trace->sampling_enabled_) {
       MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
       runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, NULL);
     } else {
@@ -420,7 +421,7 @@
   }
   runtime->GetThreadList()->ResumeAll();
 
-  if (sampling_enabled_ && sampling_pthread != 0U) {
+  if (sampling_pthread != 0U) {
     CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown");
   }
 }
@@ -436,10 +437,10 @@
   return the_trace_ != NULL;
 }
 
-Trace::Trace(File* trace_file, int buffer_size, int flags)
+Trace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled)
     : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
-      clock_source_(default_clock_source_), buffer_size_(buffer_size), start_time_(MicroTime()),
-      cur_offset_(0),  overflow_(false) {
+      sampling_enabled_(sampling_enabled), clock_source_(default_clock_source_),
+      buffer_size_(buffer_size), start_time_(MicroTime()), cur_offset_(0),  overflow_(false) {
   // Set up the beginning of the trace.
   uint16_t trace_version = GetTraceVersion(clock_source_);
   memset(buf_.get(), 0, kTraceHeaderLength);
@@ -456,10 +457,6 @@
   cur_offset_ = kTraceHeaderLength;
 }
 
-Trace::~Trace() {
-  CHECK_EQ(sampling_pthread_, static_cast<pthread_t>(0U));
-}
-
 static void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   uint8_t* ptr = buf + kTraceHeaderLength;
diff --git a/runtime/trace.h b/runtime/trace.h
index 6fc3790..06cb6a6 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -51,7 +51,7 @@
   static void SetDefaultClockSource(ProfilerClockSource clock_source);
 
   static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
-                    bool direct_to_ddms)
+                    bool direct_to_ddms, bool sampling_enabled, int interval_us)
   LOCKS_EXCLUDED(Locks::mutator_lock_,
                  Locks::thread_list_lock_,
                  Locks::thread_suspend_count_lock_,
@@ -88,11 +88,10 @@
   // Clear and store an old stack trace for later use.
   static void FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace);
 
-  ~Trace();
-
  private:
-  explicit Trace(File* trace_file, int buffer_size, int flags);
+  explicit Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled);
 
+  // The sampling interval in microseconds is passed as an argument.
   static void* RunSamplingThread(void* arg) LOCKS_EXCLUDED(Locks::trace_lock_);
 
   void FinishTracing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -115,12 +114,6 @@
   // The default profiler clock source.
   static ProfilerClockSource default_clock_source_;
 
-  // True if traceview should sample instead of instrumenting method entry/exit.
-  static bool sampling_enabled_;
-
-  // Sampling interval in microseconds.
-  static uint32_t sampling_interval_us_;
-
   // Sampling thread, non-zero when sampling.
   static pthread_t sampling_pthread_;
 
@@ -136,6 +129,9 @@
   // Flags enabling extra tracing of things such as alloc counts.
   const int flags_;
 
+  // True if traceview should sample instead of instrumenting method entry/exit.
+  const bool sampling_enabled_;
+
   const ProfilerClockSource clock_source_;
 
   // Size of buf_.