Merge "TrackEvent: Start using boot time where available"
diff --git a/Android.bp b/Android.bp
index 7b79c00..40089cd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,6 +23,7 @@
     "src/trace_processor/metrics/android/android_cpu_agg.sql",
     "src/trace_processor/metrics/android/android_ion.sql",
     "src/trace_processor/metrics/android/android_lmk.sql",
+    "src/trace_processor/metrics/android/android_lmk_reason.sql",
     "src/trace_processor/metrics/android/android_mem.sql",
     "src/trace_processor/metrics/android/android_mem_unagg.sql",
     "src/trace_processor/metrics/android/android_package_list.sql",
@@ -2385,6 +2386,7 @@
     "protos/perfetto/metrics/android/ion_metric.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
+    "protos/perfetto/metrics/android/lmk_reason_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
     "protos/perfetto/metrics/android/package_list.proto",
@@ -2405,6 +2407,7 @@
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/lmk_reason_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.cc",
@@ -2425,6 +2428,7 @@
     "protos/perfetto/metrics/android/ion_metric.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
+    "protos/perfetto/metrics/android/lmk_reason_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
     "protos/perfetto/metrics/android/package_list.proto",
@@ -2445,6 +2449,7 @@
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/lmk_reason_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.h",
@@ -3829,6 +3834,7 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
   srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3843,6 +3849,7 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
   out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
@@ -3858,6 +3865,7 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
   srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3872,6 +3880,7 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
   out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
@@ -3891,6 +3900,7 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen",
   srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3906,6 +3916,7 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
@@ -3921,6 +3932,7 @@
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
   srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3936,6 +3948,7 @@
   ],
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
@@ -5793,7 +5806,12 @@
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
     "-DHAVE_HIDDEN",
   ],
-  static_executable: true,
+  dist: {
+    targets: [
+      "sdk_repo",
+    ],
+  },
+  stl: "libc++_static",
 }
 
 // GN: //tools/trace_to_text:trace_to_text
diff --git a/BUILD b/BUILD
index f1dc21a..3b97386 100644
--- a/BUILD
+++ b/BUILD
@@ -586,6 +586,7 @@
         "src/trace_processor/metrics/android/android_cpu_agg.sql",
         "src/trace_processor/metrics/android/android_ion.sql",
         "src/trace_processor/metrics/android/android_lmk.sql",
+        "src/trace_processor/metrics/android/android_lmk_reason.sql",
         "src/trace_processor/metrics/android/android_mem.sql",
         "src/trace_processor/metrics/android/android_mem_unagg.sql",
         "src/trace_processor/metrics/android/android_package_list.sql",
@@ -1690,6 +1691,7 @@
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/java_heap_stats.proto",
         "protos/perfetto/metrics/android/lmk_metric.proto",
+        "protos/perfetto/metrics/android/lmk_reason_metric.proto",
         "protos/perfetto/metrics/android/mem_metric.proto",
         "protos/perfetto/metrics/android/mem_unagg_metric.proto",
         "protos/perfetto/metrics/android/package_list.proto",
@@ -2259,6 +2261,7 @@
 perfetto_proto_library(
     name = "protos_perfetto_trace_track_event_protos",
     srcs = [
+        "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 4f38ceb..417d7f4 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -83,7 +83,7 @@
     target_triplet = "arm-linux-androideabi"
   } else if (target_os == "android" && target_cpu == "x86") {
     target_triplet = "i686-linux-android"
-  } else if (target_os == "android" && target_cpu == "x86_64") {
+  } else if (target_os == "android" && target_cpu == "x64") {
     target_triplet = "x86_64-linux-android"
   } else {
     assert(false,
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 3e3c9fa..1debee3 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -25,6 +25,7 @@
 #include "perfetto/tracing/track_event_category_registry.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
 
+#include <type_traits>
 #include <unordered_map>
 
 namespace perfetto {
@@ -41,6 +42,16 @@
   }
 };
 
+// A helper that ensures movable debug annotations are passed by value to
+// minimize binary size at the call site, while allowing non-movable and
+// non-copiable arguments to be passed by reference.
+// TODO(skyostil): Remove this with C++17.
+template <typename T>
+struct DebugAnnotationArg {
+  using type = typename std::
+      conditional<std::is_move_constructible<T>::value, T, T&&>::type;
+};
+
 // A generic track event data source which is instantiated once per track event
 // category namespace.
 template <typename DataSourceType, const TrackEventCategoryRegistry* Registry>
@@ -97,12 +108,35 @@
   }
 
   // Trace point with one debug annotation.
+  //
+  // This type of trace point is implemented with an inner helper function which
+  // ensures |arg_value| is only passed by reference when required (i.e., with a
+  // custom DebugAnnotation type). This avoids the binary and runtime overhead
+  // of unnecessarily passing all types debug annotations by reference.
+  //
+  // Note that for this to work well, the _outer_ function (this function) has
+  // to be inlined at the call site while the _inner_ function
+  // (TraceForCategoryWithDebugAnnotations) is still outlined to minimize
+  // overall binary size.
   template <size_t CategoryIndex, typename ArgType>
   static void TraceForCategory(uint32_t instances,
                                const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                const char* arg_name,
-                               ArgType arg_value) PERFETTO_NO_INLINE {
+                               ArgType&& arg_value) PERFETTO_ALWAYS_INLINE {
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, ArgType>(
+        instances, event_name, type, arg_name,
+        std::forward<ArgType>(arg_value));
+  }
+
+  template <size_t CategoryIndex, typename ArgType>
+  static void TraceForCategoryWithDebugAnnotations(
+      uint32_t instances,
+      const char* event_name,
+      perfetto::protos::pbzero::TrackEvent::Type type,
+      const char* arg_name,
+      typename internal::DebugAnnotationArg<ArgType>::type arg_value)
+      PERFETTO_NO_INLINE {
     Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
         instances, [&](typename Base::TraceContext ctx) {
           // TODO(skyostil): Intern categories at compile time.
@@ -110,7 +144,7 @@
               ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
               Registry->GetCategory(CategoryIndex)->name, event_name, type);
           TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
-                                                 std::move(arg_value));
+                                                 arg_value);
         });
   }
 
@@ -123,9 +157,24 @@
                                const char* event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                const char* arg_name,
-                               ArgType arg_value,
+                               ArgType&& arg_value,
                                const char* arg_name2,
-                               ArgType2 arg_value2) PERFETTO_NO_INLINE {
+                               ArgType2&& arg_value2) PERFETTO_ALWAYS_INLINE {
+    TraceForCategoryWithDebugAnnotations<CategoryIndex, ArgType, ArgType2>(
+        instances, event_name, type, arg_name, std::forward<ArgType>(arg_value),
+        arg_name2, std::forward<ArgType2>(arg_value2));
+  }
+
+  template <size_t CategoryIndex, typename ArgType, typename ArgType2>
+  static void TraceForCategoryWithDebugAnnotations(
+      uint32_t instances,
+      const char* event_name,
+      perfetto::protos::pbzero::TrackEvent::Type type,
+      const char* arg_name,
+      typename internal::DebugAnnotationArg<ArgType>::type arg_value,
+      const char* arg_name2,
+      typename internal::DebugAnnotationArg<ArgType2>::type arg_value2)
+      PERFETTO_NO_INLINE {
     Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
         instances, [&](typename Base::TraceContext ctx) {
           // TODO(skyostil): Intern categories at compile time.
@@ -133,9 +182,9 @@
               ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
               Registry->GetCategory(CategoryIndex)->name, event_name, type);
           TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
-                                                 std::move(arg_value));
+                                                 arg_value);
           TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name2,
