Merge "Detect heapprofd with untrustworth self_max_count."
diff --git a/Android.bp b/Android.bp
index 044ca75..eb3d1ef 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7660,6 +7660,7 @@
     "src/trace_processor/dynamic/connected_flow_generator.cc",
     "src/trace_processor/dynamic/descendant_slice_generator.cc",
     "src/trace_processor/dynamic/describe_slice_generator.cc",
+    "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
     "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
     "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
     "src/trace_processor/dynamic/experimental_sched_upid_generator.cc",
diff --git a/BUILD b/BUILD
index b936730..df6e2d4 100644
--- a/BUILD
+++ b/BUILD
@@ -1144,6 +1144,8 @@
         "src/trace_processor/dynamic/descendant_slice_generator.h",
         "src/trace_processor/dynamic/describe_slice_generator.cc",
         "src/trace_processor/dynamic/describe_slice_generator.h",
+        "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
+        "src/trace_processor/dynamic/experimental_annotated_stack_generator.h",
         "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
         "src/trace_processor/dynamic/experimental_counter_dur_generator.h",
         "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index 3e2df10..a59c492 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -1040,8 +1040,10 @@
     "//gn/standalone:visibility_hidden",
   ]
   cflags = [ "-DFAKE_LOG_DEVICE=1" ]
