Merge "Major clean up build files, use flags-per-feature."
diff --git a/Android.bp b/Android.bp
index d9972ad..5202139 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4750,6 +4750,7 @@
     "src/trace_processor/clock_tracker.cc",
     "src/trace_processor/counter_definitions_table.cc",
     "src/trace_processor/counter_values_table.cc",
+    "src/trace_processor/cpu_profile_stack_sample_table.cc",
     "src/trace_processor/db/bit_vector.cc",
     "src/trace_processor/db/column.cc",
     "src/trace_processor/db/row_map.cc",
@@ -4954,6 +4955,7 @@
     "src/trace_processor/clock_tracker.cc",
     "src/trace_processor/counter_definitions_table.cc",
     "src/trace_processor/counter_values_table.cc",
+    "src/trace_processor/cpu_profile_stack_sample_table.cc",
     "src/trace_processor/db/bit_vector.cc",
     "src/trace_processor/db/column.cc",
     "src/trace_processor/db/row_map.cc",
diff --git a/BUILD b/BUILD
index ebc1851..b332ccc 100644
--- a/BUILD
+++ b/BUILD
@@ -314,6 +314,8 @@
         "src/trace_processor/counter_definitions_table.h",
         "src/trace_processor/counter_values_table.cc",
         "src/trace_processor/counter_values_table.h",
+        "src/trace_processor/cpu_profile_stack_sample_table.cc",
+        "src/trace_processor/cpu_profile_stack_sample_table.h",
         "src/trace_processor/db/bit_vector.cc",
         "src/trace_processor/db/bit_vector.h",
         "src/trace_processor/db/column.cc",
@@ -637,6 +639,8 @@
         "src/trace_processor/counter_definitions_table.h",
         "src/trace_processor/counter_values_table.cc",
         "src/trace_processor/counter_values_table.h",
+        "src/trace_processor/cpu_profile_stack_sample_table.cc",
+        "src/trace_processor/cpu_profile_stack_sample_table.h",
         "src/trace_processor/db/bit_vector.cc",
         "src/trace_processor/db/bit_vector.h",
         "src/trace_processor/db/column.cc",
@@ -909,6 +913,8 @@
         "src/trace_processor/counter_definitions_table.h",
         "src/trace_processor/counter_values_table.cc",
         "src/trace_processor/counter_values_table.h",
+        "src/trace_processor/cpu_profile_stack_sample_table.cc",
+        "src/trace_processor/cpu_profile_stack_sample_table.h",
         "src/trace_processor/db/bit_vector.cc",
         "src/trace_processor/db/bit_vector.h",
         "src/trace_processor/db/column.cc",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index aa193a7..7dbb4ac 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -62,6 +62,8 @@
     "counter_definitions_table.h",
     "counter_values_table.cc",
     "counter_values_table.h",
+    "cpu_profile_stack_sample_table.cc",
+    "cpu_profile_stack_sample_table.h",
     "event_tracker.cc",
     "event_tracker.h",
     "filtered_row_index.cc",
@@ -274,6 +276,7 @@
     "../../protos/perfetto/trace/ftrace:zero",
     "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
+    "../../protos/perfetto/trace/profiling:zero",
     "../../protos/perfetto/trace/ps:zero",
     "../../protos/perfetto/trace/sys_stats:zero",
     "../../protos/perfetto/trace/track_event:zero",
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.cc b/src/trace_processor/cpu_profile_stack_sample_table.cc
new file mode 100644
index 0000000..bb51404
--- /dev/null
+++ b/src/trace_processor/cpu_profile_stack_sample_table.cc
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/cpu_profile_stack_sample_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+CpuProfileStackSampleTable::CpuProfileStackSampleTable(
+    sqlite3*,
+    const TraceStorage* storage)
+    : storage_(storage) {}
+
+void CpuProfileStackSampleTable::RegisterTable(sqlite3* db,
+                                               const TraceStorage* storage) {
+  SqliteTable::Register<CpuProfileStackSampleTable>(db, storage,
+                                                    "cpu_profile_stack_sample");
+}
+
+StorageSchema CpuProfileStackSampleTable::CreateStorageSchema() {
+  const auto& allocs = storage_->cpu_profile_stack_samples();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("id", RowAccessor())
+      .AddOrderedNumericColumn("ts", &allocs.timestamps())
+      .AddNumericColumn("callsite_id", &allocs.callsite_ids())
+      .AddNumericColumn("utid", &allocs.utids())
+      .Build({"id"});
+}
+
+uint32_t CpuProfileStackSampleTable::RowCount() {
+  return storage_->cpu_profile_stack_samples().size();
+}
+
+int CpuProfileStackSampleTable::BestIndex(const QueryConstraints& qc,
+                                          BestIndexInfo* info) {
+  info->order_by_consumed = true;
+  info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.h b/src/trace_processor/cpu_profile_stack_sample_table.h
new file mode 100644
index 0000000..e422d75
--- /dev/null
+++ b/src/trace_processor/cpu_profile_stack_sample_table.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
+#define SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class CpuProfileStackSampleTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  CpuProfileStackSampleTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 7da23ca..58de79f 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -427,6 +427,11 @@
   if (packet.has_profile_packet())
     ParseProfilePacket(ts, ttp.packet_sequence_state, packet.profile_packet());
 
+  if (packet.has_streaming_profile_packet()) {
+    ParseStreamingProfilePacket(ttp.packet_sequence_state,
+                                packet.streaming_profile_packet());
+  }
+
   if (packet.has_profiled_frame_symbols())
     ParseProfiledFrameSymbols(ttp.packet_sequence_state,
                               packet.profiled_frame_symbols());
@@ -1500,6 +1505,49 @@
   }
 }
 