-                                                 std::move(arg_value2));
+                                                 arg_value2);
         });
   }
 
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 2a68702..e37a30b 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -96,7 +96,7 @@
   template <typename T>
   static void AddDebugAnnotation(perfetto::EventContext* event_ctx,
                                  const char* name,
-                                 T value) {
+                                 T&& value) {
     auto annotation = AddDebugAnnotation(event_ctx, name);
     WriteDebugAnnotation(annotation, value);
   }
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index fca7deb..f291186 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -102,4 +102,24 @@
 #define PERFETTO_INTERNAL_CONCAT(a, b) PERFETTO_INTERNAL_CONCAT2(a, b)
 #define PERFETTO_INTERNAL_UID(prefix) PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
 
+#define PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ...)             \
+  struct {                                                                    \
+    struct EventFinalizer {                                                   \
+      /* The int parameter is an implementation detail. It allows the      */ \
+      /* anonymous struct to use aggregate initialization to invoke the    */ \
+      /* lambda (which emits the BEGIN event and returns an integer)       */ \
+      /* with the proper reference capture for any                         */ \
+      /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so  */ \
+      /* that the scoped event is exactly ONE line and can't escape the    */ \
+      /* scope if used in a single line if statement.                      */ \
+      EventFinalizer(int) {}                                                  \
+      ~EventFinalizer() { TRACE_EVENT_END(category); }                        \
+    } finalizer;                                                              \
+  } PERFETTO_INTERNAL_UID(scoped_event) {                                     \
+    [&]() {                                                                   \
+      TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__);                       \
+      return 0;                                                               \
+    }()                                                                       \
+  }
+
 #endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 371346b..245b31d 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -154,13 +154,8 @@
 
 // Begin a thread-scoped slice which gets automatically closed when going out of
 // scope.
-#define TRACE_EVENT(category, name, ...)               \
-  TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__);    \
-  struct {                                             \
-    struct EventFinalizer {                            \
-      ~EventFinalizer() { TRACE_EVENT_END(category); } \
-    } finalizer;                                       \
-  } PERFETTO_INTERNAL_UID(scoped_event)
+#define TRACE_EVENT(category, name, ...) \
+  PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
 
 // Emit a thread-scoped slice which has zero duration.
 // TODO(skyostil): Add support for process-wide and global instant events.
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 3f8571c..05f5b80 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -22,6 +22,7 @@
     "ion_metric.proto",
     "java_heap_stats.proto",
     "lmk_metric.proto",
+    "lmk_reason_metric.proto",
     "mem_metric.proto",
     "mem_unagg_metric.proto",
     "package_list.proto",