-  configs += [ "//gn/standalone:c++17" ]
-  public_configs = [ ":libunwindstack_config" ]
+  public_configs = [
+    ":libunwindstack_config",
+    "//gn/standalone:c++17",
+  ]
 }
 
 config("bionic_kernel_uapi_headers") {
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index c1ac949..0aff2cd 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -119,7 +119,10 @@
   message Activity {
     optional string name = 1;
     optional string method = 2;
-    optional Slice slice = 3;
+    optional int64 ts_method_start = 4;
+
+    // Field 3 contained Slice with a sum of durations for matching slices.
+    reserved 3;
   }
 
   // Metrics with information about the status of odex files and the outcome
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index a7e2f37..447e81c 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -819,7 +819,10 @@
   message Activity {
     optional string name = 1;
     optional string method = 2;
-    optional Slice slice = 3;
+    optional int64 ts_method_start = 4;
+
+    // Field 3 contained Slice with a sum of durations for matching slices.
+    reserved 3;
   }
 
   // Metrics with information about the status of odex files and the outcome
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index d406ace..97c9876 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -1752,7 +1752,7 @@
 #error "Need to start daemons for Linux test."
 #endif
 
-INSTANTIATE_TEST_CASE_P(Run,
+INSTANTIATE_TEST_CASE_P(DISABLED_Run,
                         HeapprofdEndToEnd,
                         Values(std::make_tuple(TestMode::kStatic,
                                                AllocatorMode::kCustom)),
diff --git a/src/profiling/perf/unwinding.cc b/src/profiling/perf/unwinding.cc
index 533de7d..46dfc6b 100644
--- a/src/profiling/perf/unwinding.cc
+++ b/src/profiling/perf/unwinding.cc
@@ -323,7 +323,7 @@
         : error_code(e), warnings(w), frames(std::move(f)) {}
     UnwindResult(const UnwindResult&) = delete;
     UnwindResult& operator=(const UnwindResult&) = delete;
-    UnwindResult(UnwindResult&&) = default;
+    UnwindResult(UnwindResult&&) __attribute__((unused)) = default;
     UnwindResult& operator=(UnwindResult&&) = default;
   };
   auto attempt_unwind = [&sample, unwind_state, pid_unwound_before,
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index ece05ed..2dba9e1 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -309,6 +309,8 @@
       "dynamic/descendant_slice_generator.h",
       "dynamic/describe_slice_generator.cc",
       "dynamic/describe_slice_generator.h",
+      "dynamic/experimental_annotated_stack_generator.cc",
+      "dynamic/experimental_annotated_stack_generator.h",
       "dynamic/experimental_counter_dur_generator.cc",
       "dynamic/experimental_counter_dur_generator.h",
       "dynamic/experimental_flamegraph_generator.cc",
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
new file mode 100644
index 0000000..1af5ad1
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "src/trace_processor/dynamic/experimental_annotated_stack_generator.h"
+
+#include "perfetto/ext/base/optional.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/profiler_tables.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+#include "perfetto/ext/base/string_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+enum class MapType {
+  kArtInterp,
+  kArtJit,
+  kArtAot,
+  kNativeLibart,
+  kNativeOther,
+  kOther
+};
+
+// Mapping examples:
+//   /system/lib64/libc.so
+//   /system/framework/framework.jar
+//   /memfd:jit-cache (deleted)
+//   [vdso]
+// TODO(rsavitski): consider moving this to a hidden column on
+// stack_profile_mapping, once this logic is sufficiently stable.
+MapType ClassifyMap(NullTermStringView map) {
+  if (map.empty())
+    return MapType::kOther;
+
+  // Primary mapping where modern ART puts jitted code.
+  // TODO(rsavitski): look into /memfd:jit-zygote-cache.
+  if (!strncmp(map.c_str(), "/memfd:jit-cache", 16))
+    return MapType::kArtJit;
+
+  size_t last_slash_pos = map.rfind('/');
+  if (last_slash_pos != NullTermStringView::npos) {
+    if (!strncmp(map.c_str() + last_slash_pos, "/libart.so", 10))
+      return MapType::kNativeLibart;
+    if (!strncmp(map.c_str() + last_slash_pos, "/libartd.so", 11))
+      return MapType::kNativeLibart;
+  }
+
+  size_t extension_pos = map.rfind('.');
+  if (extension_pos != NullTermStringView::npos) {
+    if (!strncmp(map.c_str() + extension_pos, ".so", 3))
+      return MapType::kNativeOther;
+    // dex with verification speedup info, produced by dex2oat
+    if (!strncmp(map.c_str() + extension_pos, ".vdex", 5))
+      return MapType::kArtInterp;
+    // possibly uncompressed dex in a jar archive
+    if (!strncmp(map.c_str() + extension_pos, ".jar", 4))
+      return MapType::kArtInterp;
+    // ahead of time compiled ELFs
+    if (!strncmp(map.c_str() + extension_pos, ".oat", 4))
+      return MapType::kArtAot;
+    // older/alternative name for .oat
+    if (!strncmp(map.c_str() + extension_pos, ".odex", 5))
+      return MapType::kArtAot;
+  }
+  return MapType::kOther;
+}
+
+uint32_t GetConstraintColumnIndex(TraceProcessorContext* context) {
+  // The dynamic table adds two columns on top of the callsite table. Last
+  // column is the hidden constrain (i.e. input arg) column.
+  return context->storage->stack_profile_callsite_table().GetColumnCount() + 1;
+}
+
+}  // namespace
+
+std::string ExperimentalAnnotatedStackGenerator::TableName() {
+  return "experimental_annotated_callstack";
+}
+
+Table::Schema ExperimentalAnnotatedStackGenerator::CreateSchema() {
+  auto schema = tables::StackProfileCallsiteTable::Schema();
+  schema.columns.push_back(Table::Schema::Column{
+      "annotation", SqlValue::Type::kString, /* is_id = */ false,
+      /* is_sorted = */ false, /* is_hidden = */ false});
+  schema.columns.push_back(Table::Schema::Column{
+      "start_id", SqlValue::Type::kLong, /* is_id = */ false,
+      /* is_sorted = */ false, /* is_hidden = */ true});
+  return schema;
+}
+
+util::Status ExperimentalAnnotatedStackGenerator::ValidateConstraints(
+    const QueryConstraints& qc) {
+  const auto& cs = qc.constraints();
+  int column = static_cast<int>(GetConstraintColumnIndex(context_));
+
+  auto id_fn = [column](const QueryConstraints::Constraint& c) {
+    return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+  };
+  bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
+  return has_id_cs ? util::OkStatus()
+                   : util::ErrStatus("Failed to find required constraints");
+}
+
+std::unique_ptr<Table> ExperimentalAnnotatedStackGenerator::ComputeTable(
+    const std::vector<Constraint>& cs,
+    const std::vector<Order>&) {
+  const auto& cs_table = context_->storage->stack_profile_callsite_table();
+  const auto& f_table = context_->storage->stack_profile_frame_table();
+  const auto& m_table = context_->storage->stack_profile_mapping_table();
+
+  // Input (id of the callsite leaf) is the constraint on the hidden |start_id|
+  // column.
+  uint32_t constraint_col = GetConstraintColumnIndex(context_);
+  auto constraint_it =
+      std::find_if(cs.begin(), cs.end(), [constraint_col](const Constraint& c) {
+        return c.col_idx == constraint_col && c.op == FilterOp::kEq;
+      });
+  PERFETTO_DCHECK(constraint_it != cs.end());
+
+  auto start_id = static_cast<uint32_t>(constraint_it->value.AsLong());
+  base::Optional<uint32_t> start_row =
+      cs_table.id().IndexOf(CallsiteId(start_id));
+  if (!start_row)
+    return nullptr;
+
+  // Iteratively walk the parent_id chain to construct the list of callstack
+  // entries, each pointing at a frame.
+  std::vector<uint32_t> cs_rows;
+  cs_rows.push_back(*start_row);
+  base::Optional<CallsiteId> maybe_parent_id = cs_table.parent_id()[*start_row];
+  while (maybe_parent_id) {
+    uint32_t parent_row = cs_table.id().IndexOf(*maybe_parent_id).value();
+    cs_rows.push_back(parent_row);
+    maybe_parent_id = cs_table.parent_id()[parent_row];
+  }
+
+  // Walk the callsites root-to-leaf, annotating:
+  // * managed frames with their execution state (interpreted/jit/aot)
+  // * common ART frames, which are usually not relevant
+  //
+  // This is not a per-frame decision, because we do not want to filter out ART
+  // frames immediately after a JNI transition (such frames are often relevant).
+  //
+  // As a consequence of the logic being based on a root-to-leaf walk, a given
+  // callsite will always have the same annotation, as the parent path is always
+  // the same, and children callsites do not affect their parents' annotations.
+  //
+  // This could also be implemented as a hidden column on the callsite table
+  // (populated at import time), but we want to be more flexible for now.
+  StringId art_jni_trampoline =
+      context_->storage->InternString("art_jni_trampoline");
+
+  StringId common_frame = context_->storage->InternString("common-frame");
+  StringId art_interp = context_->storage->InternString("interp");
+  StringId art_jit = context_->storage->InternString("jit");
+  StringId art_aot = context_->storage->InternString("aot");
+
+  // Annotation FSM states:
+  // * kInitial: default, native-only callstacks never leave this state.
+  // * kEraseLibart: we've seen a managed frame, and will now "erase" (i.e. tag
+  //                 as a common-frame) frames belonging to the ART runtime.
+  // * kKeepNext: we've seen a special JNI trampoline for managed->native
+  //              transition, keep the immediate child (even if it is in ART),
+  //              and then go back to kEraseLibart.
+  // Regardless of the state, managed frames get annotated with their execution
+  // mode, based on the mapping.
+  enum class State { kInitial, kEraseLibart, kKeepNext };
+  State annotation_state = State::kInitial;
+
+  std::vector<StringPool::Id> annotations_reversed;
+  for (auto it = cs_rows.rbegin(); it != cs_rows.rend(); ++it) {
+    FrameId frame_id = cs_table.frame_id()[*it];
+    uint32_t frame_row = f_table.id().IndexOf(frame_id).value();
+
+    MappingId map_id = f_table.mapping()[frame_row];
+    uint32_t map_row = m_table.id().IndexOf(map_id).value();
+
+    // Keep immediate callee of a JNI trampoline, but keep tagging all
+    // successive libart frames as common.
+    if (annotation_state == State::kKeepNext) {
+      annotations_reversed.push_back(kNullStringId);
+      annotation_state = State::kEraseLibart;
+      continue;
+    }
+
+    // Special-case "art_jni_trampoline" frames, keeping their immediate callee
+    // even if it is in libart, as it could be a native implementation of a
+    // managed method. Example for "java.lang.reflect.Method.Invoke":
+    //   art_jni_trampoline
+    //   art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)
+    //
+    // Simpleperf also relies on this frame name, so it should be fairly stable.
+    // TODO(rsavitski): consider detecting standard JNI upcall entrypoints -
+    // _JNIEnv::Call*. These are sometimes inlined into other DSOs, so erasing
+    // only the libart frames does not clean up all of the JNI-related frames.
+    StringId fname_id = f_table.name()[frame_row];
+    if (fname_id == art_jni_trampoline) {
+      annotations_reversed.push_back(common_frame);
+      annotation_state = State::kKeepNext;
+      continue;
+    }
+
+    NullTermStringView map_view =
+        context_->storage->GetString(m_table.name()[map_row]);
+    MapType map_type = ClassifyMap(map_view);
+
+    // Annotate managed frames.
+    if (map_type == MapType::kArtInterp ||  //
+        map_type == MapType::kArtJit ||     //
+        map_type == MapType::kArtAot) {
+      if (map_type == MapType::kArtInterp)
+        annotations_reversed.push_back(art_interp);
+      else if (map_type == MapType::kArtJit)
+        annotations_reversed.push_back(art_jit);
+      else if (map_type == MapType::kArtAot)
+        annotations_reversed.push_back(art_aot);
+
+      // Now know to be in a managed callstack - erase subsequent ART frames.
+      if (annotation_state == State::kInitial)
+        annotation_state = State::kEraseLibart;
+      continue;
+    }
+
+    if (annotation_state == State::kEraseLibart &&
+        map_type == MapType::kNativeLibart) {
+      annotations_reversed.push_back(common_frame);
+      continue;
+    }
+
+    annotations_reversed.push_back(kNullStringId);
+  }
+
+  // Build the dynamic table.
+  auto base_rowmap = RowMap(std::move(cs_rows));
+
+  PERFETTO_DCHECK(base_rowmap.size() == annotations_reversed.size());
+  std::unique_ptr<NullableVector<StringPool::Id>> annotation_vals(
+      new NullableVector<StringPool::Id>());
+  for (auto it = annotations_reversed.rbegin();
+       it != annotations_reversed.rend(); ++it) {
+    annotation_vals->Append(*it);
+  }
+
+  // Hidden column - always the input, i.e. the callsite leaf.
+  std::unique_ptr<NullableVector<uint32_t>> start_id_vals(
+      new NullableVector<uint32_t>());
+  for (uint32_t i = 0; i < base_rowmap.size(); i++)
+    start_id_vals->Append(start_id);
+
+  return std::unique_ptr<Table>(new Table(
+      cs_table.Apply(std::move(base_rowmap))
+          .ExtendWithColumn("annotation", std::move(annotation_vals),
+                            TypedColumn<StringPool::Id>::default_flags())
+          .ExtendWithColumn("start_id", std::move(start_id_vals),
+                            TypedColumn<uint32_t>::default_flags() |
+                                TypedColumn<uint32_t>::kHidden)));
+}
+
+uint32_t ExperimentalAnnotatedStackGenerator::EstimateRowCount() {
+  return 1;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
new file mode 100644
index 0000000..7e6a62d
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
+#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
+
+#include "src/trace_processor/sqlite/db_sqlite_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+// The "experimental_annotated_callstack" dynamic table.
+//
+// Given a leaf callsite id, returns the full callstack (including the leaf),
+// with optional (currently Android-specific) annotations. A given callsite will
+// always have the same annotation.
+class ExperimentalAnnotatedStackGenerator
+    : public DbSqliteTable::DynamicTableGenerator {
+ public:
+  ExperimentalAnnotatedStackGenerator(TraceProcessorContext* context)
+      : context_(context) {}
+
+  Table::Schema CreateSchema() override;
+  std::string TableName() override;
+  uint32_t EstimateRowCount() override;
+  util::Status ValidateConstraints(const QueryConstraints&) override;
+  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
+                                      const std::vector<Order>& ob) override;
+
+ private:
+  TraceProcessorContext* context_ = nullptr;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_ANNOTATED_STACK_GENERATOR_H_
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index 02f1d14..607b2ba 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -55,13 +55,21 @@
                                     uint32_t pid,
                                     int32_t flag,
                                     base::StringView name,
-                                    uint32_t tgid,
+                                    uint32_t /* tgid */,
                                     int64_t value) {
   systrace_utils::SystraceTracePoint point{};
   point.name = name;
-  point.tgid = tgid;
   point.value = static_cast<double>(value);
 
+  // Hardcode the tgid to 0 (i.e. no tgid available) because zero events can
+  // come from kernel threads and as we group kernel threads into the kthreadd
+  // process, we would want |point.tgid == kKthreaddPid|. However, we don't have
+  // acces to the ppid of this process so we have to not associate to any
+  // process and leave the resolution of process to other events.
+  // TODO(lalitm): remove this hack once we move kernel thread grouping to
+  // the UI.
+  point.tgid = 0;
+
   // The value of these constants can be found in the msm-google kernel.
   constexpr int32_t kSystraceEventBegin = 1 << 0;
   constexpr int32_t kSystraceEventEnd = 1 << 1;
diff --git a/src/trace_processor/metrics/android/android_startup.sql b/src/trace_processor/metrics/android/android_startup.sql
index 364a635..27537db 100644
--- a/src/trace_processor/metrics/android/android_startup.sql
+++ b/src/trace_processor/metrics/android/android_startup.sql
@@ -230,13 +230,13 @@
     ),
     'activities', (
       SELECT RepeatedField(AndroidStartupMetric_Activity(
-        'name', (SELECT STR_SPLIT(s.name, ':', 1)),
-        'method', (SELECT STR_SPLIT(s.name, ':', 0)),
-        'slice', s.slice_proto
+        'name', (SELECT STR_SPLIT(s.slice_name, ':', 1)),
+        'method', (SELECT STR_SPLIT(s.slice_name, ':', 0)),
+        'ts_method_start', s.slice_ts
       ))
-      FROM main_process_slice s
+      FROM main_process_slice_unaggregated s
       WHERE s.launch_id = launches.id
-      AND (name LIKE 'performResume:%' OR name LIKE 'performCreate:%')
+      AND (slice_name LIKE 'performResume:%' OR slice_name LIKE 'performCreate:%')
     ),
     'zygote_new_process', EXISTS(SELECT TRUE FROM zygote_forks_by_id WHERE id = launches.id),
     'activity_hosting_process_count', (
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
index 32c8092..a988962 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index ca74685..8893144 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -27,6 +27,7 @@
 #include "src/trace_processor/dynamic/connected_flow_generator.h"
 #include "src/trace_processor/dynamic/descendant_slice_generator.h"
 #include "src/trace_processor/dynamic/describe_slice_generator.h"
+#include "src/trace_processor/dynamic/experimental_annotated_stack_generator.h"
 #include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
 #include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
 #include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
@@ -766,6 +767,8 @@
                                          storage->thread_table())));
   RegisterDynamicTable(std::unique_ptr<ThreadStateGenerator>(
       new ThreadStateGenerator(&context_)));