+void ProtoTraceParser::ParseStreamingProfilePacket(
+    ProtoIncrementalState::PacketSequenceState* sequence_state,
+    ConstBytes blob) {
+  protos::pbzero::StreamingProfilePacket::Decoder packet(blob.data, blob.size);
+
+  ProcessTracker* procs = context_->process_tracker.get();
+  TraceStorage* storage = context_->storage.get();
+  StackProfileTracker* stack_profile_tracker =
+      context_->stack_profile_tracker.get();
+  ProfilePacketInternLookup intern_lookup(sequence_state, storage);
+
+  uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
+  uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
+  UniqueTid utid = procs->UpdateThread(tid, pid);
+
+  auto timestamp_it = packet.timestamp_delta_us();
+  for (auto callstack_it = packet.callstack_iid(); callstack_it;
+       ++callstack_it, ++timestamp_it) {
+    if (!timestamp_it) {
+      context_->storage->IncrementStats(stats::stackprofile_parser_error);
+      PERFETTO_ELOG(
+          "StreamingProfilePacket has less callstack IDs than timestamps!");
+      break;
+    }
+
+    auto maybe_callstack_id = stack_profile_tracker->FindCallstack(
+        callstack_it->as_uint64(), &intern_lookup);
+    if (!maybe_callstack_id) {
+      context_->storage->IncrementStats(stats::stackprofile_parser_error);
+      PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
+      continue;
+    }
+
+    int64_t callstack_id = *maybe_callstack_id;
+
+    TraceStorage::CpuProfileStackSamples::Row sample_row{
+        sequence_state->IncrementAndGetTrackEventTimeNs(
+            timestamp_it->as_int64()),
+        callstack_id, utid};
+    storage->mutable_cpu_profile_stack_samples()->Insert(sample_row);
+  }
+}
+
 void ProtoTraceParser::ParseProfiledFrameSymbols(
     ProtoIncrementalState::PacketSequenceState* sequence_state,
     ConstBytes blob) {
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index c2fd422..6edccc4 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -97,6 +97,8 @@
   void ParseProfilePacket(int64_t ts,
                           ProtoIncrementalState::PacketSequenceState*,
                           ConstBytes);
+  void ParseStreamingProfilePacket(ProtoIncrementalState::PacketSequenceState*,
+                                   ConstBytes);
   void ParseProfiledFrameSymbols(ProtoIncrementalState::PacketSequenceState*,
                                  ConstBytes);
   void ParseSystemInfo(ConstBytes);
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
index 1b75c5d..4e0589d 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -24,6 +24,7 @@
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/proto_trace_parser.h"
 #include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/stack_profile_tracker.h"
 #include "src/trace_processor/systrace_parser.h"
 #include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/virtual_track_tracker.h"
@@ -41,6 +42,7 @@
 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
 #include "protos/perfetto/trace/ftrace/task.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "protos/perfetto/trace/ps/process_tree.pbzero.h"
 #include "protos/perfetto/trace/sys_stats/sys_stats.pbzero.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
@@ -199,6 +201,7 @@
     context_.sorter.reset(new TraceSorter(&context_, 0 /*window size*/));
     context_.parser.reset(new ProtoTraceParser(&context_));
     context_.systrace_parser.reset(new SystraceParser(&context_));
+    context_.stack_profile_tracker.reset(new StackProfileTracker(&context_));
   }
 
   void ResetTraceBuffers() {
@@ -2066,6 +2069,86 @@
   EXPECT_EQ(find_arg(second_set_id, "version_code").int_value, 43);
 }
 