diff --git a/protos/perfetto/metrics/android/lmk_reason_metric.proto b/protos/perfetto/metrics/android/lmk_reason_metric.proto
new file mode 100644
index 0000000..6b84b0d
--- /dev/null
+++ b/protos/perfetto/metrics/android/lmk_reason_metric.proto
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Potential culplit of a low-memory kill on Android.
+message AndroidLmkReasonMetric {
+  message Lmk {
+    // OOM score adj of the LMK'ed process.
+    optional int32 oom_score_adj = 1;
+  }
+
+  repeated Lmk lmks = 1;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 6225559..bcb5e93 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -25,6 +25,7 @@
 import "protos/perfetto/metrics/android/mem_unagg_metric.proto";
 import "protos/perfetto/metrics/android/ion_metric.proto";
 import "protos/perfetto/metrics/android/lmk_metric.proto";
+import "protos/perfetto/metrics/android/lmk_reason_metric.proto";
 import "protos/perfetto/metrics/android/powrails_metric.proto";
 import "protos/perfetto/metrics/android/startup_metric.proto";
 import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
@@ -32,8 +33,7 @@
 import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
 import "protos/perfetto/metrics/android/java_heap_stats.proto";
 
-// Trace processor metadata (taken from the stats table schema and contents).
-// TODO: perhaps add the other columns once we have enum support
+// Trace processor metadata
 message TraceMetadata {
   message Entry {
     optional string name = 1;
@@ -44,11 +44,13 @@
   repeated Entry error_stats_entry = 1;
   optional int64 trace_duration_ns = 2;
   optional string trace_uuid = 3;
+  optional string android_build_fingerprint = 4;
+  optional int64 statsd_triggering_subscription_id = 5;
 }
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 18
+// Next id: 19
 message TraceMetrics {
   reserved 4, 10, 13, 14;
 
@@ -94,6 +96,9 @@
   // If the trace contains a heap graph, output allocation statistics.
   optional JavaHeapStats java_heap_stats = 17;
 
+  // Metrics used to find potential culprits of low-memory kills.
+  optional AndroidLmkReasonMetric android_lmk_reason = 18;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 7684649..478cc2d 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3737,6 +3737,239 @@
 }
 // End of protos/perfetto/trace/trace_packet_defaults.proto
 
+// Begin of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
+
+// Describes Chrome's Compositor scheduler's current state and associated
+// variables.
+//
+// These protos and enums were adapted from the corresponding original JSON
+// trace event for the scheduler state. In contrast to the JSON, we use strongly
+// typed enum values instead of strings for many fields, and
+// microsecond-granularity timestamps.
+//
+// The original format was generated in JSON by the code at
+// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?l=870&rcl=5e15eabc9c0eec8daf94fdf78e93f13b6e3b63dd
+//
+// TODO(nuskos): Update link once we've switched to writing this proto.
+//
+// All non-delta-timestamps are absolute CLOCK_MONOTONIC timestamps.
+
+enum ChromeCompositorSchedulerAction {
+  CC_SCHEDULER_ACTION_NONE = 0;
+  CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME = 1;
+  CC_SCHEDULER_ACTION_COMMIT = 2;
+  CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE = 3;
+  CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE = 4;
+  CC_SCHEDULER_ACTION_DRAW_FORCED = 5;
+  CC_SCHEDULER_ACTION_DRAW_ABORT = 6;
+  CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION = 7;
+  CC_SCHEDULER_ACTION_PREPARE_TILES = 8;
+  CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK = 9;
+  CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION = 10;
+  CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL = 11;
+  CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON = 12;
+}
+
+// Next id: 18
+message ChromeCompositorSchedulerState {
+  enum BeginImplFrameDeadlineMode {
+    DEADLINE_MODE_NONE = 0;
+    DEADLINE_MODE_IMMEDIATE = 1;
+    DEADLINE_MODE_REGULAR = 2;
+    DEADLINE_MODE_LATE = 3;
+    DEADLINE_MODE_BLOCKED = 4;
+  }
+  optional ChromeCompositorStateMachine state_machine = 1;
+  optional bool observing_begin_frame_source = 2;
+  optional bool begin_impl_frame_deadline_task = 3;
+  optional bool pending_begin_frame_task = 4;
+  optional bool skipped_last_frame_missed_exceeded_deadline = 5;
+  optional bool skipped_last_frame_to_reduce_latency = 6;
+  optional ChromeCompositorSchedulerAction inside_action = 7;
+  optional BeginImplFrameDeadlineMode deadline_mode = 8;
+  optional int64 deadline_us = 9;
+  optional int64 deadline_scheduled_at_us = 10;
+  optional int64 now_us = 11;
+  optional int64 now_to_deadline_delta_us = 12;
+  optional int64 now_to_deadline_scheduled_at_delta_us = 13;
+  optional BeginImplFrameArgs begin_impl_frame_args = 14;
+  optional BeginFrameObserverState begin_frame_observer_state = 15;
+  optional BeginFrameSourceState begin_frame_source_state = 16;
+  optional CompositorTimingHistory compositor_timing_history = 17;
+}
+
+// Describes the current values stored in the Chrome Compositor state machine.
+// Next id: 3
+message ChromeCompositorStateMachine {
+  // Next id: 6
+  message MajorState {
+    enum BeginImplFrameState {
+      BEGIN_FRAME_IDLE = 0;
+      BEGIN_FRAME_INSIDE_BEGIN_FRAME = 1;
+      BEGIN_FRAME_INSIDE_DEADLINE = 2;
+    }
+    enum LayerTreeFrameSinkState {
+      LAYER_TREE_FRAME_NONE = 0;
+      LAYER_TREE_FRAME_ACTIVE = 1;
+      LAYER_TREE_FRAME_CREATING = 2;
+      LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = 3;
+      LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = 4;
+    }
+    enum ForcedRedrawOnTimeoutState {
+      FORCED_REDRAW_IDLE = 0;
+      FORCED_REDRAW_WAITING_FOR_COMMIT = 1;
+      FORCED_REDRAW_WAITING_FOR_ACTIVATION = 2;
+      FORCED_REDRAW_WAITING_FOR_DRAW = 3;
+    }
+    optional ChromeCompositorSchedulerAction next_action = 1;
+    optional BeginImplFrameState begin_impl_frame_state = 2;
+    optional BeginImplFrameState begin_main_frame_state = 3;
+    optional LayerTreeFrameSinkState layer_tree_frame_sink_state = 4;
+    optional ForcedRedrawOnTimeoutState forced_redraw_state = 5;
+  }
+  optional MajorState major_state = 1;
+
+  // Next id: 47
+  message MinorState {
+    enum TreePriority {
+      TREE_PRIORITY_UNKNOWN = 0;
+      TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = 1;
+      TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = 2;
+      TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = 3;
+    }
+    enum ScrollHandlerState {
+      SCROLL_AFFECTS_SCROLL_HANDLER = 0;
+      SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = 1;
+    }
+    optional int32 commit_count = 1;
+    optional int32 current_frame_number = 2;
+    optional int32 last_frame_number_submit_performed = 3;
+    optional int32 last_frame_number_draw_performed = 4;
+    optional int32 last_frame_number_begin_main_frame_sent = 5;
+    optional bool did_draw = 6;
+    optional bool did_send_begin_main_frame_for_current_frame = 7;
+    optional bool did_notify_begin_main_frame_not_expected_until = 8;
+    optional bool did_notify_begin_main_frame_not_expected_soon = 9;
+    optional bool wants_begin_main_frame_not_expected = 10;
+    optional bool did_commit_during_frame = 11;
+    optional bool did_invalidate_layer_tree_frame_sink = 12;
+    optional bool did_perform_impl_side_invalidaion = 13;
+    optional bool did_prepare_tiles = 14;
+    optional int32 consecutive_checkerboard_animations = 15;
+    optional int32 pending_submit_frames = 16;
+    optional int32 submit_frames_with_current_layer_tree_frame_sink = 17;
+    optional bool needs_redraw = 18;
+    optional bool needs_prepare_tiles = 19;
+    optional bool needs_begin_main_frame = 20;
+    optional bool needs_one_begin_impl_frame = 21;
+    optional bool visible = 22;
+    optional bool begin_frame_source_paused = 23;
+    optional bool can_draw = 24;
+    optional bool resourceless_draw = 25;
+    optional bool has_pending_tree = 26;
+    optional bool pending_tree_is_ready_for_activation = 27;
+    optional bool active_tree_needs_first_draw = 28;
+    optional bool active_tree_is_ready_to_draw = 29;
+    optional bool did_create_and_initialize_first_layer_tree_frame_sink = 30;
+    optional TreePriority tree_priority = 31;
+    optional ScrollHandlerState scroll_handler_state = 32;
+    optional bool critical_begin_main_frame_to_activate_is_fast = 33;
+    optional bool main_thread_missed_last_deadline = 34;
+    optional bool skip_next_begin_main_frame_to_reduce_latency = 35;
+    optional bool video_needs_begin_frames = 36;
+    optional bool defer_begin_main_frame = 37;
+    optional bool last_commit_had_no_updates = 38;
+    optional bool did_draw_in_last_frame = 39;
+    optional bool did_submit_in_last_frame = 40;
+    optional bool needs_impl_side_invalidation = 41;
+    optional bool current_pending_tree_is_impl_side = 42;
+    optional bool previous_pending_tree_was_impl_side = 43;
+    optional bool processing_animation_worklets_for_active_tree = 44;
+    optional bool processing_animation_worklets_for_pending_tree = 45;
+    optional bool processing_paint_worklets_for_pending_tree = 46;
+  }
+  optional MinorState minor_state = 2;
+}
+
+// Next id: 12
+message BeginFrameArgs {
+  // JSON format has a "type" field that was always just "BeginFrameArgs" we
+  // drop this in the proto representation, and instead make the JSON format
+  // "subtype" field become the type field.
+  enum BeginFrameArgsType {
+    BEGIN_FRAME_ARGS_TYPE_INVALID = 0;
+    BEGIN_FRAME_ARGS_TYPE_NORMAL = 1;
+    BEGIN_FRAME_ARGS_TYPE_MISSED = 2;
+  }
+  optional BeginFrameArgsType type = 1;
+  optional uint64 source_id = 2;
+  optional uint64 sequence_number = 3;
+  optional int64 frame_time_us = 4;
+  optional int64 deadline_us = 5;
+  optional int64 interval_delta_us = 6;
+  optional bool on_critical_path = 7;
+  optional bool animate_only = 8;
+  oneof created_from {
+    // The interned SourceLocation.
+    uint64 source_location_iid = 9;
+    // The SourceLocation that this args was created from.
+    // TODO(nuskos): Eventually we will support interning inside of
+    // TypedArgument TraceEvents and then we shouldn't need this SourceLocation
+    // since we can emit it as part of the InternedData message. When we can
+    // remove this |source_location|.
+    SourceLocation source_location = 10;
+  }
+}
+
+// Next id: 7
+message BeginImplFrameArgs {
+  optional int64 updated_at_us = 1;
+  optional int64 finished_at_us = 2;
+  enum State {
+    BEGIN_FRAME_FINISHED = 0;
+    BEGIN_FRAME_USING = 1;
+  }
+  optional State state = 3;
+  oneof args {
+    // Only set if |state| is BEGIN_FRAME_FINISHED.
+    BeginFrameArgs current_args = 4;
+    // Only set if |state| is BEGIN_FRAME_USING.
+    BeginFrameArgs last_args = 5;
+  }
+  message TimestampsInUs {
+    optional int64 interval_delta = 1;
+    optional int64 now_to_deadline_delta = 2;
+    optional int64 frame_time_to_now_delta = 3;
+    optional int64 frame_time_to_deadline_delta = 4;
+    optional int64 now = 5;
+    optional int64 frame_time = 6;
+    optional int64 deadline = 7;
+  }
+  optional TimestampsInUs timestamps_in_us = 6;
+}
+
+message BeginFrameObserverState {
+  optional int64 dropped_begin_frame_args = 1;
+  optional BeginFrameArgs last_begin_frame_args = 2;
+}
+
+message BeginFrameSourceState {
+  optional uint32 source_id = 1;
+}
+
+message CompositorTimingHistory {
+  optional int64 begin_main_frame_queue_critical_estimate_delta_us = 1;
+  optional int64 begin_main_frame_queue_not_critical_estimate_delta_us = 2;
+  optional int64 begin_main_frame_start_to_ready_to_commit_estimate_delta_us =
+      3;
+  optional int64 commit_to_ready_to_activate_estimate_delta_us = 4;
+  optional int64 prepare_tiles_estimate_delta_us = 5;
+  optional int64 activate_estimate_delta_us = 6;
+  optional int64 draw_estimate_delta_us = 7;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
+
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
@@ -4029,7 +4262,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 24.
+// Next reserved id: 12 (up to 15). Next id: 25.
 message TrackEvent {
   // Names of categories of the event. In the client library, categories are a
   // way to turn groups of individual events on or off.
@@ -4124,6 +4357,7 @@
   // Typed event arguments:
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
+  optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index 929d51c..afb3630 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -16,6 +16,7 @@
 
 perfetto_proto_library("@TYPE@") {
   sources = [
+    "chrome_compositor_scheduler_state.proto",
     "debug_annotation.proto",
     "log_message.proto",
     "process_descriptor.proto",
diff --git a/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
new file mode 100644
index 0000000..838c61c
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+import "protos/perfetto/trace/track_event/source_location.proto";
+
+package perfetto.protos;
+
+// Describes Chrome's Compositor scheduler's current state and associated
+// variables.
+//
+// These protos and enums were adapted from the corresponding original JSON
+// trace event for the scheduler state. In contrast to the JSON, we use strongly
+// typed enum values instead of strings for many fields, and
+// microsecond-granularity timestamps.
+//
+// The original format was generated in JSON by the code at
+// https://cs.chromium.org/chromium/src/cc/scheduler/scheduler.cc?l=870&rcl=5e15eabc9c0eec8daf94fdf78e93f13b6e3b63dd
+//
+// TODO(nuskos): Update link once we've switched to writing this proto.
+//
+// All non-delta-timestamps are absolute CLOCK_MONOTONIC timestamps.
+
+enum ChromeCompositorSchedulerAction {
+  CC_SCHEDULER_ACTION_NONE = 0;
+  CC_SCHEDULER_ACTION_SEND_BEGIN_MAIN_FRAME = 1;
+  CC_SCHEDULER_ACTION_COMMIT = 2;
+  CC_SCHEDULER_ACTION_ACTIVATE_SYNC_TREE = 3;
+  CC_SCHEDULER_ACTION_DRAW_IF_POSSIBLE = 4;
+  CC_SCHEDULER_ACTION_DRAW_FORCED = 5;
+  CC_SCHEDULER_ACTION_DRAW_ABORT = 6;
+  CC_SCHEDULER_ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION = 7;
+  CC_SCHEDULER_ACTION_PREPARE_TILES = 8;
+  CC_SCHEDULER_ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK = 9;
+  CC_SCHEDULER_ACTION_PERFORM_IMPL_SIDE_INVALIDATION = 10;
+  CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL = 11;
+  CC_SCHEDULER_ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON = 12;
+}
+
+// Next id: 18
+message ChromeCompositorSchedulerState {
+  enum BeginImplFrameDeadlineMode {
+    DEADLINE_MODE_NONE = 0;
+    DEADLINE_MODE_IMMEDIATE = 1;
+    DEADLINE_MODE_REGULAR = 2;
+    DEADLINE_MODE_LATE = 3;
+    DEADLINE_MODE_BLOCKED = 4;
+  }
+  optional ChromeCompositorStateMachine state_machine = 1;
+  optional bool observing_begin_frame_source = 2;
+  optional bool begin_impl_frame_deadline_task = 3;
+  optional bool pending_begin_frame_task = 4;
+  optional bool skipped_last_frame_missed_exceeded_deadline = 5;
+  optional bool skipped_last_frame_to_reduce_latency = 6;
+  optional ChromeCompositorSchedulerAction inside_action = 7;
+  optional BeginImplFrameDeadlineMode deadline_mode = 8;
+  optional int64 deadline_us = 9;
+  optional int64 deadline_scheduled_at_us = 10;
+  optional int64 now_us = 11;
+  optional int64 now_to_deadline_delta_us = 12;
+  optional int64 now_to_deadline_scheduled_at_delta_us = 13;
+  optional BeginImplFrameArgs begin_impl_frame_args = 14;
+  optional BeginFrameObserverState begin_frame_observer_state = 15;
+  optional BeginFrameSourceState begin_frame_source_state = 16;
+  optional CompositorTimingHistory compositor_timing_history = 17;
+}
+
+// Describes the current values stored in the Chrome Compositor state machine.
+// Next id: 3
+message ChromeCompositorStateMachine {
+  // Next id: 6
+  message MajorState {
+    enum BeginImplFrameState {
+      BEGIN_FRAME_IDLE = 0;
+      BEGIN_FRAME_INSIDE_BEGIN_FRAME = 1;
+      BEGIN_FRAME_INSIDE_DEADLINE = 2;
+    }
+    enum LayerTreeFrameSinkState {
+      LAYER_TREE_FRAME_NONE = 0;
+      LAYER_TREE_FRAME_ACTIVE = 1;
+      LAYER_TREE_FRAME_CREATING = 2;
+      LAYER_TREE_FRAME_WAITING_FOR_FIRST_COMMIT = 3;
+      LAYER_TREE_FRAME_WAITING_FOR_FIRST_ACTIVATION = 4;
+    }
+    enum ForcedRedrawOnTimeoutState {
+      FORCED_REDRAW_IDLE = 0;
+      FORCED_REDRAW_WAITING_FOR_COMMIT = 1;
+      FORCED_REDRAW_WAITING_FOR_ACTIVATION = 2;
+      FORCED_REDRAW_WAITING_FOR_DRAW = 3;
+    }
+    optional ChromeCompositorSchedulerAction next_action = 1;
+    optional BeginImplFrameState begin_impl_frame_state = 2;
+    optional BeginImplFrameState begin_main_frame_state = 3;
+    optional LayerTreeFrameSinkState layer_tree_frame_sink_state = 4;
+    optional ForcedRedrawOnTimeoutState forced_redraw_state = 5;
+  }
+  optional MajorState major_state = 1;
+
+  // Next id: 47
+  message MinorState {
+    enum TreePriority {
+      TREE_PRIORITY_UNKNOWN = 0;
+      TREE_PRIORITY_SAME_PRIORITY_FOR_BOTH_TREES = 1;
+      TREE_PRIORITY_SMOOTHNESS_TAKES_PRIORITY = 2;
+      TREE_PRIORITY_NEW_CONTENT_TAKES_PRIORITY = 3;
+    }
+    enum ScrollHandlerState {
+      SCROLL_AFFECTS_SCROLL_HANDLER = 0;
+      SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER = 1;
+    }
+    optional int32 commit_count = 1;
+    optional int32 current_frame_number = 2;
+    optional int32 last_frame_number_submit_performed = 3;
+    optional int32 last_frame_number_draw_performed = 4;
+    optional int32 last_frame_number_begin_main_frame_sent = 5;
+    optional bool did_draw = 6;
+    optional bool did_send_begin_main_frame_for_current_frame = 7;
+    optional bool did_notify_begin_main_frame_not_expected_until = 8;
+    optional bool did_notify_begin_main_frame_not_expected_soon = 9;
+    optional bool wants_begin_main_frame_not_expected = 10;
+    optional bool did_commit_during_frame = 11;
+    optional bool did_invalidate_layer_tree_frame_sink = 12;
+    optional bool did_perform_impl_side_invalidaion = 13;
+    optional bool did_prepare_tiles = 14;
+    optional int32 consecutive_checkerboard_animations = 15;
+    optional int32 pending_submit_frames = 16;
+    optional int32 submit_frames_with_current_layer_tree_frame_sink = 17;
+    optional bool needs_redraw = 18;
+    optional bool needs_prepare_tiles = 19;
+    optional bool needs_begin_main_frame = 20;
+    optional bool needs_one_begin_impl_frame = 21;
+    optional bool visible = 22;
+    optional bool begin_frame_source_paused = 23;
+    optional bool can_draw = 24;
+    optional bool resourceless_draw = 25;
+    optional bool has_pending_tree = 26;
+    optional bool pending_tree_is_ready_for_activation = 27;
+    optional bool active_tree_needs_first_draw = 28;
+    optional bool active_tree_is_ready_to_draw = 29;
+    optional bool did_create_and_initialize_first_layer_tree_frame_sink = 30;
+    optional TreePriority tree_priority = 31;
+    optional ScrollHandlerState scroll_handler_state = 32;
+    optional bool critical_begin_main_frame_to_activate_is_fast = 33;
+    optional bool main_thread_missed_last_deadline = 34;
+    optional bool skip_next_begin_main_frame_to_reduce_latency = 35;
+    optional bool video_needs_begin_frames = 36;
+    optional bool defer_begin_main_frame = 37;
+    optional bool last_commit_had_no_updates = 38;
+    optional bool did_draw_in_last_frame = 39;
+    optional bool did_submit_in_last_frame = 40;
+    optional bool needs_impl_side_invalidation = 41;
+    optional bool current_pending_tree_is_impl_side = 42;
+    optional bool previous_pending_tree_was_impl_side = 43;
+    optional bool processing_animation_worklets_for_active_tree = 44;
+    optional bool processing_animation_worklets_for_pending_tree = 45;
+    optional bool processing_paint_worklets_for_pending_tree = 46;
+  }
+  optional MinorState minor_state = 2;
+}
+
+// Next id: 12
+message BeginFrameArgs {
+  // JSON format has a "type" field that was always just "BeginFrameArgs" we
+  // drop this in the proto representation, and instead make the JSON format
+  // "subtype" field become the type field.
+  enum BeginFrameArgsType {
+    BEGIN_FRAME_ARGS_TYPE_INVALID = 0;
+    BEGIN_FRAME_ARGS_TYPE_NORMAL = 1;
+    BEGIN_FRAME_ARGS_TYPE_MISSED = 2;
+  }
+  optional BeginFrameArgsType type = 1;
+  optional uint64 source_id = 2;
+  optional uint64 sequence_number = 3;
+  optional int64 frame_time_us = 4;
+  optional int64 deadline_us = 5;
+  optional int64 interval_delta_us = 6;
+  optional bool on_critical_path = 7;
+  optional bool animate_only = 8;
+  oneof created_from {
+    // The interned SourceLocation.
+    uint64 source_location_iid = 9;
+    // The SourceLocation that this args was created from.
+    // TODO(nuskos): Eventually we will support interning inside of
+    // TypedArgument TraceEvents and then we shouldn't need this SourceLocation
+    // since we can emit it as part of the InternedData message. When we can
+    // remove this |source_location|.
+    SourceLocation source_location = 10;
+  }
+}
+
+// Next id: 7
+message BeginImplFrameArgs {
+  optional int64 updated_at_us = 1;
+  optional int64 finished_at_us = 2;
+  enum State {
+    BEGIN_FRAME_FINISHED = 0;
+    BEGIN_FRAME_USING = 1;
+  }
+  optional State state = 3;
+  oneof args {
+    // Only set if |state| is BEGIN_FRAME_FINISHED.
+    BeginFrameArgs current_args = 4;
+    // Only set if |state| is BEGIN_FRAME_USING.
+    BeginFrameArgs last_args = 5;
+  }
+  message TimestampsInUs {
+    optional int64 interval_delta = 1;
+    optional int64 now_to_deadline_delta = 2;
+    optional int64 frame_time_to_now_delta = 3;
+    optional int64 frame_time_to_deadline_delta = 4;
+    optional int64 now = 5;
+    optional int64 frame_time = 6;
+    optional int64 deadline = 7;
+  }
+  optional TimestampsInUs timestamps_in_us = 6;
+}
+
+message BeginFrameObserverState {
+  optional int64 dropped_begin_frame_args = 1;
+  optional BeginFrameArgs last_begin_frame_args = 2;
+}
+
+message BeginFrameSourceState {
+  optional uint32 source_id = 1;
+}
+
+message CompositorTimingHistory {
+  optional int64 begin_main_frame_queue_critical_estimate_delta_us = 1;
+  optional int64 begin_main_frame_queue_not_critical_estimate_delta_us = 2;
+  optional int64 begin_main_frame_start_to_ready_to_commit_estimate_delta_us =
+      3;
+  optional int64 commit_to_ready_to_activate_estimate_delta_us = 4;
+  optional int64 prepare_tiles_estimate_delta_us = 5;
+  optional int64 activate_estimate_delta_us = 6;
+  optional int64 draw_estimate_delta_us = 7;
+}
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index c5bd588..b4a20cc 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -20,6 +20,7 @@
 import "protos/perfetto/trace/track_event/debug_annotation.proto";
 import "protos/perfetto/trace/track_event/log_message.proto";
 import "protos/perfetto/trace/track_event/task_execution.proto";
+import "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto";
 
 package perfetto.protos;
 
@@ -82,7 +83,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 24.
+// Next reserved id: 12 (up to 15). Next id: 25.
 message TrackEvent {
   // Names of categories of the event. In the client library, categories are a
   // way to turn groups of individual events on or off.
@@ -177,6 +178,7 @@
   // Typed event arguments:
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
+  optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 7efcc6e..8fb1281 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -316,6 +316,13 @@
     context_->storage->SetMetadata(metadata::system_machine,
                                    Variadic::String(machine_id));
   }
+
+  if (packet.has_android_build_fingerprint()) {
+    context_->storage->SetMetadata(
+        metadata::android_build_fingerprint,
+        Variadic::String(context_->storage->InternString(
+            packet.android_build_fingerprint())));
+  }
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/metadata.h b/src/trace_processor/metadata.h
index 7faa8bc..8965052 100644
--- a/src/trace_processor/metadata.h
+++ b/src/trace_processor/metadata.h
@@ -44,7 +44,8 @@
   F(system_name,                         kSingle,  Variadic::kString), \
   F(system_version,                      kSingle,  Variadic::kString), \
   F(system_release,                      kSingle,  Variadic::kString), \
-  F(system_machine,                      kSingle,  Variadic::kString)
+  F(system_machine,                      kSingle,  Variadic::kString), \
+  F(android_build_fingerprint,           kSingle,  Variadic::kString)
 // clang-format on
 
 enum KeyType {
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 2c3416b..82ae165 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -23,6 +23,7 @@
   "android/android_mem.sql",
   "android/android_mem_unagg.sql",
   "android/android_ion.sql",
+  "android/android_lmk_reason.sql",
   "android/android_lmk.sql",
   "android/android_powrails.sql",
   "android/android_startup_launches.sql",
diff --git a/src/trace_processor/metrics/android/android_lmk.sql b/src/trace_processor/metrics/android/android_lmk.sql
index 7ddd2ea..8b96ab7 100644
--- a/src/trace_processor/metrics/android/android_lmk.sql
+++ b/src/trace_processor/metrics/android/android_lmk.sql
@@ -17,13 +17,13 @@
 SELECT RUN_METRIC('android/process_oom_score.sql');
 
 -- Create all the views used to for LMK related stuff.
-CREATE TABLE lmk_events AS
+CREATE TABLE IF NOT EXISTS lmk_events AS
 SELECT ref AS upid, MIN(ts) AS ts
 FROM instants
 WHERE name = 'mem.lmk' AND ref_type = 'upid'
 GROUP BY 1;
 
-CREATE VIEW lmk_by_score AS
+CREATE VIEW IF NOT EXISTS lmk_by_score AS
 SELECT lmk_events.upid, oom_scores.oom_score_val AS score
 FROM lmk_events
 LEFT JOIN oom_score_span oom_scores
@@ -32,12 +32,12 @@
       lmk_events.ts < oom_scores.ts + oom_scores.dur)
 ORDER BY lmk_events.upid;
 
-CREATE VIEW lmk_counts AS
+CREATE VIEW IF NOT EXISTS lmk_counts AS
 SELECT score, COUNT(1) AS count
 FROM lmk_by_score
 GROUP BY score;
 
-CREATE VIEW android_lmk_output AS
+CREATE VIEW IF NOT EXISTS android_lmk_output AS
 SELECT AndroidLmkMetric(
   'total_count', (SELECT COUNT(1) FROM lmk_events),
   'by_oom_score', (
diff --git a/src/trace_processor/metrics/android/android_lmk_reason.sql b/src/trace_processor/metrics/android/android_lmk_reason.sql
new file mode 100644
index 0000000..8a91000
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_lmk_reason.sql
@@ -0,0 +1,39 @@
+--
+-- Copyright 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
+--
+--     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 RUN_METRIC('android/android_lmk.sql');
+
+CREATE VIEW IF NOT EXISTS android_lmk_reason_output AS
+WITH
+lmk_ooms AS (
+  SELECT
+  lmk_events.ts,
+  oom_score_val
+  FROM lmk_events
+  LEFT JOIN oom_score_span USING (upid)
+  WHERE oom_score_span.ts <= lmk_events.ts
+  AND (oom_score_span.ts + oom_score_span.dur) > lmk_events.ts
+)
+SELECT AndroidLmkReasonMetric(
+  'lmks', (
+    SELECT RepeatedField(AndroidLmkReasonMetric_Lmk(
+      'oom_score_adj', oom_score_val
+    ))
+    FROM lmk_events
+    JOIN lmk_ooms USING (ts)
+    ORDER BY ts
+  )
+);
diff --git a/src/trace_processor/metrics/android/process_oom_score.sql b/src/trace_processor/metrics/android/process_oom_score.sql
index ee9a64f..00812d4 100644
--- a/src/trace_processor/metrics/android/process_oom_score.sql
+++ b/src/trace_processor/metrics/android/process_oom_score.sql
@@ -15,9 +15,7 @@
 --
 
 -- Create a track for process OOM scores.
-DROP VIEW IF EXISTS oom_score_span;
-
-CREATE VIEW oom_score_span AS
+CREATE VIEW IF NOT EXISTS oom_score_span AS
 SELECT
   ts,
   LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index e811f69..3022438 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -12,14 +12,14 @@
 // SHA1(tools/gen_binary_descriptors)
 // 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// fb0504ef20a790f031fc622ba1b9312cb97d67a6
+// e1fea13f5853cbb276ae800c5fee91c46704565d
 
 // This is the proto Metrics encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 10136> kMetricsDescriptor{
+constexpr std::array<uint8_t, 10631> kMetricsDescriptor{
     {0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
      0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
@@ -311,7 +311,25 @@
      0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63,
      0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
      0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf4, 0x02, 0x0a,
+     0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd5, 0x01, 0x0a,
+     0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
+     0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x22, 0x84, 0x01, 0x0a, 0x16, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x12, 0x3f, 0x0a, 0x04, 0x6c, 0x6d, 0x6b, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52,
+     0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x4c, 0x6d, 0x6b, 0x52, 0x04, 0x6c, 0x6d, 0x6b, 0x73, 0x1a, 0x29, 0x0a,
+     0x03, 0x4c, 0x6d, 0x6b, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f,
+     0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72,
+     0x65, 0x41, 0x64, 0x6a, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf4, 0x02, 0x0a,
      0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
      0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77,
@@ -696,7 +714,7 @@
      0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61,
      0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61,
      0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
-     0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xe0, 0x0f, 0x0a, 0x25, 0x70, 0x72,
+     0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf7, 0x11, 0x0a, 0x25, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65,
      0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
@@ -727,55 +745,71 @@
      0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
      0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d,
      0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77,
-     0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65,
-     0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63,
-     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
+     0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69,
+     0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f,
+     0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c,
+     0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63,
+     0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65,
+     0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
      0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
-     0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65,
-     0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72,
-     0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e,
-     0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
-     0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
-     0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x45,
-     0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e,
-     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61,
-     0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73,
-     0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x75,
-     0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72,
-     0x61, 0x63, 0x65, 0x55, 0x75, 0x69, 0x64, 0x1a, 0x43, 0x0a, 0x05, 0x45,
+     0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74,
+     0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8, 0x02,
+     0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64,
+     0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+     0x74, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72,
+     0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72,
+     0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64,
+     0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44,
+     0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a,
+     0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x55, 0x75, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x19, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x69,
+     0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x17, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x42, 0x75, 0x69, 0x6c, 0x64, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70,
+     0x72, 0x69, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x21, 0x73, 0x74, 0x61, 0x74,
+     0x73, 0x64, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x1e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x54, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a, 0x43, 0x0a, 0x05, 0x45,
      0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
      0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
      0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
      0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
      0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76,
-     0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x08, 0x0a, 0x0c, 0x54, 0x72, 0x61,
+     0x61, 0x6c, 0x75, 0x65, 0x22, 0x80, 0x09, 0x0a, 0x0c, 0x54, 0x72, 0x61,
      0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a,
      0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74,
      0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65,
@@ -861,10 +895,17 @@
      0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61,
      0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x6a,
      0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06, 0x08, 0xf4,
-     0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04,
-     0x08, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04,
-     0x08, 0x0e, 0x10, 0x0f, 0x42, 0x02, 0x48, 0x03}};
+     0x12, 0x55, 0x0a, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+     0x6c, 0x6d, 0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x12,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61,
+     0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x10, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61,
+     0x73, 0x6f, 0x6e, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a,
+     0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10,
+     0x05, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0d, 0x10,
+     0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x42, 0x02, 0x48, 0x03}};
 
 }  // namespace perfetto
 
diff --git a/src/trace_processor/metrics/trace_metadata.sql b/src/trace_processor/metrics/trace_metadata.sql
index 11524ac..78259ea 100644
--- a/src/trace_processor/metrics/trace_metadata.sql
+++ b/src/trace_processor/metrics/trace_metadata.sql
@@ -27,5 +27,12 @@
 SELECT TraceMetadata(
   'error_stats_entry', (SELECT RepeatedField(entry) FROM error_stats_view),
   'trace_duration_ns', (SELECT end_ts - start_ts FROM trace_bounds),
-  'trace_uuid', (SELECT str_value FROM metadata WHERE name = 'trace_uuid')
+  'trace_uuid', (SELECT str_value FROM metadata WHERE name = 'trace_uuid'),
+  'android_build_fingerprint', (
+    SELECT str_value FROM metadata WHERE name = 'android_build_fingerprint'
+  ),
+  'statsd_triggering_subscription_id', (
+    SELECT int_value FROM metadata
+    WHERE name = 'statsd_triggering_subscription_id'
+  )
 );
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 59f927f..4ad454f 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -190,10 +190,13 @@
 
   // Setup the variables for estimating the number of rows we will have at the
   // end of filtering. Note that |current_row_count| should always be at least 1
-  // as otherwise SQLite can make some bad choices.
+  // unless we are absolutely certain that we will return no rows as otherwise
+  // SQLite can make some bad choices.
   uint32_t current_row_count = table.size();
 
-  // If the table is empty, any constraint set only pays the fixed cost.
+  // If the table is empty, any constraint set only pays the fixed cost. Also we
+  // can return 0 as the row count as we are certain that we will return no
+  // rows.
   if (current_row_count == 0)
     return QueryCost{kFixedQueryCost, 0};
 
@@ -201,6 +204,8 @@
   double filter_cost = 0.0;
   const auto& cs = qc.constraints();
   for (const auto& c : cs) {
+    if (current_row_count < 2)
+      break;
     const auto& col = table.GetColumn(static_cast<uint32_t>(c.column));
     if (sqlite_utils::IsOpEq(c.op) && col.IsId()) {
       // If we have an id equality constraint, it's a bit expensive to find
diff --git a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
index 1228c28..d88a046 100644
--- a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
@@ -31,73 +31,102 @@
     columns_.emplace_back(Column::IdColumn(this, 0u, 0u));
     columns_.emplace_back(
         Column("a", &a_, Column::Flag::kNoFlag, this, 1u, 0u));
+    columns_.emplace_back(
+        Column("sorted", &sorted_, Column::Flag::kSorted, this, 2u, 0u));
   }
 
  private:
   StringPool pool_;
   SparseVector<uint32_t> a_;
+  SparseVector<uint32_t> sorted_;
 };
 
-TEST(DbSqliteTableTest, EstimateCostEmpty) {
+TEST(DbSqliteTable, IdEqCheaperThanOtherEq) {
+  TestTable table(1234);
+
+  QueryConstraints id_eq;
+  id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+  auto id_cost = DbSqliteTable::EstimateCost(table, id_eq);
+
+  QueryConstraints a_eq;
+  a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
+
+  auto a_cost = DbSqliteTable::EstimateCost(table, a_eq);
+
+  ASSERT_LT(id_cost.cost, a_cost.cost);
+  ASSERT_LT(id_cost.rows, a_cost.rows);
+}
+
+TEST(DbSqliteTable, IdEqCheaperThatOtherConstraint) {
+  TestTable table(1234);
+
+  QueryConstraints id_eq;
+  id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+  auto id_cost = DbSqliteTable::EstimateCost(table, id_eq);
+
+  QueryConstraints a_eq;
+  a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
+
+  auto a_cost = DbSqliteTable::EstimateCost(table, a_eq);
+
+  ASSERT_LT(id_cost.cost, a_cost.cost);
+  ASSERT_LT(id_cost.rows, a_cost.rows);
+}
+
+TEST(DbSqliteTable, SingleEqCheaperThanMultipleConstraint) {
+  TestTable table(1234);
+
+  QueryConstraints single_eq;
+  single_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+  auto single_cost = DbSqliteTable::EstimateCost(table, single_eq);
+
+  QueryConstraints multi_eq;
+  multi_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+  multi_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
+
+  auto multi_cost = DbSqliteTable::EstimateCost(table, multi_eq);
+
+  // The cost of the single filter should be cheaper (because of our special
+  // handling of single equality). But the number of rows should be greater.
+  ASSERT_LT(single_cost.cost, multi_cost.cost);
+  ASSERT_GT(single_cost.rows, multi_cost.rows);
+}
+
+TEST(DbSqliteTable, EmptyTableCosting) {
   TestTable table(0u);
 
-  auto cost = DbSqliteTable::EstimateCost(table, QueryConstraints());
-  ASSERT_EQ(cost.rows, 0u);
+  QueryConstraints id_eq;
+  id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
 
-  // The cost should be 1000 (fixed cost).
-  ASSERT_DOUBLE_EQ(cost.cost, 1000.0);
+  auto id_cost = DbSqliteTable::EstimateCost(table, id_eq);
+
+  QueryConstraints a_eq;
+  a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
+
+  auto a_cost = DbSqliteTable::EstimateCost(table, a_eq);
+
+  ASSERT_DOUBLE_EQ(id_cost.cost, a_cost.cost);
+  ASSERT_EQ(id_cost.rows, a_cost.rows);
 }
 
-TEST(DbSqliteTableTest, EstimateCostSmoke) {
-  TestTable table(1234u);
+TEST(DbSqliteTable, OrderByOnSortedCheaper) {
+  TestTable table(1234);
 
-  auto cost = DbSqliteTable::EstimateCost(table, QueryConstraints());
-  ASSERT_EQ(cost.rows, 1234u);
+  QueryConstraints a_qc;
+  a_qc.AddOrderBy(1u, false);
 
-  // The cost should be 1000 (fixed cost) + 2468 (iteration cost).
-  ASSERT_DOUBLE_EQ(cost.cost, 3468);
-}
+  auto a_cost = DbSqliteTable::EstimateCost(table, a_qc);
 
-TEST(DbSqliteTableTest, EstimateCostFilterId) {
-  TestTable table(1234u);
+  // On an ordered column, the constraint for sorting would get pruned so
+  // we would end up with an empty constraint set.
+  QueryConstraints sorted_qc;
+  auto sorted_cost = DbSqliteTable::EstimateCost(table, sorted_qc);
 
-  QueryConstraints qc;
-  qc.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
-
-  auto cost = DbSqliteTable::EstimateCost(table, qc);
-  ASSERT_EQ(cost.rows, 1u);
-
-  // The cost should be 1000 (fixed cost) + 100 (filter cost) + 2 (iteration
-  // cost).
-  ASSERT_DOUBLE_EQ(cost.cost, 1102);
-}
-
-TEST(DbSqliteTableTest, EstimateCostEqualityConstraint) {
-  TestTable table(1234u);
-
-  QueryConstraints qc;
-  qc.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
-
-  auto cost = DbSqliteTable::EstimateCost(table, qc);
-  ASSERT_EQ(cost.rows, 120u);
-
-  // The cost should be 1000 (fixed cost) + 240.332 (filter cost) + 240
-  // (iteration cost).
-  ASSERT_DOUBLE_EQ(round(cost.cost), 1480);
-}
-
-TEST(DbSqliteTableTest, EstimateCostSort) {
-  TestTable table(1234u);
-
-  QueryConstraints qc;
-  qc.AddOrderBy(1u, false);
-
-  auto cost = DbSqliteTable::EstimateCost(table, qc);
-  ASSERT_EQ(cost.rows, 1234u);
-
-  // The cost should be 1000 (fixed cost) + 12672.102 (sort cost) + 2468
-  // (iteration cost).
-  ASSERT_DOUBLE_EQ(round(cost.cost), 16140);
+  ASSERT_LT(sorted_cost.cost, a_cost.cost);
+  ASSERT_EQ(sorted_cost.rows, a_cost.rows);
 }
 
 }  // namespace
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
index 72069e9..a78e2ec 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/api_integrationtest.cc
@@ -404,6 +404,8 @@
             value << "(pointer)" << std::hex << it.pointer_value();
           } else if (it.has_legacy_json_value()) {
             value << "(json)" << it.legacy_json_value();
+          } else if (it.has_nested_value()) {
+            value << "(nested)" << it.nested_value().string_value();
           }
           slice += value.str();
           first_annotation = false;
@@ -1117,6 +1119,10 @@
     });
   }
 
+  // Ensure a single line if statement counts as a valid scope for the macro.
+  if (true)
+    TRACE_EVENT("test", "SingleLineTestEvent");
+
   {
     // Make sure you can have multiple scoped events in the same scope.
     TRACE_EVENT("test", "TestEvent");
@@ -1128,6 +1134,7 @@
   tracing_session->get()->StopBlocking();
   auto slices = ReadSlicesFromTrace(tracing_session->get());
   EXPECT_THAT(slices, ElementsAre("B:test.TestEventWithArgs", "E:test.",
+                                  "B:test.SingleLineTestEvent", "E:test.",
                                   "B:test.TestEvent", "B:test.AnotherEvent",
                                   "E:test.", "E:test."));
 }
@@ -1227,6 +1234,86 @@
           R"(B:test.E(normal_arg=(string)x,custom_arg=(json){"key": 123}))"));
 }
 