+  RegisterDynamicTable(std::unique_ptr<ExperimentalAnnotatedStackGenerator>(
+      new ExperimentalAnnotatedStackGenerator(&context_)));
 
   // New style db-backed tables.
   RegisterDbTable(storage->arg_table());
diff --git a/test/trace_processor/dynamic/annotated_callstack.sql b/test/trace_processor/dynamic/annotated_callstack.sql
new file mode 100644
index 0000000..a23f3cc
--- /dev/null
+++ b/test/trace_processor/dynamic/annotated_callstack.sql
@@ -0,0 +1,25 @@
+--
+-- Copyright 2021 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
+--
+--     https://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.
+--
+
+select eac.id, eac.depth, eac.frame_id, eac.annotation,
+       spf.name
+from experimental_annotated_callstack eac
+join perf_sample ps
+  on (eac.start_id == ps.callsite_id)
+join stack_profile_frame spf
+  on (eac.frame_id == spf.id)
+order by eac.start_id asc, eac.depth asc;
+
diff --git a/test/trace_processor/dynamic/index b/test/trace_processor/dynamic/index
index 8e76690..3c5953b 100644
--- a/test/trace_processor/dynamic/index
+++ b/test/trace_processor/dynamic/index
@@ -7,4 +7,7 @@
 relationship_tables.textproto descendant_slice.sql descendant_slice.out
 
 # Connected/Following/Perceeding flow table.