+TEST_F(ProtoTraceParserTest, ParseCPUProfileSamplesIntoTable) {
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1);
+    thread_desc->set_reference_thread_time_us(2);
+
+    auto* interned_data = packet->set_interned_data();
+
+    auto mapping = interned_data->add_mappings();
+    mapping->set_iid(1);
+
+    auto frame = interned_data->add_frames();
+    frame->set_iid(1);
+    frame->set_rel_pc(0x42);
+    frame->set_mapping_id(1);
+
+    auto frame2 = interned_data->add_frames();
+    frame2->set_iid(2);
+    frame2->set_rel_pc(0x4242);
+    frame2->set_mapping_id(1);
+
+    auto callstack = interned_data->add_callstacks();
+    callstack->set_iid(1);
+    callstack->add_frame_ids(1);
+
+    auto callstack2 = interned_data->add_callstacks();
+    callstack2->set_iid(42);
+    callstack2->add_frame_ids(2);
+  }
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+
+    auto* samples = packet->set_streaming_profile_packet();
+    samples->add_callstack_iid(42);
+    samples->add_timestamp_delta_us(10);
+
+    samples->add_callstack_iid(1);
+    samples->add_timestamp_delta_us(15);
+  }
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* samples = packet->set_streaming_profile_packet();
+
+    samples->add_callstack_iid(42);
+    samples->add_timestamp_delta_us(42);
+  }
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(2)
+      .WillRepeatedly(Return(1));
+
+  Tokenize();
+
+  // Verify cpu_profile_samples.
+  const auto& samples = storage_->cpu_profile_stack_samples();
+  EXPECT_EQ(samples.size(), 3u);
+
+  EXPECT_EQ(samples.timestamps()[0], 1010);
+  EXPECT_EQ(samples.callsite_ids()[0], 0);
+  EXPECT_EQ(samples.utids()[0], 1u);
+
+  EXPECT_EQ(samples.timestamps()[1], 1025);
+  EXPECT_EQ(samples.callsite_ids()[1], 1);
+  EXPECT_EQ(samples.utids()[1], 1u);
+
+  EXPECT_EQ(samples.timestamps()[2], 1067);
+  EXPECT_EQ(samples.callsite_ids()[2], 0);
+  EXPECT_EQ(samples.utids()[2], 1u);
+}
+
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index b9d3fe7..b7bd13e 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -71,6 +71,7 @@
   F(stackprofile_invalid_mapping_id,          kSingle,  kError,    kTrace),    \
   F(stackprofile_invalid_frame_id,            kSingle,  kError,    kTrace),    \
   F(stackprofile_invalid_callstack_id,        kSingle,  kError,    kTrace),    \
+  F(stackprofile_parser_error,                kSingle,  kError,    kTrace),    \
   F(systrace_parse_failure,                   kSingle,  kError,    kAnalysis), \
   F(task_state_invalid,                       kSingle,  kError,    kAnalysis), \
   F(traced_buf_buffer_size,                   kIndexed, kInfo,     kTrace),    \
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 6a3f23b..d370351 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -32,6 +32,7 @@
 #include "src/trace_processor/clock_tracker.h"
 #include "src/trace_processor/counter_definitions_table.h"
 #include "src/trace_processor/counter_values_table.h"
+#include "src/trace_processor/cpu_profile_stack_sample_table.h"
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
 #include "src/trace_processor/heap_profile_allocation_table.h"
@@ -295,6 +296,7 @@
   AndroidLogsTable::RegisterTable(*db_, context_.storage.get());
   RawTable::RegisterTable(*db_, context_.storage.get());
   HeapProfileAllocationTable::RegisterTable(*db_, context_.storage.get());
+  CpuProfileStackSampleTable::RegisterTable(*db_, context_.storage.get());
   StackProfileCallsiteTable::RegisterTable(*db_, context_.storage.get());
   StackProfileFrameTable::RegisterTable(*db_, context_.storage.get());
   StackProfileMappingTable::RegisterTable(*db_, context_.storage.get());
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index dad9744..3854435 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -1100,6 +1100,32 @@
     std::deque<int64_t> sizes_;
   };
 
+  class CpuProfileStackSamples {
+   public:
+    struct Row {
+      int64_t timestamp;
+      int64_t callsite_id;
+      UniqueTid utid;
+    };
+
+    uint32_t size() const { return static_cast<uint32_t>(timestamps_.size()); }
+
+    void Insert(const Row& row) {
+      timestamps_.emplace_back(row.timestamp);
+      callsite_ids_.emplace_back(row.callsite_id);
+      utids_.emplace_back(row.utid);
+    }
+
+    const std::deque<int64_t>& timestamps() const { return timestamps_; }
+    const std::deque<int64_t>& callsite_ids() const { return callsite_ids_; }
+    const std::deque<UniqueTid>& utids() const { return utids_; }
+
+   private:
+    std::deque<int64_t> timestamps_;
+    std::deque<int64_t> callsite_ids_;
+    std::deque<UniqueTid> utids_;
+  };
+
   void ResetStorage();
 
   UniqueTid AddEmptyThread(uint32_t tid) {
@@ -1324,6 +1350,12 @@
   HeapProfileAllocations* mutable_heap_profile_allocations() {
     return &heap_profile_allocations_;
   }
+  const CpuProfileStackSamples& cpu_profile_stack_samples() const {
+    return cpu_profile_stack_samples_;
+  }
+  CpuProfileStackSamples* mutable_cpu_profile_stack_samples() {
+    return &cpu_profile_stack_samples_;
+  }
 
   const GpuTracks& gpu_tracks() const { return gpu_tracks_; }
   GpuTracks* mutable_gpu_tracks() { return &gpu_tracks_; }
@@ -1430,6 +1462,7 @@
   StackProfileFrames stack_profile_frames_;
   StackProfileCallsites stack_profile_callsites_;
   HeapProfileAllocations heap_profile_allocations_;
+  CpuProfileStackSamples cpu_profile_stack_samples_;
 };
 
 }  // namespace trace_processor