+TEST_F(PerfettoApiTest, TrackEventCustomRawDebugAnnotations) {
+  // Setup the trace config.
+  perfetto::TraceConfig cfg;
+  cfg.set_duration_ms(500);
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("track_event");
+  ds_cfg->set_legacy_config("test");
+
+  // Note: this class is also testing a non-moveable and non-copiable argument.
+  class MyRawDebugAnnotation : public perfetto::DebugAnnotation {
+   public:
+    MyRawDebugAnnotation() { msg_->set_string_value("nested_value"); }
+    ~MyRawDebugAnnotation() = default;
+
+    // |msg_| already deletes these implicitly, but let's be explicit for safety
+    // against future changes.
+    MyRawDebugAnnotation(const MyRawDebugAnnotation&) = delete;
+    MyRawDebugAnnotation(MyRawDebugAnnotation&&) = delete;
+
+    void Add(perfetto::protos::pbzero::DebugAnnotation* annotation) const {
+      auto ranges = msg_.GetRanges();
+      annotation->AppendScatteredBytes(
+          perfetto::protos::pbzero::DebugAnnotation::kNestedValueFieldNumber,
+          &ranges[0], ranges.size());
+    }
+
+   private:
+    mutable protozero::HeapBuffered<
+        perfetto::protos::pbzero::DebugAnnotation::NestedValue>
+        msg_;
+  };
+
+  // Create a new trace session.
+  auto* tracing_session = NewTrace(cfg);
+  tracing_session->get()->StartBlocking();
+
+  TRACE_EVENT_BEGIN("test", "E", "raw_arg", MyRawDebugAnnotation());
+  TRACE_EVENT_BEGIN("test", "E", "plain_arg", 42, "raw_arg",
+                    MyRawDebugAnnotation());
+  perfetto::TrackEvent::Flush();
+
+  tracing_session->get()->StopBlocking();
+  auto slices = ReadSlicesFromTrace(tracing_session->get());
+  EXPECT_THAT(
+      slices,
+      ElementsAre("B:test.E(raw_arg=(nested)nested_value)",
+                  "B:test.E(plain_arg=(int)42,raw_arg=(nested)nested_value)"));
+}
+
+TEST_F(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
+  // Setup the trace config.
+  perfetto::TraceConfig cfg;
+  cfg.set_duration_ms(500);
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("track_event");
+  ds_cfg->set_legacy_config("foo");
+
+  // Create a new trace session.
+  auto* tracing_session = NewTrace(cfg);
+  tracing_session->get()->StartBlocking();
+
+  bool called = false;
+  auto ArgumentFunction = [&] {
+    called = true;
+    return 123;
+  };
+
+  TRACE_EVENT_BEGIN("test", "DisabledEvent", "arg", ArgumentFunction());
+  { TRACE_EVENT("test", "DisabledScopedEvent", "arg", ArgumentFunction()); }
+  perfetto::TrackEvent::Flush();
+
+  tracing_session->get()->StopBlocking();
+  EXPECT_FALSE(called);
+
+  ArgumentFunction();
+  EXPECT_TRUE(called);
+}
+
 TEST_F(PerfettoApiTest, OneDataSourceOneEvent) {
   auto* data_source = &data_sources_["my_data_source"];
 
diff --git a/test/metrics/android_lmk_reason.out b/test/metrics/android_lmk_reason.out
new file mode 100644
index 0000000..6bcb83d
--- /dev/null
+++ b/test/metrics/android_lmk_reason.out
@@ -0,0 +1,5 @@
+android_lmk_reason {
+  lmks: {
+    oom_score_adj: 0
+  }
+}
diff --git a/test/metrics/android_lmk_reason.py b/test/metrics/android_lmk_reason.py
new file mode 100644
index 0000000..efede95
--- /dev/null
+++ b/test/metrics/android_lmk_reason.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+# Copyright (C) 2018 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.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet()
+trace.add_process(1, 0, 'init')
+trace.add_process(2, 1, 'system_server')
+trace.add_process(3, 1, 'lmk_victim_1')
+
+trace.add_ftrace_packet(cpu=0)
+trace.add_oom_score_update(ts=1, oom_score_adj=0, pid=3)
+trace.add_kernel_lmk(ts=100, tid=3)
+
+print(trace.trace.SerializeToString())
diff --git a/test/metrics/index b/test/metrics/index
index 0ee6a7f..0175754 100644
--- a/test/metrics/index
+++ b/test/metrics/index
@@ -5,6 +5,7 @@
 # Synthetic traces
 android_mem_by_priority.py android_mem android_mem_by_priority.out
 android_lmk.py android_lmk android_mem_lmk.out
+android_lmk_reason.py android_lmk_reason android_lmk_reason.out
 android_ion.py android_ion android_ion.out
 
 android_startup.py android_startup android_startup.out
diff --git a/test/trace_processor/config_metadata.out b/test/trace_processor/config_metadata.out
index 102f707..edcba50 100644
--- a/test/trace_processor/config_metadata.out
+++ b/test/trace_processor/config_metadata.out
@@ -1,2 +1,3 @@
 "name","str_value"
+"android_build_fingerprint","the fingerprint"
 "trace_uuid","123e4567-e89b-12d3-a456-426655443322"
diff --git a/test/trace_processor/config.textproto b/test/trace_processor/config_metadata.textproto
similarity index 78%
rename from test/trace_processor/config.textproto
rename to test/trace_processor/config_metadata.textproto
index 7d399ba..e2c1766 100644
--- a/test/trace_processor/config.textproto
+++ b/test/trace_processor/config_metadata.textproto
@@ -17,4 +17,8 @@
     trace_uuid_lsb: -6605018796207623390
   }
 }