-connected_flow_data.json connected_flow.sql connected_flow.out
\ No newline at end of file
+connected_flow_data.json connected_flow.sql connected_flow.out
+
+# Annotated callstacks.
+../../data/perf_sample_sc.pb annotated_callstack.sql perf_sample_sc_annotated_callstack.out
diff --git a/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out b/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out
new file mode 100644
index 0000000..633c97e
--- /dev/null
+++ b/test/trace_processor/dynamic/perf_sample_sc_annotated_callstack.out
@@ -0,0 +1,96 @@
+"id","depth","frame_id","annotation","name"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
+3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
+4,4,4,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
+5,5,5,"[NULL]","_ZN7android10PoolThread10threadLoopEv"
+6,6,6,"[NULL]","_ZN7android14IPCThreadState14joinThreadPoolEb"
+7,7,7,"[NULL]","_ZN7android14IPCThreadState14executeCommandEi"
+8,8,8,"[NULL]","_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j"
+9,9,9,"[NULL]","_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j"
+10,10,10,"[NULL]","_ZN7_JNIEnv17CallBooleanMethodEP8_jobjectP10_jmethodIDz"
+11,11,11,"[NULL]","_ZN3art3JNIILb0EE18CallBooleanMethodVEP7_JNIEnvP8_jobjectP10_jmethodIDSt9__va_list"
+12,12,12,"[NULL]","_ZN3art35InvokeVirtualOrInterfaceWithVarArgsIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_St9__va_list"
+13,13,13,"[NULL]","art_quick_invoke_stub"
+14,14,14,"aot","android.os.Binder.execTransact"
+15,15,15,"aot","android.os.Binder.execTransactInternal"
+16,16,16,"aot","com.android.server.wm.Session.onTransact"
+17,17,17,"jit","android.view.IWindowSession$Stub.onTransact"
+18,18,18,"aot","com.android.server.wm.Session.sendWallpaperCommand"
+19,19,19,"aot","com.android.server.ThreadPriorityBooster.boost"
+20,20,20,"common-frame","art_jni_trampoline"
+21,21,21,"[NULL]","_Z36android_os_Process_getThreadPriorityP7_JNIEnvP8_jobjecti"
+22,22,22,"[NULL]","getpriority"
+23,23,23,"[NULL]","__getpriority"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
+3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
+24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
+25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+28,8,28,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+29,9,29,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
+30,10,30,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+31,11,31,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+32,12,32,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
+33,13,33,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher29reportTouchEventForStatisticsERKNS0_11MotionEntryE"
+34,14,34,"[NULL]","_ZN7android17LatencyStatistics12shouldReportEv"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
+3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
+4,4,4,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
+35,5,35,"[NULL]","_ZThn32_N7android13SensorService10threadLoopEv"
+36,6,36,"[NULL]","_ZN7android13SensorService10threadLoopEv"
+37,7,37,"[NULL]","_ZN7android12SensorDevice7pollFmqEP15sensors_event_tm"
+38,8,38,"[NULL]","_ZN7android8hardware9EventFlag10waitHelperEjPjl"
+39,9,39,"[NULL]","syscall"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
+3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
+24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
+25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+28,8,28,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+29,9,29,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
+30,10,30,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+31,11,31,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+40,12,40,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
+41,13,41,"[NULL]","_ZN7android15inputdispatcher34verifiedMotionEventFromMotionEntryERKNS0_11MotionEntryE"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+2,2,2,"[NULL]","_ZN13thread_data_t10trampolineEPKS_"
+3,3,3,"[NULL]","_ZN7android14AndroidRuntime15javaThreadShellEPv"
+24,4,24,"[NULL]","_ZN7android6Thread11_threadLoopEPv"
+25,5,25,"[NULL]","_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+26,6,26,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+27,7,27,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+42,8,42,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+43,9,43,"[NULL]","_ZN7android15inputdispatcher15InputDispatcher30findTouchedWindowTargetsLockedElRKNS0_11MotionEntryERNSt3__16vectorINS0_11InputTargetENS5_9allocatorIS7_EEEEPlPb"
+44,10,44,"[NULL]","_ZNK7android15inputdispatcher15InputDispatcher29hasResponsiveConnectionLockedERNS_17InputWindowHandleE"
+45,11,45,"[NULL]","_ZNK7android7RefBase9incStrongEPKv"
+0,0,0,"[NULL]","__start_thread"
+1,1,1,"[NULL]","_ZL15__pthread_startPv"
+46,2,46,"[NULL]","_ZN3art6Thread14CreateCallbackEPv"
+47,3,47,"[NULL]","_ZN3art35InvokeVirtualOrInterfaceWithJValuesIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_PK6jvalue"
+48,4,48,"[NULL]","_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc"
+49,5,13,"[NULL]","art_quick_invoke_stub"
+50,6,49,"aot","com.android.server.UiThread.run"
+51,7,50,"aot","android.os.HandlerThread.run"
+52,8,51,"aot","android.os.Looper.loop"
+53,9,52,"aot","android.os.Looper.loopOnce"
+54,10,53,"aot","android.os.MessageQueue.next"
+55,11,54,"common-frame","art_jni_trampoline"
+56,12,55,"[NULL]","_ZN7androidL38android_os_MessageQueue_nativePollOnceEP7_JNIEnvP8_jobjectli"
+57,13,56,"[NULL]","_ZN7android6Looper8pollOnceEiPiS1_PPv"
+58,14,57,"[NULL]","_ZN7android6Looper9pollInnerEi"
+59,15,58,"[NULL]","_ZN7android24NativeInputEventReceiver11handleEventEiiPv"
+60,16,59,"[NULL]","_ZN7android24NativeInputEventReceiver13consumeEventsEP7_JNIEnvblPb"
+61,17,60,"common-frame","_ZN3art3JNIILb0EE9FindClassEP7_JNIEnvPKc"
+62,18,61,"common-frame","_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE"
+63,19,62,"common-frame",""
diff --git a/test/trace_processor/profiling/index b/test/trace_processor/profiling/index
index 58a7282..60166f5 100644
--- a/test/trace_processor/profiling/index
+++ b/test/trace_processor/profiling/index
@@ -45,8 +45,9 @@
 heap_graph_closest_proc.textproto java_heap_stats heap_stats_closest_proc.out
 heap_graph.textproto java_heap_histogram java_heap_histogram.out
 
-# perf_sample table (traced_perf trace as an input).
-../../data/perf_sample.pb perf_sample.sql perf_sample_perf_sample.out
+# perf_sample table (traced_perf) with android R and S trace inputs.
+../../data/perf_sample.pb perf_sample.sql perf_sample_rvc.out
+../../data/perf_sample_sc.pb perf_sample.sql perf_sample_sc.out
 
 # this uses llvm-symbolizer to test the offline symbolization built into
 # trace_processor_shell.
diff --git a/test/trace_processor/profiling/perf_sample.sql b/test/trace_processor/profiling/perf_sample.sql
index 362f6ff..5c0f1b4 100644
--- a/test/trace_processor/profiling/perf_sample.sql
+++ b/test/trace_processor/profiling/perf_sample.sql
@@ -13,30 +13,19 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
-select perf_sample.ts, thread.tid, perf_sample.cpu, perf_sample.cpu_mode,
-       perf_sample.unwind_error, concatenated_callsite.frames_str
-from perf_sample
+
+select ps.ts, ps.cpu, ps.cpu_mode, ps.unwind_error, ps.perf_session_id,
+       pct.name cntr_name, pct.is_timebase,
+       thread.tid,
+       spf.name
+from experimental_annotated_callstack eac
+join perf_sample ps
+  on (eac.start_id == ps.callsite_id)
+join perf_counter_track pct
+  using(perf_session_id, cpu)
 join thread
   using(utid)