-
+packet {
+  system_info {
+    android_build_fingerprint: "the fingerprint"
+  }
+}
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 4a4da7c..85857c1 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -149,8 +149,8 @@
 # Parsing of an html file with systrace data inside
 ../data/systrace.html systrace_html.sql systrace_html.out
 
-# Config
-config.textproto metadata.sql config_metadata.out
+# Config & metadata
+config_metadata.textproto metadata.sql config_metadata.out
 
 # Decoding of sched_waking events from a trace with compact scheduling events.
 # Verifies the contents of raw & instants tables.
diff --git a/test/trace_processor/metadata.sql b/test/trace_processor/metadata.sql
index 34eddee..164675d 100644
--- a/test/trace_processor/metadata.sql
+++ b/test/trace_processor/metadata.sql
@@ -1 +1 @@
-select name, str_value from metadata where name = "trace_uuid";
+select name, str_value from metadata order by name;
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 7c45e92..fa38f37 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -155,7 +155,10 @@
         ('required', {'libperfetto_android_internal', 'trigger_perfetto'}),
     ],
     'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
-    'trace_processor_shell': [('static_executable', True),],
+    'trace_processor_shell': [
+      ('dist', {'targets': ['sdk_repo']}),
+      ('stl', 'libc++_static'),
+    ],
 }
 
 