-left join (
-  select flattened_callsite.id, group_concat(spf.name) frames_str
-  from (
-    with recursive rec(id, parent_id, frame_id, depth)
-      as (
-        select id, parent_id, frame_id, depth
-        from stack_profile_callsite
-        union all
-          select rec.id, spc.parent_id, spc.frame_id, spc.depth
-          from stack_profile_callsite spc
-          join rec
-            on spc.id == rec.parent_id
-      )
-    select id, frame_id, depth
-    from rec
-    order by id asc, depth desc
-  ) as flattened_callsite
-  left join stack_profile_frame spf
-    on flattened_callsite.frame_id == spf.id
-  group by flattened_callsite.id
-) as concatenated_callsite
-  on perf_sample.callsite_id == concatenated_callsite.id;
+join stack_profile_frame spf
+  on (eac.frame_id == spf.id)
+order by ps.ts asc, eac.depth asc
+
diff --git a/test/trace_processor/profiling/perf_sample_perf_sample.out b/test/trace_processor/profiling/perf_sample_perf_sample.out
deleted file mode 100644
index 64ae205..0000000
--- a/test/trace_processor/profiling/perf_sample_perf_sample.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"ts","tid","cpu","cpu_mode","unwind_error","frames_str"
-260406202383309,1102,3,"kernel","[NULL]","__ppoll,poll,_ZN8perfetto4base14UnixTaskRunner3RunEv,_ZN8perfetto11ServiceMainEiPPc,__libc_init"
-260406295220349,1102,0,"kernel","[NULL]","__connect,_ZN12_GLOBAL__N_117netdClientConnectEiPK8sockaddrj.cfi,_ZL21HandleProfilingSignaliP7siginfoPv,__kernel_rt_sigreturn,__ppoll,poll,_ZN8perfetto4base14UnixTaskRunner3RunEv,_ZN8perfetto11ServiceMainEiPPc,__libc_init"
-260406802020973,1102,2,"user","[NULL]","_ZN8perfetto3ipc25BufferedFrameDeserializer12BeginReceiveEv,_ZN8perfetto4base10UnixSocket7OnEventEv,_ZN8perfetto4base14UnixTaskRunner22RunFileDescriptorWatchEi,_ZN8perfetto4base14UnixTaskRunner26RunImmediateAndDelayedTaskEv,_ZN8perfetto4base14UnixTaskRunner3RunEv,_ZN8perfetto11ServiceMainEiPPc,__libc_init"
diff --git a/test/trace_processor/profiling/perf_sample_rvc.out b/test/trace_processor/profiling/perf_sample_rvc.out
new file mode 100644
index 0000000..00f7325
--- /dev/null
+++ b/test/trace_processor/profiling/perf_sample_rvc.out
@@ -0,0 +1,22 @@
+"ts","cpu","cpu_mode","unwind_error","perf_session_id","cntr_name","is_timebase","tid","name"
+260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
+260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
+260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
+260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"poll"
+260406202383309,3,"kernel","[NULL]",0,"cpu-clock",1,1102,"__ppoll"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"poll"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__ppoll"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__kernel_rt_sigreturn"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZL21HandleProfilingSignaliP7siginfoPv"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"_ZN12_GLOBAL__N_117netdClientConnectEiPK8sockaddrj.cfi"
+260406295220349,0,"kernel","[NULL]",0,"cpu-clock",1,1102,"__connect"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"__libc_init"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto11ServiceMainEiPPc"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner3RunEv"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner26RunImmediateAndDelayedTaskEv"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base14UnixTaskRunner22RunFileDescriptorWatchEi"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto4base10UnixSocket7OnEventEv"
+260406802020973,2,"user","[NULL]",0,"cpu-clock",1,1102,"_ZN8perfetto3ipc25BufferedFrameDeserializer12BeginReceiveEv"
diff --git a/test/trace_processor/profiling/perf_sample_sc.out b/test/trace_processor/profiling/perf_sample_sc.out
new file mode 100644
index 0000000..4ddbb3a
--- /dev/null
+++ b/test/trace_processor/profiling/perf_sample_sc.out
@@ -0,0 +1,96 @@
+"ts","cpu","cpu_mode","unwind_error","perf_session_id","cntr_name","is_timebase","tid","name"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"__start_thread"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZL15__pthread_startPv"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN13thread_data_t10trampolineEPKS_"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android6Thread11_threadLoopEPv"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android10PoolThread10threadLoopEv"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14IPCThreadState14joinThreadPoolEb"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android14IPCThreadState14executeCommandEi"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN7_JNIEnv17CallBooleanMethodEP8_jobjectP10_jmethodIDz"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN3art3JNIILb0EE18CallBooleanMethodVEP7_JNIEnvP8_jobjectP10_jmethodIDSt9__va_list"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_ZN3art35InvokeVirtualOrInterfaceWithVarArgsIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_St9__va_list"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"art_quick_invoke_stub"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.os.Binder.execTransact"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.os.Binder.execTransactInternal"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.wm.Session.onTransact"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"android.view.IWindowSession$Stub.onTransact"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.wm.Session.sendWallpaperCommand"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"com.android.server.ThreadPriorityBooster.boost"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"art_jni_trampoline"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"_Z36android_os_Process_getThreadPriorityP7_JNIEnvP8_jobjecti"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"getpriority"
+105089621851721,7,"kernel","[NULL]",0,"cpu-clock",1,8817,"__getpriority"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher29reportTouchEventForStatisticsERKNS0_11MotionEntryE"
+105090420158231,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android17LatencyStatistics12shouldReportEv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"__start_thread"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZL15__pthread_startPv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN13thread_data_t10trampolineEPKS_"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android6Thread11_threadLoopEPv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZThn32_N7android13SensorService10threadLoopEv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android13SensorService10threadLoopEv"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android12SensorDevice7pollFmqEP15sensors_event_tm"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"_ZN7android8hardware9EventFlag10waitHelperEjPjl"
+105090420368127,3,"user","[NULL]",0,"cpu-clock",1,2379,"syscall"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher19dispatchEventLockedElNSt3__110shared_ptrINS0_10EventEntryEEERKNS2_6vectorINS0_11InputTargetENS2_9allocatorIS7_EEEE"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher26prepareDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher28enqueueDispatchEntriesLockedElRKNS_2spINS0_10ConnectionEEENSt3__110shared_ptrINS0_10EventEntryEEERKNS0_11InputTargetE"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher24startDispatchCycleLockedElRKNS_2spINS0_10ConnectionEEE"
+105090445130783,1,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher34verifiedMotionEventFromMotionEntryERKNS0_11MotionEntryE"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"__start_thread"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZL15__pthread_startPv"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN13thread_data_t10trampolineEPKS_"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android14AndroidRuntime15javaThreadShellEPv"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android6Thread11_threadLoopEPv"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android12_GLOBAL__N_115InputThreadImpl10threadLoopEv"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher12dispatchOnceEv"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher23dispatchOnceInnerLockedEPl"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher20dispatchMotionLockedElNSt3__110shared_ptrINS0_11MotionEntryEEEPNS1_10DropReasonEPl"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZN7android15inputdispatcher15InputDispatcher30findTouchedWindowTargetsLockedElRKNS0_11MotionEntryERNSt3__16vectorINS0_11InputTargetENS5_9allocatorIS7_EEEEPlPb"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZNK7android15inputdispatcher15InputDispatcher29hasResponsiveConnectionLockedERNS_17InputWindowHandleE"
+105091020156148,2,"user","[NULL]",0,"cpu-clock",1,2395,"_ZNK7android7RefBase9incStrongEPKv"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"__start_thread"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZL15__pthread_startPv"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art6Thread14CreateCallbackEPv"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art35InvokeVirtualOrInterfaceWithJValuesIPNS_9ArtMethodEEENS_6JValueERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectT_PK6jvalue"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"art_quick_invoke_stub"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"com.android.server.UiThread.run"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.HandlerThread.run"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.Looper.loop"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.Looper.loopOnce"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"android.os.MessageQueue.next"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"art_jni_trampoline"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7androidL38android_os_MessageQueue_nativePollOnceEP7_JNIEnvP8_jobjectli"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android6Looper8pollOnceEiPiS1_PPv"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android6Looper9pollInnerEi"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android24NativeInputEventReceiver11handleEventEiiPv"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN7android24NativeInputEventReceiver13consumeEventsEP7_JNIEnvblPb"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art3JNIILb0EE9FindClassEP7_JNIEnvPKc"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,"_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE"
+105091321851304,7,"user","[NULL]",0,"cpu-clock",1,2029,""
diff --git a/test/trace_processor/startup/android_startup_breakdown.out b/test/trace_processor/startup/android_startup_breakdown.out
index 298773d..cebd9d0 100644
--- a/test/trace_processor/startup/android_startup_breakdown.out
+++ b/test/trace_processor/startup/android_startup_breakdown.out
@@ -53,10 +53,7 @@
     activities {
       name: "com.google.android.calendar.MainActivity"
       method: "performCreate"
-      slice {
-        dur_ns: 4000000000
-        dur_ms: 4000
-      }
+      ts_method_start: 188000000000
     }
     optimization_status {
       odex_status: "up-to-date"
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 0714a44..a37d87b 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -232,8 +232,8 @@
     # Example traces for regression tests.
     Dependency(
         'test/data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20210331-182333.zip',
-        'a9b6afb4b33f6aa9dd7ffa0a8c84fb2853c44a10f7f4d918d626f948ef602083',
+        'https://storage.googleapis.com/perfetto/test-data-20210409-215222.zip',
+        'a06fa41e7e334cad89ba0725e0675ee8c4c9dda7b21f327aaaa58ee0ff61687a',
         'all', 'all',
     ),