@@ -262,6 +265,16 @@
   if isinstance(value, Target):
     value.to_string(output)
     return
+  if isinstance(value, dict):
+    kv_output = []
+    for k, v in value.items():
+      write_blueprint_key_value(kv_output, k, v)
+
+    output.append('  %s: {' % name)
+    for line in kv_output:
+      output.append('  %s' % line)
+    output.append('  },')
+    return
   output.append('  %s: "%s",' % (name, value))
 
 
@@ -320,7 +333,8 @@
     self.android = Target('android')
     self.host = Target('host')
     self.lto = None
-    self.static_executable = False
+    self.stl = None
+    self.dist = dict()
     self.data = set()
     # The genrule_XXX below are properties that must to be propagated back
     # on the module(s) that depend on the genrule.
@@ -349,9 +363,10 @@
     self._output_field(output, 'include_dirs')
     self._output_field(output, 'header_libs')
     self._output_field(output, 'required')
-    self._output_field(output, 'static_executable')
+    self._output_field(output, 'dist')
     self._output_field(output, 'tool_files')
     self._output_field(output, 'data')
+    self._output_field(output, 'stl')
 
     target_out = []
     self._output_field(target_out, 'android')
@@ -625,8 +640,10 @@
     curr = getattr(module, key)
     if add_val and isinstance(add_val, set) and isinstance(curr, set):
       curr.update(add_val)
-    elif isinstance(add_val, bool) and isinstance(curr, bool):
+    elif isinstance(add_val, str) and (not curr or isinstance(curr, str)):
       setattr(module, key, add_val)
+    elif isinstance(add_val, dict) and isinstance(curr, dict):
+      curr.update(add_val)
     else:
       raise Error('Unimplemented type of additional_args: %r' % key)
 
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index f776369..3202ad8 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -94,6 +94,7 @@
     'protos/perfetto/trace/trace.proto',
     'protos/perfetto/trace/trace_packet.proto',
     'protos/perfetto/trace/trace_packet_defaults.proto',
+    'protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto',
     'protos/perfetto/trace/track_event/debug_annotation.proto',
     'protos/perfetto/trace/track_event/log_message.proto',
     'protos/perfetto/trace/track_event/process_descriptor.proto',