Merge "perfetto-cmd: Save/Load state using protozero"
diff --git a/.gn b/.gn
index d96dec4..692a951 100644
--- a/.gn
+++ b/.gn
@@ -1 +1,15 @@
+# Copyright (C) 2017 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.
+
 buildconfig = "//gn/standalone/BUILDCONFIG.gn"
diff --git a/Android.bp b/Android.bp
index 5a1b59e..635cfab 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3826,6 +3826,9 @@
   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/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3841,6 +3844,9 @@
   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/chrome_keyed_service.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3857,6 +3863,9 @@
   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/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.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 +3881,9 @@
   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/chrome_keyed_service.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3892,6 +3904,9 @@
   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/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3908,6 +3923,9 @@
   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/chrome_keyed_service.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3924,6 +3942,9 @@
   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/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.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",
@@ -3940,6 +3961,9 @@
   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/chrome_keyed_service.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.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",
diff --git a/BUILD b/BUILD
index db7385c..9f05570 100644
--- a/BUILD
+++ b/BUILD
@@ -2273,6 +2273,9 @@
     name = "protos_perfetto_trace_track_event_protos",
     srcs = [
         "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+        "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+        "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+        "protos/perfetto/trace/track_event/chrome_user_event.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/LICENSE b/LICENSE
new file mode 100644
index 0000000..25f8ab9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2017, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/docs/contributing.md b/docs/contributing.md
index ff70e62..9737028 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -1,32 +1,51 @@
-# Contributing to Pefetto
-This project uses [Android AOSP Gerrit][perfetto-gerrit] for code reviews and
+# Contributing to Perfetto
+This project uses [Android AOSP Gerrit][perfetto-gerrit] for code reviews,
 uses the [Google C++ style][google-cpp-style] and targets `-std=c++11`.
 
+Development happens in this repo:
+https://android.googlesource.com/platform/external/perfetto/
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code Reviews
+
+All submissions, including submissions by project members, require review.
+We use [Android AOSP Gerrit][perfetto-gerrit] for this purpose.
+
 `git cl upload` from [Chromium depot tools][depot-tools] is the preferred
 workflow to upload patches, as it supports presubmits and code formatting via
 `git cl format`.
 
-See https://source.android.com/source/contributing for more details about
-external contributions and CLA signing.
-
-
-### Continuous integration
+## Continuous integration
 
 Continuous build and test coverage is available at
 [ci.perfetto.dev](https://ci.perfetto.dev).
 
 **Trybots**:  
-CLs uploaded to gerrit are automatically submitted to the CI and
+CLs uploaded to Gerrit are automatically submitted to the CI and
 and available on the CI page.
 If the label `Presubmit-Ready: +1` is set, the CI will also publish a comment
 like [this][ci-example] on the CL.
 
-### Community
+## Community
 
 You can reach us on our [Discord channel](https://discord.gg/35ShE3A).
 If you prefer using IRC we have an experimental Discord <> IRC bridge
 synced with `#perfetto-dev` on [Freenode](https://webchat.freenode.net/).
 
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
+
 [perfetto-gerrit]: https://android-review.googlesource.com/q/project:platform%252Fexternal%252Fperfetto+status:open
 [google-cpp-style]: https://google.github.io/styleguide/cppguide.html
 [depot-tools]: https://dev.chromium.org/developers/how-tos/depottools
diff --git a/docs/security-model.md b/docs/security-model.md
index 369e6cc..5f38531 100644
--- a/docs/security-model.md
+++ b/docs/security-model.md
@@ -63,8 +63,3 @@
 types of packets, which doesn't scale.  
 However, the service appends the POSIX uid of the producer to each `TracePacket`
 to perform offline attestation of the contents of the trace.
-
-Internal docs
--------------
-* [Android security review doc](http://go/perfetto-asec)
-* [Chromium security review doc](http://go/perfetto-csec)
diff --git a/docs/trace-processor.md b/docs/trace-processor.md
index 9ef2546..cea8846 100644
--- a/docs/trace-processor.md
+++ b/docs/trace-processor.md
@@ -10,7 +10,7 @@
   Web Assembly module.
 * Standalone, using the `trace_processor_shell` target
   (`ninja -C out/xxx trace_processor_shell`).
-* In internal google3 pipelines for batch processing.
+* In internal pipelines for batch processing.
 
 Supported input formats:
  * Perfetto .proto traces
diff --git a/gn/write_buildflag_header.py b/gn/write_buildflag_header.py
index 6d92daa..702c70f 100644
--- a/gn/write_buildflag_header.py
+++ b/gn/write_buildflag_header.py
@@ -28,6 +28,24 @@
 import shlex
 import sys
 
+COPYRIGHT_HEADER = '''/*
+ * 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.
+ */
+
+'''
+
 
 def main():
   parser = argparse.ArgumentParser()
@@ -64,6 +82,7 @@
   lines.append('')
 
   with open(args.out, 'w') as out:
+    out.write(COPYRIGHT_HEADER)
     out.write('\n'.join(lines))
 
 
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index 4edd028..1b35256 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 // Generated by ../../gn/write_buildflag_header.py
 
 // fix_include_guards: off
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 49f80f5..1702d01 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 // Generated by ../../gn/write_buildflag_header.py
 
 // fix_include_guards: off
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index f291186..9b5bcff 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -90,11 +90,24 @@
 
 // Efficiently determines whether tracing is enabled for the given category, and
 // if so, emits one trace event with the given arguments.
-#define PERFETTO_INTERNAL_TRACK_EVENT(category, ...)                      \
-  ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::CallIfCategoryEnabled<    \
-      PERFETTO_GET_CATEGORY_INDEX(category)>([&](uint32_t instances) {    \
-    ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceForCategory<       \
-        PERFETTO_GET_CATEGORY_INDEX(category)>(instances, ##__VA_ARGS__); \
+#define PERFETTO_INTERNAL_TRACK_EVENT(category, name, ...)                    \
+  ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::CallIfCategoryEnabled<        \
+      PERFETTO_GET_CATEGORY_INDEX(category)>([&](uint32_t instances) {        \
+    /* Check that |name| is a static string. If this fails, you probably want \
+     * to use "constexpr const char*" if the string is computed by an         \
+     * expression, or something like this if the string is fully dynamic:     \
+     *                                                                        \
+     *   TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {   \
+     *     ctx.event()->set_name(dynamic_name);                               \
+     *   }                                                                    \
+     */                                                                       \
+    static_assert(                                                            \
+        (name) == nullptr || (name) != nullptr,                               \
+        "Track event name must be a (constexpr) static string. Use a trace "  \
+        "lambda if you need a dynamic name (see above).");                    \
+    ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceForCategory<           \
+        PERFETTO_GET_CATEGORY_INDEX(category)>(instances, name,               \
+                                               ##__VA_ARGS__);                \
   })
 
 // Generate a unique variable name with a given prefix.
diff --git a/infra/ci/controller/index.yaml b/infra/ci/controller/index.yaml
index 36e4583..bdce6e0 100644
--- a/infra/ci/controller/index.yaml
+++ b/infra/ci/controller/index.yaml
@@ -1,3 +1,17 @@
+# 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.
+
 indexes:
 # AUTOGENERATED
 
diff --git a/infra/ci/frontend/index.yaml b/infra/ci/frontend/index.yaml
index 6536212..eb9fd6f 100644
--- a/infra/ci/frontend/index.yaml
+++ b/infra/ci/frontend/index.yaml
@@ -1,2 +1,16 @@
+# 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.
+
 indexes:
 # AUTOGENERATED
diff --git a/infra/ci/worker/gce-startup-script.sh b/infra/ci/worker/gce-startup-script.sh
index 7a3081d..2e384b8 100644
--- a/infra/ci/worker/gce-startup-script.sh
+++ b/infra/ci/worker/gce-startup-script.sh
@@ -1,4 +1,18 @@
 #!/bin/bash
+# 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.
+
 set -eux -o pipefail
 
 # num-workers is set at VM creation time in the Makefile.
diff --git a/infra/perfetto-get.appspot.com/index.yaml b/infra/perfetto-get.appspot.com/index.yaml
index 6536212..eb9fd6f 100644
--- a/infra/perfetto-get.appspot.com/index.yaml
+++ b/infra/perfetto-get.appspot.com/index.yaml
@@ -1,2 +1,16 @@
+# 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.
+
 indexes:
 # AUTOGENERATED
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index c953f36..80fd4a8 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
 // Autogenerated by:
 // ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
 // Do not edit.
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 1df23ca..43840f0 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3986,6 +3986,87 @@
 
 // End of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
 
+// Begin of protos/perfetto/trace/track_event/chrome_keyed_service.proto
+
+// Details about one of Chrome's keyed services associated with the event.
+message ChromeKeyedService {
+  // Name of the service, e.g. "MediaRouter", "PreviewsService", etc. (in
+  // Chrome, these are static strings known at compile time).
+  optional string name = 1;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_keyed_service.proto
+
+// Begin of protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
+
+// Details about a legacy Chrome IPC message that is either sent by the event.
+// TODO(eseckler): Also use this message on the receiving side?
+message ChromeLegacyIpc {
+  enum MessageClass {
+    CLASS_UNSPECIFIED = 0;
+    CLASS_AUTOMATION = 1;
+    CLASS_FRAME = 2;
+    CLASS_PAGE = 3;
+    CLASS_VIEW = 4;
+    CLASS_WIDGET = 5;
+    CLASS_INPUT = 6;
+    CLASS_TEST = 7;
+    CLASS_WORKER = 8;
+    CLASS_NACL = 9;
+    CLASS_GPU_CHANNEL = 10;
+    CLASS_MEDIA = 11;
+    CLASS_PPAPI = 12;
+    CLASS_CHROME = 13;
+    CLASS_DRAG = 14;
+    CLASS_PRINT = 15;
+    CLASS_EXTENSION = 16;
+    CLASS_TEXT_INPUT_CLIENT = 17;
+    CLASS_BLINK_TEST = 18;
+    CLASS_ACCESSIBILITY = 19;
+    CLASS_PRERENDER = 20;
+    CLASS_CHROMOTING = 21;
+    CLASS_BROWSER_PLUGIN = 22;
+    CLASS_ANDROID_WEB_VIEW = 23;
+    CLASS_NACL_HOST = 24;
+    CLASS_ENCRYPTED_MEDIA = 25;
+    CLASS_CAST = 26;
+    CLASS_GIN_JAVA_BRIDGE = 27;
+    CLASS_CHROME_UTILITY_PRINTING = 28;
+    CLASS_OZONE_GPU = 29;
+    CLASS_WEB_TEST = 30;
+    CLASS_NETWORK_HINTS = 31;
+    CLASS_EXTENSIONS_GUEST_VIEW = 32;
+    CLASS_GUEST_VIEW = 33;
+    CLASS_MEDIA_PLAYER_DELEGATE = 34;
+    CLASS_EXTENSION_WORKER = 35;
+    CLASS_SUBRESOURCE_FILTER = 36;
+    CLASS_UNFREEZABLE_FRAME = 37;
+  }
+
+  // Corresponds to the message class type defined in Chrome's IPCMessageStart
+  // enum, e.g. FrameMsgStart,
+  optional MessageClass message_class = 1;
+
+  // Line number of the message definition. See Chrome's IPC_MESSAGE_ID and
+  // IPC_MESSAGE_START macros.
+  optional uint32 message_line = 2;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
+
+// Begin of protos/perfetto/trace/track_event/chrome_user_event.proto
+
+// Details about a UI interaction initiated by the user, such as opening or
+// closing a tab or a context menu.
+message ChromeUserEvent {
+  // Name of the action, e.g. "NewTab", "ShowBookmarkManager", etc. (in
+  // Chrome, these are usually static strings known at compile time, or
+  // concatenations of multiple such static strings).
+  optional string action = 1;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_user_event.proto
+
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
@@ -4278,7 +4359,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 25.
+// Next reserved id: 12 (up to 15). Next id: 28.
 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.
@@ -4374,6 +4455,9 @@
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
   optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
+  optional ChromeUserEvent chrome_user_event = 25;
+  optional ChromeKeyedService chrome_keyed_service = 26;
+  optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index afb3630..a897601 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -17,6 +17,9 @@
 perfetto_proto_library("@TYPE@") {
   sources = [
     "chrome_compositor_scheduler_state.proto",
+    "chrome_keyed_service.proto",
+    "chrome_legacy_ipc.proto",
+    "chrome_user_event.proto",
     "debug_annotation.proto",
     "log_message.proto",
     "process_descriptor.proto",
diff --git a/protos/perfetto/trace/track_event/chrome_keyed_service.proto b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
new file mode 100644
index 0000000..95ce21d
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+// Details about one of Chrome's keyed services associated with the event.
+message ChromeKeyedService {
+  // Name of the service, e.g. "MediaRouter", "PreviewsService", etc. (in
+  // Chrome, these are static strings known at compile time).
+  optional string name = 1;
+}
diff --git a/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
new file mode 100644
index 0000000..df6dcce
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+// Details about a legacy Chrome IPC message that is either sent by the event.
+// TODO(eseckler): Also use this message on the receiving side?
+message ChromeLegacyIpc {
+  enum MessageClass {
+    CLASS_UNSPECIFIED = 0;
+    CLASS_AUTOMATION = 1;
+    CLASS_FRAME = 2;
+    CLASS_PAGE = 3;
+    CLASS_VIEW = 4;
+    CLASS_WIDGET = 5;
+    CLASS_INPUT = 6;
+    CLASS_TEST = 7;
+    CLASS_WORKER = 8;
+    CLASS_NACL = 9;
+    CLASS_GPU_CHANNEL = 10;
+    CLASS_MEDIA = 11;
+    CLASS_PPAPI = 12;
+    CLASS_CHROME = 13;
+    CLASS_DRAG = 14;
+    CLASS_PRINT = 15;
+    CLASS_EXTENSION = 16;
+    CLASS_TEXT_INPUT_CLIENT = 17;
+    CLASS_BLINK_TEST = 18;
+    CLASS_ACCESSIBILITY = 19;
+    CLASS_PRERENDER = 20;
+    CLASS_CHROMOTING = 21;
+    CLASS_BROWSER_PLUGIN = 22;
+    CLASS_ANDROID_WEB_VIEW = 23;
+    CLASS_NACL_HOST = 24;
+    CLASS_ENCRYPTED_MEDIA = 25;
+    CLASS_CAST = 26;
+    CLASS_GIN_JAVA_BRIDGE = 27;
+    CLASS_CHROME_UTILITY_PRINTING = 28;
+    CLASS_OZONE_GPU = 29;
+    CLASS_WEB_TEST = 30;
+    CLASS_NETWORK_HINTS = 31;
+    CLASS_EXTENSIONS_GUEST_VIEW = 32;
+    CLASS_GUEST_VIEW = 33;
+    CLASS_MEDIA_PLAYER_DELEGATE = 34;
+    CLASS_EXTENSION_WORKER = 35;
+    CLASS_SUBRESOURCE_FILTER = 36;
+    CLASS_UNFREEZABLE_FRAME = 37;
+  }
+
+  // Corresponds to the message class type defined in Chrome's IPCMessageStart
+  // enum, e.g. FrameMsgStart,
+  optional MessageClass message_class = 1;
+
+  // Line number of the message definition. See Chrome's IPC_MESSAGE_ID and
+  // IPC_MESSAGE_START macros.
+  optional uint32 message_line = 2;
+}
diff --git a/protos/perfetto/trace/track_event/chrome_user_event.proto b/protos/perfetto/trace/track_event/chrome_user_event.proto
new file mode 100644
index 0000000..5ba91d1
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_user_event.proto
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+// Details about a UI interaction initiated by the user, such as opening or
+// closing a tab or a context menu.
+message ChromeUserEvent {
+  // Name of the action, e.g. "NewTab", "ShowBookmarkManager", etc. (in
+  // Chrome, these are usually static strings known at compile time, or
+  // concatenations of multiple such static strings).
+  optional string action = 1;
+}
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index b4a20cc..4d8b1fb 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -21,6 +21,9 @@
 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";
+import "protos/perfetto/trace/track_event/chrome_keyed_service.proto";
+import "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto";
+import "protos/perfetto/trace/track_event/chrome_user_event.proto";
 
 package perfetto.protos;
 
@@ -83,7 +86,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 25.
+// Next reserved id: 12 (up to 15). Next id: 28.
 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.
@@ -179,6 +182,9 @@
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
   optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
+  optional ChromeUserEvent chrome_user_event = 25;
+  optional ChromeKeyedService chrome_keyed_service = 26;
+  optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index 8e950d5..5b467e1 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -1,3 +1,18 @@
+/*
+ * 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_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
 #define SRC_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
@@ -10,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// a6fca0c2012a0bfb620b978f2c0579145cdad174
+// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
 // SHA1(protos/perfetto/config/perfetto_config.proto)
 // 3cad942a7f5da2b1936464abea5d6c3d76525e9e
 
diff --git a/src/profiling/memory/README.md b/src/profiling/memory/README.md
index 9e9272ea..2fa5747 100644
--- a/src/profiling/memory/README.md
+++ b/src/profiling/memory/README.md
@@ -5,4 +5,4 @@
 
 For documentation, see https://docs.perfetto.dev/#/heapprofd.
 
-Googlers, for design doc see: http://go/heapprofd-design.
+Googlers, for design doc see: http://goto.google.com/heapprofd-design.
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index 2a02b64..2497451 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -750,9 +750,14 @@
     PERFETTO_DLOG("%d: Received FDs.", self->peer_pid());
     int raw_fd = pending_process.shmem.fd();
     // TODO(fmayer): Full buffer could deadlock us here.
-    self->Send(&data_source.client_configuration,
-               sizeof(data_source.client_configuration), &raw_fd, 1,
-               base::UnixSocket::BlockingMode::kBlocking);
+    if (!self->Send(&data_source.client_configuration,
+                    sizeof(data_source.client_configuration), &raw_fd, 1,
+                    base::UnixSocket::BlockingMode::kBlocking)) {
+      // If Send fails, the socket will have been Shutdown, and the raw socket
+      // closed.
+      producer_->pending_processes_.erase(it);
+      return;
+    }
 
     UnwindingWorker::HandoffData handoff_data;
     handoff_data.data_source_instance_id =
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 6e0ff15..8cda24c 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -1,3 +1,18 @@
+/*
+ * 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_PROTOZERO_TEST_EXAMPLE_PROTO_TEST_MESSAGES_DESCRIPTOR_H_
 #define SRC_PROTOZERO_TEST_EXAMPLE_PROTO_TEST_MESSAGES_DESCRIPTOR_H_
@@ -10,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// a6fca0c2012a0bfb620b978f2c0579145cdad174
+// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
 // SHA1(src/protozero/test/example_proto/test_messages.proto)
 // 61c0771c4c18c994996335be97413d944ce8f80d
 
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index 4c49442..b6f089a 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
 // Autogenerated by:
 // ../../tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
 // Do not edit.
diff --git a/src/trace_processor/importers/proto/args_table_utils.cc b/src/trace_processor/importers/proto/args_table_utils.cc
index d784bd3..bf29509 100644
--- a/src/trace_processor/importers/proto/args_table_utils.cc
+++ b/src/trace_processor/importers/proto/args_table_utils.cc
@@ -27,10 +27,11 @@
 ProtoToArgsTable::ProtoToArgsTable(PacketSequenceState* sequence_state,
                                    size_t sequence_state_generation,
                                    TraceProcessorContext* context,
+                                   ArgsTracker* args_tracker,
                                    std::string starting_prefix,
                                    size_t prefix_size_hint)
-    : state_{context->args_tracker.get(), context, sequence_state,
-             sequence_state_generation, RowId(0)},
+    : state_{args_tracker ? args_tracker : context->args_tracker.get(), context,
+             sequence_state, sequence_state_generation, RowId(0)},
       prefix_(std::move(starting_prefix)) {
   prefix_.reserve(prefix_size_hint);
 }
diff --git a/src/trace_processor/importers/proto/args_table_utils.h b/src/trace_processor/importers/proto/args_table_utils.h
index d7caf9b..4eca899 100644
--- a/src/trace_processor/importers/proto/args_table_utils.h
+++ b/src/trace_processor/importers/proto/args_table_utils.h
@@ -103,15 +103,15 @@
   // |sequence_state| and |sequence_state_generation| provide access to
   // interning data. |context| provides access to storage.
   //
-  // |proto_descriptor_array| and |proto_descriptor_array_size| define the
-  // compile time reflection of the proto we are outputing.
-  // |args_tracker| is the access to the Args table.
+  // |args_tracker| is the access to the Args table, if nullptr then we will use
+  // the tracker inside |context|.
   // |starting_prefix| will be prepended to all columns.
   // |prefix_size_hint| allows the class to upfront reserve the expected string
   // size needed.
   ProtoToArgsTable(PacketSequenceState* sequence_state,
                    size_t sequence_state_generation,
                    TraceProcessorContext* context,
+                   ArgsTracker* args_tracker = nullptr,
                    std::string starting_prefix = "",
                    size_t prefix_size_hint = 64);
 
diff --git a/src/trace_processor/importers/proto/args_table_utils_unittest.cc b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
index daa1325..467620d 100644
--- a/src/trace_processor/importers/proto/args_table_utils_unittest.cc
+++ b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
@@ -78,8 +78,8 @@
 
 TEST_F(ArgsTableUtilsTest, EnsureChromeCompositorStateDescriptorParses) {
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(
       kChromeCompositorSchedulerStateDescriptor.data(),
       kChromeCompositorSchedulerStateDescriptor.size());
@@ -90,8 +90,8 @@
 
 TEST_F(ArgsTableUtilsTest, EnsureTestMessageProtoParses) {
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   EXPECT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -128,8 +128,8 @@
 
   storage_->mutable_track_table()->Insert({});
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -201,8 +201,8 @@
 
   storage_->mutable_track_table()->Insert({});
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -230,8 +230,8 @@
 
   storage_->mutable_track_table()->Insert({});
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -259,8 +259,8 @@
 
   storage_->mutable_track_table()->Insert({});
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -302,8 +302,8 @@
 
   storage_->mutable_track_table()->Insert({});
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
                                               kTestMessagesDescriptor.size());
   ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
@@ -358,8 +358,8 @@
       std::move(blob));
 
   ProtoToArgsTable helper(sequence_state_.get(),
-                          sequence_state_->current_generation(), &context_, "",
-                          0);
+                          sequence_state_->current_generation(), &context_,
+                          nullptr, "", 0);
   // Now we override the behaviour of |value_c| so we can expand the iid into
   // multiple args rows.
   helper.AddParsingOverride(
diff --git a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
index bd8b3f2..1a6b94f 100644
--- a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
+++ b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
@@ -1,3 +1,18 @@
+/*
+ * 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_IMPORTERS_PROTO_CHROME_COMPOSITOR_SCHEDULER_STATE_DESCRIPTOR_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_CHROME_COMPOSITOR_SCHEDULER_STATE_DESCRIPTOR_H_
@@ -10,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// a6fca0c2012a0bfb620b978f2c0579145cdad174
+// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
 // SHA1(protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto)
 // 360017d4658dfd81fbf16af8cc2abb994958af05
 
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 1305fbf..9f0560f 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -28,6 +28,9 @@
 
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_user_event.pbzero.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 #include "protos/perfetto/trace/track_event/log_message.pbzero.h"
 #include "protos/perfetto/trace/track_event/source_location.pbzero.h"
@@ -133,7 +136,54 @@
           context->storage->InternString("legacy_event.flow_direction")),
       flow_direction_value_in_id_(context->storage->InternString("in")),
       flow_direction_value_out_id_(context->storage->InternString("out")),
-      flow_direction_value_inout_id_(context->storage->InternString("inout")) {}
+      flow_direction_value_inout_id_(context->storage->InternString("inout")),
+      chrome_user_event_action_args_key_id_(
+          context->storage->InternString("user_event.action")),
+      chrome_legacy_ipc_class_args_key_id_(
+          context->storage->InternString("legacy_ipc.class")),
+      chrome_legacy_ipc_line_args_key_id_(
+          context->storage->InternString("legacy_ipc.line")),
+      chrome_keyed_service_name_args_key_id_(
+          context->storage->InternString("keyed_service.name")),
+      chrome_legacy_ipc_class_ids_{
+          {context->storage->InternString("UNSPECIFIED"),
+           context->storage->InternString("AUTOMATION"),
+           context->storage->InternString("FRAME"),
+           context->storage->InternString("PAGE"),
+           context->storage->InternString("VIEW"),
+           context->storage->InternString("WIDGET"),
+           context->storage->InternString("INPUT"),
+           context->storage->InternString("TEST"),
+           context->storage->InternString("WORKER"),
+           context->storage->InternString("NACL"),
+           context->storage->InternString("GPU_CHANNEL"),
+           context->storage->InternString("MEDIA"),
+           context->storage->InternString("PPAPI"),
+           context->storage->InternString("CHROME"),
+           context->storage->InternString("DRAG"),
+           context->storage->InternString("PRINT"),
+           context->storage->InternString("EXTENSION"),
+           context->storage->InternString("TEXT_INPUT_CLIENT"),
+           context->storage->InternString("BLINK_TEST"),
+           context->storage->InternString("ACCESSIBILITY"),
+           context->storage->InternString("PRERENDER"),
+           context->storage->InternString("CHROMOTING"),
+           context->storage->InternString("BROWSER_PLUGIN"),
+           context->storage->InternString("ANDROID_WEB_VIEW"),
+           context->storage->InternString("NACL_HOST"),
+           context->storage->InternString("ENCRYPTED_MEDIA"),
+           context->storage->InternString("CAST"),
+           context->storage->InternString("GIN_JAVA_BRIDGE"),
+           context->storage->InternString("CHROME_UTILITY_PRINTING"),
+           context->storage->InternString("OZONE_GPU"),
+           context->storage->InternString("WEB_TEST"),
+           context->storage->InternString("NETWORK_HINTS"),
+           context->storage->InternString("EXTENSIONS_GUEST_VIEW"),
+           context->storage->InternString("GUEST_VIEW"),
+           context->storage->InternString("MEDIA_PLAYER_DELEGATE"),
+           context->storage->InternString("EXTENSION_WORKER"),
+           context->storage->InternString("SUBRESOURCE_FILTER"),
+           context->storage->InternString("UNFREEZABLE_FRAME")}} {}
 
 void TrackEventParser::ParseTrackEvent(int64_t ts,
                                        int64_t tts,
@@ -408,7 +458,17 @@
     }
     if (event.has_cc_scheduler_state()) {
       ParseCcScheduler(event.cc_scheduler_state(), sequence_state,
-                       sequence_state_generation, row_id);
+                       sequence_state_generation, args_tracker, row_id);
+    }
+    if (event.has_chrome_user_event()) {
+      ParseChromeUserEvent(event.chrome_user_event(), args_tracker, row_id);
+    }
+    if (event.has_chrome_legacy_ipc()) {
+      ParseChromeLegacyIpc(event.chrome_legacy_ipc(), args_tracker, row_id);
+    }
+    if (event.has_chrome_keyed_service()) {
+      ParseChromeKeyedService(event.chrome_keyed_service(), args_tracker,
+                              row_id);
     }
 
     if (legacy_tid) {
@@ -959,13 +1019,14 @@
 void TrackEventParser::ParseCcScheduler(ConstBytes cc,
                                         PacketSequenceState* sequence_state,
                                         size_t sequence_state_generation,
+                                        ArgsTracker* args_tracker,
                                         RowId row) {
   // The 79 decides the initial amount of memory reserved in the prefix. This
   // was determined my manually counting the length of the longest column.
   constexpr size_t kCcSchedulerStateMaxColumnLength = 79;
-  ProtoToArgsTable helper(sequence_state, sequence_state_generation, context_,
-                          /* starting_prefix = */ "",
-                          kCcSchedulerStateMaxColumnLength);
+  ProtoToArgsTable helper(
+      sequence_state, sequence_state_generation, context_, args_tracker,
+      /* starting_prefix = */ "", kCcSchedulerStateMaxColumnLength);
   auto status = helper.AddProtoFileDescriptor(
       kChromeCompositorSchedulerStateDescriptor.data(),
       kChromeCompositorSchedulerStateDescriptor.size());
@@ -997,5 +1058,55 @@
       cc, ".perfetto.protos.ChromeCompositorSchedulerState", row);
 }
 
+void TrackEventParser::ParseChromeUserEvent(
+    protozero::ConstBytes chrome_user_event,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeUserEvent::Decoder event(chrome_user_event.data,
+                                                 chrome_user_event.size);
+  if (event.has_action()) {
+    StringId action_id = context_->storage->InternString(event.action());
+    args_tracker->AddArg(row, chrome_user_event_action_args_key_id_,
+                         chrome_user_event_action_args_key_id_,
+                         Variadic::String(action_id));
+  }
+}
+
+void TrackEventParser::ParseChromeLegacyIpc(
+    protozero::ConstBytes chrome_legacy_ipc,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeLegacyIpc::Decoder event(chrome_legacy_ipc.data,
+                                                 chrome_legacy_ipc.size);
+  if (event.has_message_class()) {
+    size_t message_class_index = static_cast<size_t>(event.message_class());
+    if (message_class_index >= chrome_legacy_ipc_class_ids_.size())
+      message_class_index = 0;
+    args_tracker->AddArg(
+        row, chrome_legacy_ipc_class_args_key_id_,
+        chrome_legacy_ipc_class_args_key_id_,
+        Variadic::String(chrome_legacy_ipc_class_ids_[message_class_index]));
+  }
+  if (event.has_message_line()) {
+    args_tracker->AddArg(row, chrome_legacy_ipc_line_args_key_id_,
+                         chrome_legacy_ipc_line_args_key_id_,
+                         Variadic::Integer(event.message_line()));
+  }
+}
+
+void TrackEventParser::ParseChromeKeyedService(
+    protozero::ConstBytes chrome_keyed_service,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeKeyedService::Decoder event(chrome_keyed_service.data,
+                                                    chrome_keyed_service.size);
+  if (event.has_name()) {
+    StringId action_id = context_->storage->InternString(event.name());
+    args_tracker->AddArg(row, chrome_keyed_service_name_args_key_id_,
+                         chrome_keyed_service_name_args_key_id_,
+                         Variadic::String(action_id));
+  }
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index 0c4ce41..e44b76d 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -78,7 +78,17 @@
   void ParseCcScheduler(protozero::ConstBytes cc_scheduler,
                         PacketSequenceState*,
                         size_t sequence_state_generation,
+                        ArgsTracker*,
                         RowId row);
+  void ParseChromeUserEvent(protozero::ConstBytes chrome_user_event,
+                            ArgsTracker*,
+                            RowId);
+  void ParseChromeLegacyIpc(protozero::ConstBytes chrome_legacy_ipc,
+                            ArgsTracker*,
+                            RowId);
+  void ParseChromeKeyedService(protozero::ConstBytes chrome_keyed_service,
+                               ArgsTracker*,
+                               RowId);
 
  private:
   TraceProcessorContext* context_;
@@ -108,6 +118,12 @@
   const StringId flow_direction_value_in_id_;
   const StringId flow_direction_value_out_id_;
   const StringId flow_direction_value_inout_id_;
+  const StringId chrome_user_event_action_args_key_id_;
+  const StringId chrome_legacy_ipc_class_args_key_id_;
+  const StringId chrome_legacy_ipc_line_args_key_id_;
+  const StringId chrome_keyed_service_name_args_key_id_;
+
+  std::array<StringId, 38> chrome_legacy_ipc_class_ids_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 83d430c..8dfe867 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -1,3 +1,18 @@
+/*
+ * 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_METRICS_METRICS_DESCRIPTOR_H_
 #define SRC_TRACE_PROCESSOR_METRICS_METRICS_DESCRIPTOR_H_
@@ -10,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// a6fca0c2012a0bfb620b978f2c0579145cdad174
+// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
 // SHA1(protos/perfetto/metrics/metrics.proto)
 // e1fea13f5853cbb276ae800c5fee91c46704565d
 
diff --git a/src/trace_processor/storage_columns.h b/src/trace_processor/storage_columns.h
index 83e855b..a10f4ba 100644
--- a/src/trace_processor/storage_columns.h
+++ b/src/trace_processor/storage_columns.h
@@ -1,4 +1,6 @@
 /*
+ * 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
diff --git a/src/trace_processor/storage_schema.h b/src/trace_processor/storage_schema.h
index 96888b2..fe7955c 100644
--- a/src/trace_processor/storage_schema.h
+++ b/src/trace_processor/storage_schema.h
@@ -1,4 +1,6 @@
 /*
+ * 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
diff --git a/src/trace_processor/storage_table.h b/src/trace_processor/storage_table.h
index e03a776..882ee32 100644
--- a/src/trace_processor/storage_table.h
+++ b/src/trace_processor/storage_table.h
@@ -1,4 +1,6 @@
 /*
+ * 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
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index cc86e0b..da9f127 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -49,7 +49,7 @@
 
 TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) {
   context_.config = cfg;
-  context_.storage.reset(new TraceStorage());
+  context_.storage.reset(new TraceStorage(context_.config));
   context_.track_tracker.reset(new TrackTracker(&context_));
   context_.args_tracker.reset(new ArgsTracker(&context_));
   context_.slice_tracker.reset(new SliceTracker(&context_));
diff --git a/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc b/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
index f10b335..8c23bce 100644
--- a/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 #include "src/traced/probes/ftrace/cpu_stats_parser.h"
 
 #include "src/traced/probes/ftrace/ftrace_controller.h"
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index 6cd0e03..41d0519 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
 // Autogenerated by:
 // ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
 // Do not edit.
diff --git a/test/synth_common.py b/test/synth_common.py
index 142e76e..984105b 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -296,35 +296,6 @@
       buffer_event.type = event_type
     buffer_event.duration_ns = duration
 
-  def add_thread_track_descriptor(self,
-                                  ps,
-                                  ts,
-                                  uuid,
-                                  pid,
-                                  tid,
-                                  thread_name,
-                                  inc_state_cleared=False):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    if inc_state_cleared:
-      packet.incremental_state_cleared = True
-    track = packet.track_descriptor
-    track.uuid = uuid
-    track.thread.pid = pid
-    track.thread.tid = tid
-    track.thread.thread_name = thread_name
-
-  def add_track_event(self, ps, ts, track_uuid, cat, name, type):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    event = packet.track_event
-    event.track_uuid = track_uuid
-    event.categories.append(cat)
-    event.name = name
-    event.type = type
-
 
 def create_trace():
   parser = argparse.ArgumentParser()
diff --git a/test/trace_processor/android_log_counts.sql b/test/trace_processor/android_log_counts.sql
index 4072c21..f22fea1 100644
--- a/test/trace_processor/android_log_counts.sql
+++ b/test/trace_processor/android_log_counts.sql
@@ -1,3 +1,18 @@
+--
+-- 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 count(*) as cnt from android_logs union all
 select count(*) as cnt from android_logs where prio = 3 union all
 select count(*) as cnt from android_logs where prio > 4 union all
diff --git a/test/trace_processor/android_log_msgs.sql b/test/trace_processor/android_log_msgs.sql
index db0c288..dfbd6a3 100644
--- a/test/trace_processor/android_log_msgs.sql
+++ b/test/trace_processor/android_log_msgs.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create view v1 as select tag, count(*) from android_logs group by tag order by 2 desc limit 5
 
 create view v2 as select tag, count(*) from android_logs group by tag order by 2 asc limit 5;
diff --git a/test/trace_processor/android_log_ring_buffer_mode.sql b/test/trace_processor/android_log_ring_buffer_mode.sql
index 6a5e430..2ce2bd1 100644
--- a/test/trace_processor/android_log_ring_buffer_mode.sql
+++ b/test/trace_processor/android_log_ring_buffer_mode.sql
@@ -1 +1,16 @@
+--
+-- 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 count(*) from android_logs;
diff --git a/test/trace_processor/args_string_filter_null.sql b/test/trace_processor/args_string_filter_null.sql
index 18c822d..50f90e1 100644
--- a/test/trace_processor/args_string_filter_null.sql
+++ b/test/trace_processor/args_string_filter_null.sql
@@ -1,3 +1,18 @@
+--
+-- 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 string_value
 from args
 where string_value = NULL
diff --git a/test/trace_processor/args_string_is_not_null.sql b/test/trace_processor/args_string_is_not_null.sql
index ac6b7d0..971f47d 100644
--- a/test/trace_processor/args_string_is_not_null.sql
+++ b/test/trace_processor/args_string_is_not_null.sql
@@ -1,3 +1,18 @@
+--
+-- 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 string_value
 from args
 where string_value IS NOT NULL
diff --git a/test/trace_processor/args_string_is_null.sql b/test/trace_processor/args_string_is_null.sql
index 14a819a..c1feb90 100644
--- a/test/trace_processor/args_string_is_null.sql
+++ b/test/trace_processor/args_string_is_null.sql
@@ -1,3 +1,18 @@
+--
+-- 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 string_value
 from args
 where string_value IS NULL
diff --git a/test/trace_processor/b119301023.sql b/test/trace_processor/b119301023.sql
index e751239..c5efec1 100644
--- a/test/trace_processor/b119301023.sql
+++ b/test/trace_processor/b119301023.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts from sched
 where ts > 0.1 + 1e9
 limit 10;
diff --git a/test/trace_processor/b119496959.sql b/test/trace_processor/b119496959.sql
index be4460c..207ca4f 100644
--- a/test/trace_processor/b119496959.sql
+++ b/test/trace_processor/b119496959.sql
@@ -1 +1,16 @@
+--
+-- 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 ts, cpu from sched where ts >= 81473797418963 limit 10
diff --git a/test/trace_processor/b120278869_neg_ts_end.sql b/test/trace_processor/b120278869_neg_ts_end.sql
index 3c3d97a..bee5180 100644
--- a/test/trace_processor/b120278869_neg_ts_end.sql
+++ b/test/trace_processor/b120278869_neg_ts_end.sql
@@ -1 +1,16 @@
+--
+-- 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 count(*) from counters where -1 < ts
diff --git a/test/trace_processor/b120487929.sql b/test/trace_processor/b120487929.sql
index 4aa2007..179d324 100644
--- a/test/trace_processor/b120487929.sql
+++ b/test/trace_processor/b120487929.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create view freq_view as
   select
     ts,
diff --git a/test/trace_processor/b120605557.sql b/test/trace_processor/b120605557.sql
index 684fdcf..8af6cd9 100644
--- a/test/trace_processor/b120605557.sql
+++ b/test/trace_processor/b120605557.sql
@@ -1,3 +1,18 @@
+--
+-- 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 count(*)
 from counter
 inner join counter_track on counter_track.id = counter.track_id
diff --git a/test/trace_processor/clock_sync.sql b/test/trace_processor/clock_sync.sql
index 73d5d2a..227767b 100644
--- a/test/trace_processor/clock_sync.sql
+++ b/test/trace_processor/clock_sync.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, cast(value as integer) as int_value
 from counters
 where name like 'gpu_counter%'
\ No newline at end of file
diff --git a/test/trace_processor/counters_group_by_freq.sql b/test/trace_processor/counters_group_by_freq.sql
index 2b8a0bf..2bd1706 100644
--- a/test/trace_processor/counters_group_by_freq.sql
+++ b/test/trace_processor/counters_group_by_freq.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   value,
   sum(dur) as dur_sum
diff --git a/test/trace_processor/counters_where_cpu.sql b/test/trace_processor/counters_where_cpu.sql
index 88fa062..14fea10 100644
--- a/test/trace_processor/counters_where_cpu.sql
+++ b/test/trace_processor/counters_where_cpu.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   ts,
   lead(ts, 1, ts) OVER (PARTITION BY name ORDER BY ts) - ts AS dur,
diff --git a/test/trace_processor/end_reason_eq.sql b/test/trace_processor/end_reason_eq.sql
index 960d731..e56f5ff 100644
--- a/test/trace_processor/end_reason_eq.sql
+++ b/test/trace_processor/end_reason_eq.sql
@@ -1,3 +1,18 @@
+--
+-- 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 end_state, count(*)
 from sched
 where end_state = 'D'
diff --git a/test/trace_processor/end_reason_match.sql b/test/trace_processor/end_reason_match.sql
index bd26668..99ef8f8 100644
--- a/test/trace_processor/end_reason_match.sql
+++ b/test/trace_processor/end_reason_match.sql
@@ -1,3 +1,18 @@
+--
+-- 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 end_state, count(*)
 from sched
 where end_state MATCH 'D'
diff --git a/test/trace_processor/end_reason_neq.sql b/test/trace_processor/end_reason_neq.sql
index 6a0cf42..57e6092 100644
--- a/test/trace_processor/end_reason_neq.sql
+++ b/test/trace_processor/end_reason_neq.sql
@@ -1,3 +1,18 @@
+--
+-- 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 end_state, count(*)
 from sched
 where end_state != 'D'
diff --git a/test/trace_processor/filter_counter.sql b/test/trace_processor/filter_counter.sql
index 427f2d0..e234b77 100644
--- a/test/trace_processor/filter_counter.sql
+++ b/test/trace_processor/filter_counter.sql
@@ -1,3 +1,18 @@
+--
+-- 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 COUNT(*)
 FROM counter
 WHERE
diff --git a/test/trace_processor/filter_row_vector.sql b/test/trace_processor/filter_row_vector.sql
index ef5fbcc..855d40c 100644
--- a/test/trace_processor/filter_row_vector.sql
+++ b/test/trace_processor/filter_row_vector.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts
 FROM counter
 WHERE
diff --git a/test/trace_processor/filter_sched.sql b/test/trace_processor/filter_sched.sql
index 36f56ea..07ff56c 100644
--- a/test/trace_processor/filter_sched.sql
+++ b/test/trace_processor/filter_sched.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, cpu, dur from sched
 where
   cpu = 1 and
diff --git a/test/trace_processor/global_memory_counter.sql b/test/trace_processor/global_memory_counter.sql
index ebada42..fdf24c2 100644
--- a/test/trace_processor/global_memory_counter.sql
+++ b/test/trace_processor/global_memory_counter.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, value, name
 from counter
 inner join counter_track on counter.track_id = counter_track.id
diff --git a/test/trace_processor/gpu_counters.sql b/test/trace_processor/gpu_counters.sql
index 1248732..1d8c1c6 100644
--- a/test/trace_processor/gpu_counters.sql
+++ b/test/trace_processor/gpu_counters.sql
@@ -1,3 +1,18 @@
+--
+-- 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 "ts","value","name","gpu_id","description","unit"
 from counter
 join gpu_counter_track
diff --git a/test/trace_processor/gpu_log.sql b/test/trace_processor/gpu_log.sql
index dd846e3..2e48384 100644
--- a/test/trace_processor/gpu_log.sql
+++ b/test/trace_processor/gpu_log.sql
@@ -1,3 +1,18 @@
+--
+-- 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 scope, track.name as track_name, ts, dur, gpu_slice.name as slice_name,
     key, string_value as value
 from gpu_track
diff --git a/test/trace_processor/gpu_render_stages.sql b/test/trace_processor/gpu_render_stages.sql
index e534e99..978a033 100644
--- a/test/trace_processor/gpu_render_stages.sql
+++ b/test/trace_processor/gpu_render_stages.sql
@@ -1,3 +1,18 @@
+--
+-- 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 track.name AS track_name, ts,dur, gpu_slice.name AS slice_name,
     depth, gpu_slice.arg_set_id, flat_key, string_value, gpu_slice.context_id,
     render_target, submission_id, hw_queue_id
diff --git a/test/trace_processor/graphics_frame_events.sql b/test/trace_processor/graphics_frame_events.sql
index 2c51484..0abcc8d 100644
--- a/test/trace_processor/graphics_frame_events.sql
+++ b/test/trace_processor/graphics_frame_events.sql
@@ -1,3 +1,18 @@
+--
+-- 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 scope, track.name as track_name, ts, dur, gpu_slice.name as slice_name,
     frame_id, key, string_value as layer_name
 from gpu_track
diff --git a/test/trace_processor/heap_graph_object.sql b/test/trace_processor/heap_graph_object.sql
index 2c4866f..234728f 100644
--- a/test/trace_processor/heap_graph_object.sql
+++ b/test/trace_processor/heap_graph_object.sql
@@ -1 +1,16 @@
+--
+-- 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 * from heap_graph_object
diff --git a/test/trace_processor/heap_graph_reference.sql b/test/trace_processor/heap_graph_reference.sql
index e0fe907..f3b6894 100644
--- a/test/trace_processor/heap_graph_reference.sql
+++ b/test/trace_processor/heap_graph_reference.sql
@@ -1 +1,16 @@
+--
+-- 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 * from heap_graph_reference
diff --git a/test/trace_processor/heap_profile_frames.sql b/test/trace_processor/heap_profile_frames.sql
index 9aa5b81..b59602e 100644
--- a/test/trace_processor/heap_profile_frames.sql
+++ b/test/trace_processor/heap_profile_frames.sql
@@ -1 +1,16 @@
+--
+-- 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 name, mapping, rel_pc FROM stack_profile_frame ORDER BY name;
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 9c78fec..4a9db38 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -144,8 +144,10 @@
 heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
 
 # TrackEvent tests.
-track_event_same_tids.py process_tracking.sql track_event_same_tids_threads.out
-track_event_same_tids.py track_event_slices.sql track_event_same_tids_slices.out
+track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
+track_event_same_tids.textproto track_event_slices.sql track_event_same_tids_slices.out
+track_event_typed_args.textproto track_event_slices.sql track_event_typed_args_slices.out
+track_event_typed_args.textproto track_event_args.sql track_event_typed_args_args.out
 
 # Parsing of an html file with systrace data inside
 ../data/systrace.html systrace_html.sql systrace_html.out
diff --git a/test/trace_processor/lmk.sql b/test/trace_processor/lmk.sql
index 8a5de9e..6241040 100644
--- a/test/trace_processor/lmk.sql
+++ b/test/trace_processor/lmk.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, process.pid
 from instants
 inner join process
diff --git a/test/trace_processor/metadata.sql b/test/trace_processor/metadata.sql
index 164675d..46f9e6b 100644
--- a/test/trace_processor/metadata.sql
+++ b/test/trace_processor/metadata.sql
@@ -1 +1,16 @@
+--
+-- 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 name, str_value from metadata order by name;
diff --git a/test/trace_processor/mm_event.sql b/test/trace_processor/mm_event.sql
index 8728f70..5130db6 100644
--- a/test/trace_processor/mm_event.sql
+++ b/test/trace_processor/mm_event.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, name, value, upid
 from counter
 inner join process_counter_track
diff --git a/test/trace_processor/nulls.sql b/test/trace_processor/nulls.sql
index 614fec0..44e5132 100644
--- a/test/trace_processor/nulls.sql
+++ b/test/trace_processor/nulls.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 CREATE TABLE null_test (
   primary_key INTEGER PRIMARY KEY,
   int_nulls INTEGER,
diff --git a/test/trace_processor/oom_query.sql b/test/trace_processor/oom_query.sql
index 8e4d2c5..68c19ac 100644
--- a/test/trace_processor/oom_query.sql
+++ b/test/trace_processor/oom_query.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 /* Create the file RSS table. */
 CREATE VIEW file_rss AS
 SELECT ts,
diff --git a/test/trace_processor/oom_score_poll.sql b/test/trace_processor/oom_score_poll.sql
index 192b991..f22624b 100644
--- a/test/trace_processor/oom_score_poll.sql
+++ b/test/trace_processor/oom_score_poll.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, name, value, upid
 from counter c
 join process_counter_track t
diff --git a/test/trace_processor/power_rail_event.sql b/test/trace_processor/power_rail_event.sql
index 0082ac3..9a1a254 100644
--- a/test/trace_processor/power_rail_event.sql
+++ b/test/trace_processor/power_rail_event.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, value
 from counters
 where name like "power.%"
diff --git a/test/trace_processor/power_rails.sql b/test/trace_processor/power_rails.sql
index 4e884d1..c095608 100644
--- a/test/trace_processor/power_rails.sql
+++ b/test/trace_processor/power_rails.sql
@@ -1,3 +1,18 @@
+--
+-- 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 name, AVG(value), COUNT(*)
 from counters
 where name like "power.%"
diff --git a/test/trace_processor/print_systrace.sql b/test/trace_processor/print_systrace.sql
index ab5d87e..7e834eb 100644
--- a/test/trace_processor/print_systrace.sql
+++ b/test/trace_processor/print_systrace.sql
@@ -1,2 +1,17 @@
+--
+-- 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 to_ftrace(id)
 from raw;
diff --git a/test/trace_processor/process_metadata_matching.sql b/test/trace_processor/process_metadata_matching.sql
index 875d59a..759448e 100644
--- a/test/trace_processor/process_metadata_matching.sql
+++ b/test/trace_processor/process_metadata_matching.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 -- Create so that RUN_METRIC will run without outputting any rows.
 CREATE TABLE TEST_TMP AS
 SELECT RUN_METRIC('android/process_metadata.sql');
diff --git a/test/trace_processor/process_parent_pid.sql b/test/trace_processor/process_parent_pid.sql
index 8a50cc5..a836c92 100644
--- a/test/trace_processor/process_parent_pid.sql
+++ b/test/trace_processor/process_parent_pid.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   child.pid as child_pid,
   parent.pid as parent_pid
diff --git a/test/trace_processor/process_track_slices.sql b/test/trace_processor/process_track_slices.sql
index 33ed9bf..1b9151d 100644
--- a/test/trace_processor/process_track_slices.sql
+++ b/test/trace_processor/process_track_slices.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   ts,
   dur,
diff --git a/test/trace_processor/process_tracking.sql b/test/trace_processor/process_tracking.sql
index 922cb7f..b28859d 100644
--- a/test/trace_processor/process_tracking.sql
+++ b/test/trace_processor/process_tracking.sql
@@ -1,3 +1,18 @@
+--
+-- 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 tid, pid, process.name as pname, thread.name as tname
 from thread
 left join process using(upid)
diff --git a/test/trace_processor/process_tracking_uid.sql b/test/trace_processor/process_tracking_uid.sql
index de06399..fcc590b 100644
--- a/test/trace_processor/process_tracking_uid.sql
+++ b/test/trace_processor/process_tracking_uid.sql
@@ -1,3 +1,18 @@
+--
+-- 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 pid, uid
 from process
 order by pid;
diff --git a/test/trace_processor/sched_slices.sql b/test/trace_processor/sched_slices.sql
index 1e808d5..15c1ec7 100644
--- a/test/trace_processor/sched_slices.sql
+++ b/test/trace_processor/sched_slices.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, cpu, dur, ts_end, end_state, priority, tid, name
 FROM sched JOIN thread ON sched.utid == thread.utid
 ORDER BY cpu, sched.ts ASC;
diff --git a/test/trace_processor/sched_wakeup.sql b/test/trace_processor/sched_wakeup.sql
index 33b4e06..f3c280c 100644
--- a/test/trace_processor/sched_wakeup.sql
+++ b/test/trace_processor/sched_wakeup.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, tid
 from instants
 inner join thread on instants.ref = thread.utid
diff --git a/test/trace_processor/sched_waking_instants.sql b/test/trace_processor/sched_waking_instants.sql
index 55ab59b..15a569b 100644
--- a/test/trace_processor/sched_waking_instants.sql
+++ b/test/trace_processor/sched_waking_instants.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, instants.name, thread.name, thread.tid
 FROM instants
 JOIN thread ON instants.ref = thread.utid
diff --git a/test/trace_processor/sched_waking_raw.sql b/test/trace_processor/sched_waking_raw.sql
index 259e2fe..0c6a755 100644
--- a/test/trace_processor/sched_waking_raw.sql
+++ b/test/trace_processor/sched_waking_raw.sql
@@ -1 +1,16 @@
+--
+-- 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 ts, name, cpu, key, int_value, string_value FROM raw JOIN args ON raw.arg_set_id == args.arg_set_id WHERE name == "sched_waking" ORDER BY cpu ASC, ts ASC;
diff --git a/test/trace_processor/slice_span_join_b118665515.sql b/test/trace_processor/slice_span_join_b118665515.sql
index 85eefce..34bacf0 100644
--- a/test/trace_processor/slice_span_join_b118665515.sql
+++ b/test/trace_processor/slice_span_join_b118665515.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create virtual table window_8 using window;
 
 create virtual table span_8 using span_join(sched PARTITIONED cpu, window_8);
diff --git a/test/trace_processor/smoke.sql b/test/trace_processor/smoke.sql
index a54ba35..c3af84a 100644
--- a/test/trace_processor/smoke.sql
+++ b/test/trace_processor/smoke.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   ts,
   cpu,
diff --git a/test/trace_processor/smoke_counters.sql b/test/trace_processor/smoke_counters.sql
index 407b004..b4dc7ed 100644
--- a/test/trace_processor/smoke_counters.sql
+++ b/test/trace_processor/smoke_counters.sql
@@ -1,4 +1,19 @@
-select 
+--
+-- 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
   ts,
   value,
   name
diff --git a/test/trace_processor/smoke_instants.sql b/test/trace_processor/smoke_instants.sql
index 6b33613..b57a531 100644
--- a/test/trace_processor/smoke_instants.sql
+++ b/test/trace_processor/smoke_instants.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   ts,
   name,
diff --git a/test/trace_processor/smoke_slices.sql b/test/trace_processor/smoke_slices.sql
index 0c6b396..f876c41 100644
--- a/test/trace_processor/smoke_slices.sql
+++ b/test/trace_processor/smoke_slices.sql
@@ -1,3 +1,18 @@
+--
+-- 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 track.type as type, depth, count(*) as count
 from slice
 inner join track on slice.track_id = track.id
diff --git a/test/trace_processor/smoke_window.sql b/test/trace_processor/smoke_window.sql
index 3eb1ca6..7fe479f 100644
--- a/test/trace_processor/smoke_window.sql
+++ b/test/trace_processor/smoke_window.sql
@@ -1 +1,16 @@
+--
+-- 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 * from window;
diff --git a/test/trace_processor/span_join_unordered_cols.sql b/test/trace_processor/span_join_unordered_cols.sql
index c47380c..5cc1645 100644
--- a/test/trace_processor/span_join_unordered_cols.sql
+++ b/test/trace_processor/span_join_unordered_cols.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   a1 STRING,
   a2 BIG INT,
diff --git a/test/trace_processor/span_join_unordered_cols_reverse.sql b/test/trace_processor/span_join_unordered_cols_reverse.sql
index bf5a782..e533e0d 100644
--- a/test/trace_processor/span_join_unordered_cols_reverse.sql
+++ b/test/trace_processor/span_join_unordered_cols_reverse.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   a1 STRING,
   a2 BIG INT,
diff --git a/test/trace_processor/span_join_zero_negative_dur.sql b/test/trace_processor/span_join_zero_negative_dur.sql
index 246ebcf..f3cece8 100644
--- a/test/trace_processor/span_join_zero_negative_dur.sql
+++ b/test/trace_processor/span_join_zero_negative_dur.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
diff --git a/test/trace_processor/span_left_join.sql b/test/trace_processor/span_left_join.sql
index 2295fcf..7e8f23e 100644
--- a/test/trace_processor/span_left_join.sql
+++ b/test/trace_processor/span_left_join.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
@@ -57,7 +72,7 @@
 -- Insert a row into t2 which intersects the first row of partition 5.
 INSERT INTO t2(ts, dur, part, b) VALUES (190, 20, 5, 2222);
 
-create virtual table sp using span_left_join(t1 PARTITIONED part, 
+create virtual table sp using span_left_join(t1 PARTITIONED part,
                                              t2 PARTITIONED part);
 
 select * from sp;
diff --git a/test/trace_processor/span_left_join_empty_right.sql b/test/trace_processor/span_left_join_empty_right.sql
index 011fb5f..3502780 100644
--- a/test/trace_processor/span_left_join_empty_right.sql
+++ b/test/trace_processor/span_left_join_empty_right.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
@@ -16,7 +31,7 @@
 VALUES
 (500, 500, 100);
 
-create virtual table sp using span_left_join(t1 PARTITIONED part, 
+create virtual table sp using span_left_join(t1 PARTITIONED part,
                                              t2 PARTITIONED part);
 
 select * from sp;
diff --git a/test/trace_processor/span_left_join_left_partitioned.sql b/test/trace_processor/span_left_join_left_partitioned.sql
index 6a28297..e5a6319 100644
--- a/test/trace_processor/span_left_join_left_partitioned.sql
+++ b/test/trace_processor/span_left_join_left_partitioned.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
diff --git a/test/trace_processor/span_left_join_left_unpartitioned.sql b/test/trace_processor/span_left_join_left_unpartitioned.sql
index 3e08eba..f7228a3 100644
--- a/test/trace_processor/span_left_join_left_unpartitioned.sql
+++ b/test/trace_processor/span_left_join_left_unpartitioned.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
diff --git a/test/trace_processor/span_left_join_unpartitioned.sql b/test/trace_processor/span_left_join_unpartitioned.sql
index 855f5e1..a0045e8 100644
--- a/test/trace_processor/span_left_join_unpartitioned.sql
+++ b/test/trace_processor/span_left_join_unpartitioned.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
diff --git a/test/trace_processor/span_outer_join.sql b/test/trace_processor/span_outer_join.sql
index b11b850..294e863 100644
--- a/test/trace_processor/span_outer_join.sql
+++ b/test/trace_processor/span_outer_join.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
@@ -57,7 +72,7 @@
 -- Insert a row into t2 which intersects the first row of partition 5.
 INSERT INTO t2(ts, dur, part, b) VALUES (190, 20, 5, 2222);
 
-create virtual table sp using span_outer_join(t1 PARTITIONED part, 
+create virtual table sp using span_outer_join(t1 PARTITIONED part,
                                               t2 PARTITIONED part);
 
 select * from sp;
diff --git a/test/trace_processor/span_outer_join_empty.sql b/test/trace_processor/span_outer_join_empty.sql
index 7a07268..c6db65c 100644
--- a/test/trace_processor/span_outer_join_empty.sql
+++ b/test/trace_processor/span_outer_join_empty.sql
@@ -1,3 +1,18 @@
+--
+-- 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.
+--
 create table t1(
   ts BIG INT,
   dur BIG INT,
@@ -18,7 +33,7 @@
 
 -- t2 is empty.
 
-create virtual table sp using span_outer_join(t1 PARTITIONED part, 
+create virtual table sp using span_outer_join(t1 PARTITIONED part,
                                              t2 PARTITIONED part);
 
 select * from sp;
diff --git a/test/trace_processor/stats.sql b/test/trace_processor/stats.sql
index 1c03b93..5962ae5 100644
--- a/test/trace_processor/stats.sql
+++ b/test/trace_processor/stats.sql
@@ -1 +1,16 @@
+--
+-- 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 * from stats where name like 'ftrace_cpu_%' or name like 'traced_buf_%';
\ No newline at end of file
diff --git a/test/trace_processor/sys.sql b/test/trace_processor/sys.sql
index 20286f9..7d42be3 100644
--- a/test/trace_processor/sys.sql
+++ b/test/trace_processor/sys.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts, dur, name
 from slices
 limit 10
diff --git a/test/trace_processor/systrace_html.sql b/test/trace_processor/systrace_html.sql
index 2251793..55236aa 100644
--- a/test/trace_processor/systrace_html.sql
+++ b/test/trace_processor/systrace_html.sql
@@ -1 +1,16 @@
+--
+-- 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 ts, cpu, dur, ts_end, utid, end_state, priority, upid, name, tid  from sched join thread using(utid) order by ts
\ No newline at end of file
diff --git a/test/trace_processor/thread_cpu_time.sql b/test/trace_processor/thread_cpu_time.sql
index b487fe0..887af35 100644
--- a/test/trace_processor/thread_cpu_time.sql
+++ b/test/trace_processor/thread_cpu_time.sql
@@ -1,3 +1,18 @@
+--
+-- 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
   tid,
   pid,
diff --git a/test/trace_processor/track_event_args.sql b/test/trace_processor/track_event_args.sql
new file mode 100644
index 0000000..7b7b978
--- /dev/null
+++ b/test/trace_processor/track_event_args.sql
@@ -0,0 +1,16 @@
+--
+-- 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 arg_set_id, flat_key, key, int_value, string_value from args where arg_set_id >= 2 order by arg_set_id, key asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_same_tids.py b/test/trace_processor/track_event_same_tids.py
deleted file mode 100644
index c838d6d..0000000
--- a/test/trace_processor/track_event_same_tids.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Chrome renderer processes don't know their "true" tids on some platforms.
-# Instead, they each write tids that start at 1 - which means, the same tids are
-# used in multiple different processes at the same time. This trace replicates
-# such a situation.
-
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=1, pid=5, tid=1, thread_name="t1", inc_state_cleared=True)
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=2, pid=10, tid=1, thread_name="t2")
-
-trace.add_track_event(
-    ps=1, ts=1000, track_uuid=1, cat="cat", name="name1", type=3)
-trace.add_track_event(
-    ps=1, ts=2000, track_uuid=2, cat="cat", name="name2", type=3)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/track_event_same_tids.textproto b/test/trace_processor/track_event_same_tids.textproto
new file mode 100644
index 0000000..d8d7ca2
--- /dev/null
+++ b/test/trace_processor/track_event_same_tids.textproto
@@ -0,0 +1,45 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 2
+    thread {
+      pid: 10
+      tid: 1
+      thread_name: "t2"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name1"
+    type: 3
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    track_uuid: 2
+    categories: "cat"
+    name: "name2"
+    type: 3
+  }
+}
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
index f66b8ce..350acf9 100644
--- a/test/trace_processor/track_event_same_tids_slices.out
+++ b/test/trace_processor/track_event_same_tids_slices.out
@@ -1,3 +1,3 @@
-"ts","dur","category","name"
-1000,0,"cat","name1"
-2000,0,"cat","name2"
+"ts","dur","category","name","arg_set_id"
+1000,0,"cat","name1",0
+2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
index b69c990..68772b4 100644
--- a/test/trace_processor/track_event_slices.sql
+++ b/test/trace_processor/track_event_slices.sql
@@ -1 +1,16 @@
-select ts, dur, category, name from slice order by ts asc;
\ No newline at end of file
+--
+-- 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 ts, dur, category, name, arg_set_id from slice order by ts asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_typed_args.textproto b/test/trace_processor/track_event_typed_args.textproto
new file mode 100644
index 0000000..3c49c21
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args.textproto
@@ -0,0 +1,53 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name1"
+    type: 3
+    chrome_user_event {
+      action: "NewTab"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name2"
+    type: 3
+    chrome_legacy_ipc {
+      message_class: 1
+      message_line: 10
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name3"
+    type: 3
+    chrome_keyed_service {
+      name: "MediaRouter"
+    }
+  }
+}
diff --git a/test/trace_processor/track_event_typed_args_args.out b/test/trace_processor/track_event_typed_args_args.out
new file mode 100644
index 0000000..f08c63e
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_args.out
@@ -0,0 +1,5 @@
+"arg_set_id","flat_key","key","int_value","string_value"
+2,"user_event.action","user_event.action","[NULL]","NewTab"
+3,"legacy_ipc.class","legacy_ipc.class","[NULL]","AUTOMATION"
+3,"legacy_ipc.line","legacy_ipc.line",10,"[NULL]"
+4,"keyed_service.name","keyed_service.name","[NULL]","MediaRouter"
diff --git a/test/trace_processor/track_event_typed_args_slices.out b/test/trace_processor/track_event_typed_args_slices.out
new file mode 100644
index 0000000..d280266
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_slices.out
@@ -0,0 +1,4 @@
+"ts","dur","category","name","arg_set_id"
+1000,0,"cat","name1",2
+2000,0,"cat","name2",3
+3000,0,"cat","name3",4
diff --git a/test/trace_processor/ts_desc_filter.sql b/test/trace_processor/ts_desc_filter.sql
index 8bf5f24..6f49a98 100644
--- a/test/trace_processor/ts_desc_filter.sql
+++ b/test/trace_processor/ts_desc_filter.sql
@@ -1,3 +1,18 @@
+--
+-- 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 ts
 from sched
 inner join thread using(utid)
diff --git a/tools/add_test_trace.sh b/tools/add_test_trace.sh
index 976955a..f91551d 100755
--- a/tools/add_test_trace.sh
+++ b/tools/add_test_trace.sh
@@ -1,4 +1,18 @@
 #!/bin/bash
+# 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.
+
 set -e
 
 echo ""
diff --git a/tools/add_tp_diff_test.sh b/tools/add_tp_diff_test.sh
index 92a9ead..196fd5f 100755
--- a/tools/add_tp_diff_test.sh
+++ b/tools/add_tp_diff_test.sh
@@ -1,4 +1,18 @@
 #!/bin/bash
+# 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.
+
 set -e
 
 read -p "Name of SQL file to create (in test/trace_processor): " sqlfile
diff --git a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
index 65f0f5f..4339e47 100644
--- a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
@@ -31,6 +31,23 @@
   for (int i = 0; i < one_of_event->field_count(); i++)
     max_id = std::max(max_id, one_of_event->field(i)->number());
 
+  *fout << R"(/*
+ * Copyright (C) 2017 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.
+ */
+
+ )";
   *fout << "// Autogenerated by:\n";
   *fout << std::string("// ") + __FILE__ + "\n";
   *fout << "// Do not edit.\n";
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index e6c9ebd..b8cc7cb 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -31,8 +31,30 @@
 
 namespace perfetto {
 
-using base::StartsWith;
+namespace {
+
+const char kCopyrightHeader[] = R"(/*
+ * Copyright (C) 2017 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.
+ */
+
+ )";
+
+}  // namespace
+
 using base::Contains;
+using base::StartsWith;
 
 std::string EventNameToProtoFieldName(const std::string& name) {
   return (name == "0") ? "zero" : name;
@@ -89,6 +111,7 @@
 void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
                               const std::set<std::string>& groups,
                               std::ostream* fout) {
+  *fout << kCopyrightHeader;
   *fout << "// Autogenerated by:\n";
   *fout << std::string("// ") + __FILE__ + "\n";
   *fout << "// Do not edit.\n\n";
@@ -193,7 +216,8 @@
 // This will generate the event_info.cc file for the whitelisted protos.
 void GenerateEventInfo(const std::vector<std::string>& events_info,
                        std::ostream* fout) {
-  std::string s = "// Autogenerated by:\n";
+  std::string s = kCopyrightHeader;
+  s += "// Autogenerated by:\n";
   s += std::string("// ") + __FILE__ + "\n";
   s += "// Do not edit.\n";
   s += R"(
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index 8bba861..e980379 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -100,7 +100,22 @@
     include_guard = target.replace('/', '_').replace('.', '_').upper() + '_'
 
     with open(os.path.join(ROOT_DIR, target), 'wb') as f:
-      f.write("""
+      f.write("""/*
+ * 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 {include_guard}
 #define {include_guard}
 
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 3d807c7..52bcf76 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -96,6 +96,9 @@
     '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/chrome_keyed_service.proto',
+    'protos/perfetto/trace/track_event/chrome_legacy_ipc.proto',
+    'protos/perfetto/trace/track_event/chrome_user_event.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/tools/protoprofile/main.cc b/tools/protoprofile/main.cc
index 8fe6f24..a3be2c9 100644
--- a/tools/protoprofile/main.cc
+++ b/tools/protoprofile/main.cc
@@ -1,3 +1,19 @@
+/*
+ * 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 <algorithm>
 #include <vector>
 
diff --git a/ui/jest.headless.config.js b/ui/jest.headless.config.js
index edb6a99..e2487b8 100644
--- a/ui/jest.headless.config.js
+++ b/ui/jest.headless.config.js
@@ -1,3 +1,17 @@
+// 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.
+
 module.exports = {
     "transform": {},
     "testRegex": ".*_headlesstest.js$",
diff --git a/ui/jest.jsdom.config.js b/ui/jest.jsdom.config.js
index eeb695f..51c9ede 100644
--- a/ui/jest.jsdom.config.js
+++ b/ui/jest.jsdom.config.js
@@ -1,3 +1,17 @@
+// 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.
+
 module.exports = {
     "transform": {},
     "testRegex": "_jsdomtest.js$",
diff --git a/ui/jest.unit.config.js b/ui/jest.unit.config.js
index 2dfb83a..a58dcbf 100644
--- a/ui/jest.unit.config.js
+++ b/ui/jest.unit.config.js
@@ -1,3 +1,17 @@
+// 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.
+
 module.exports = {
     "transform": {},
     "testRegex": "_unittest.js$",
diff --git a/ui/rollup.config.js b/ui/rollup.config.js
index e4795c4..d6389d2 100644
--- a/ui/rollup.config.js
+++ b/ui/rollup.config.js
@@ -1,3 +1,17 @@
+// 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.
+
 import commonjs from 'rollup-plugin-commonjs';
 import nodeResolve from 'rollup-plugin-node-resolve';
 
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 85720b8..cfccc3e 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -309,6 +309,10 @@
           box-shadow: 0 -4px 2px -1px hsl(213, 40%, 50%) inset;
         }
 
+        &.selected {
+          background-color: #ebeef9;
+        }
+
         h1 {
             grid-area: title;
             margin: 0;
@@ -565,6 +569,9 @@
     &.flash {
       background-color: #ffe263;
     }
+    &.selected {
+      background-color: #ebeef9;
+    }
   }
 }
 
diff --git a/ui/src/base/utils/index-browser.js b/ui/src/base/utils/index-browser.js
index 51a6d05..491c8f2 100644
--- a/ui/src/base/utils/index-browser.js
+++ b/ui/src/base/utils/index-browser.js
@@ -1,3 +1,16 @@
+// 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.
 
 export const _TextDecoder = TextDecoder;
 export const _TextEncoder = TextEncoder;
\ No newline at end of file
diff --git a/ui/src/base/utils/index.js b/ui/src/base/utils/index.js
index ed27974..534c91a 100644
--- a/ui/src/base/utils/index.js
+++ b/ui/src/base/utils/index.js
@@ -1,3 +1,16 @@
+// 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.
 
 const util = require('util');
 
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 9b8c082..c5f7f63 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -28,9 +28,9 @@
   RecordConfig,
   RecordingTarget,
   SCROLLING_TRACK_GROUP,
-  SelectedTimeRange,
   State,
   Status,
+  TimestampedAreaSelection,
   TraceSource,
   TraceTime,
   TrackState,
@@ -525,8 +525,8 @@
     state.frontendLocalState.omniboxState = args;
   },
 
-  selectTimeRange(state: StateDraft, args: SelectedTimeRange): void {
-    state.frontendLocalState.selectedTimeRange = args;
+  selectArea(state: StateDraft, args: TimestampedAreaSelection): void {
+    state.frontendLocalState.selectedArea = args;
   },
 
   setVisibleTraceTime(state: StateDraft, args: VisibleState): void {
diff --git a/ui/src/common/flamegraph_unittest.ts b/ui/src/common/flamegraph_unittest.ts
index d9015a8..fc19250 100644
--- a/ui/src/common/flamegraph_unittest.ts
+++ b/ui/src/common/flamegraph_unittest.ts
@@ -1,3 +1,17 @@
+// 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.
+
 import {mergeCallsites} from './flamegraph_util';
 import {CallsiteInfo} from './state';
 
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 74ca488..cf9fc43 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -29,8 +29,15 @@
 export type VisibleState =
     Timestamped<{startSec: number; endSec: number; resolution: number;}>;
 
-export type SelectedTimeRange =
-    Timestamped<{startSec?: number; endSec?: number;}>;
+export type TimestampedAreaSelection = Timestamped<AreaSelection>;
+export interface AreaSelection {
+  area?: Area;
+}
+export interface Area {
+  startSec: number;
+  endSec: number;
+  tracks: string[];
+}
 
 export const MAX_TIME = 180;
 
@@ -118,7 +125,7 @@
 export interface FrontendLocalState {
   omniboxState: OmniboxState;
   visibleState: VisibleState;
-  selectedTimeRange: SelectedTimeRange;
+  selectedArea: TimestampedAreaSelection;
 }
 
 export interface Status {
@@ -448,7 +455,7 @@
         lastUpdate: 0,
         resolution: 0,
       },
-      selectedTimeRange: {
+      selectedArea: {
         lastUpdate: 0,
       },
     },
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index a20776c..4888431 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -1,3 +1,17 @@
+// 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.
+
 import {_TextDecoder, _TextEncoder} from 'custom_utils';
 
 import {Adb, AdbMsg, AdbStream, CmdType} from './adb_interfaces';
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index 1dde45d..f8b51b3 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -72,8 +72,14 @@
       if (iter > 100) throw new Error('Controllers are stuck in a livelock');
       const actions = this._queuedActions;
       this._queuedActions = new Array<DeferredAction>();
+
       for (const action of actions) {
-        patches.push(...this.applyAction(action));
+        const originalLength = patches.length;
+        const morePatches = this.applyAction(action);
+        patches.length += morePatches.length;
+        for (let i = 0; i < morePatches.length; ++i) {
+          patches[i + originalLength] = morePatches[i];
+        }
       }
       this._runningControllers = true;
       try {
@@ -109,7 +115,11 @@
           (StateActions as any)[action.type](draft, action.args);
         },
         (morePatches, _) => {
-          patches.push(...morePatches);
+          const originalLength = patches.length;
+          patches.length += morePatches.length;
+          for (let i = 0; i < morePatches.length; ++i) {
+            patches[i + originalLength] = morePatches[i];
+          }
         });
     return patches;
   }
diff --git a/ui/src/controller/record_controller_interfaces.ts b/ui/src/controller/record_controller_interfaces.ts
index afd1d8b..8c336e0 100644
--- a/ui/src/controller/record_controller_interfaces.ts
+++ b/ui/src/controller/record_controller_interfaces.ts
@@ -1,3 +1,17 @@
+// 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.
+
 import {ConsumerPortResponse} from './consumer_port_types';
 
 export type ConsumerPortCallback = (_: ConsumerPortResponse) => void;
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index ffa27e1..1afdea3 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -534,9 +534,13 @@
           pid,
           thread.name as threadName,
           process.name as processName,
-          total_dur as totalDur
+          total_dur as totalDur,
+          ifnull(has_sched, false) as hasSched
         from
           thread
+          left join (select utid, count(1), true as has_sched
+              from sched group by utid
+          ) using(utid)
           left join process using(upid)
           left join (select upid, sum(dur) as total_dur
               from sched join thread using(utid)
@@ -558,6 +562,7 @@
            threadName: STR_NULL,
            processName: STR_NULL,
            totalDur: NUM_NULL,
+           hasSched: NUM,
          })) {
       const utid = row.utid;
       const tid = row.tid;
@@ -566,9 +571,7 @@
       const threadName = row.threadName;
       const processName = row.processName;
       const hasSchedEvents = !!row.totalDur;
-      const threadSched =
-          await engine.query(`select count(1) from sched where utid = ${utid}`);
-      const threadHasSched = threadSched.columns[0].longValues![0] > 0;
+      const threadHasSched = !!row.hasSched;
 
       const threadTrack =
           utid === null ? undefined : utidToThreadTrack.get(utid);
diff --git a/ui/src/frontend/track_constants.ts b/ui/src/frontend/css_constants.ts
similarity index 82%
rename from ui/src/frontend/track_constants.ts
rename to ui/src/frontend/css_constants.ts
index 63b51f8..a443306 100644
--- a/ui/src/frontend/track_constants.ts
+++ b/ui/src/frontend/css_constants.ts
@@ -33,5 +33,13 @@
   return readCssVarSlow('--track-border-color', '#ffc0cb');
 }
 
+function getTopbarHeight(): number {
+  const width = readCssVarSlow('--topbar-height', '48px');
+  const match = width.match(/^\W*(\d+)px$/);
+  if (!match) throw Error(`Could not parse topbar height as number (${width})`);
+  return Number(match[1]);
+}
+
 export const TRACK_SHELL_WIDTH = getTrackShellWidth();
 export const TRACK_BORDER_COLOR = getTrackBorderColor();
+export const TOPBAR_HEIGHT = getTopbarHeight();
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 8ff4a96..74eff69 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -202,8 +202,7 @@
       detailsPanels.set('android_logs', m(LogPanel, {}));
     }
 
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
+    if (globals.frontendLocalState.selectedArea.area !== undefined) {
       detailsPanels.set('time_range', m(AggregationPanel));
     }
 
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 710c767..aa3d489 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -17,8 +17,8 @@
 import {
   FrontendLocalState as FrontendState,
   OmniboxState,
-  SelectedTimeRange,
   Timestamped,
+  TimestampedAreaSelection,
   VisibleState,
 } from '../common/state';
 import {TimeSpan} from '../common/time';
@@ -27,6 +27,11 @@
 import {globals} from './globals';
 import {TimeScale} from './time_scale';
 
+interface Range {
+  start?: number;
+  end?: number;
+}
+
 function chooseLatest<T extends Timestamped<{}>>(current: T, next: T): T {
   if (next !== current && next.lastUpdate > current.lastUpdate) {
     return next;
@@ -94,6 +99,8 @@
   showNotePreview = false;
   localOnlyMode = false;
   sidebarVisible = true;
+  // This is used to calculate the tracks within a Y range for area selection.
+  areaY: Range = {};
   visibleTracks = new Set<string>();
   prevVisibleTracks = new Set<string>();
   searchIndex = -1;
@@ -115,7 +122,7 @@
     resolution: 1,
   };
 
-  private _selectedTimeRange: SelectedTimeRange = {
+  private _selectedArea: TimestampedAreaSelection = {
     lastUpdate: 0,
   };
 
@@ -202,38 +209,39 @@
   mergeState(state: FrontendState): void {
     this._omniboxState = chooseLatest(this._omniboxState, state.omniboxState);
     this._visibleState = chooseLatest(this._visibleState, state.visibleState);
-    this._selectedTimeRange =
-        chooseLatest(this._selectedTimeRange, state.selectedTimeRange);
+    this._selectedArea = chooseLatest(this._selectedArea, state.selectedArea);
     if (this._visibleState === state.visibleState) {
       this.updateLocalTime(
           new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
     }
   }
 
-  private selectTimeRangeDebounced = debounce(() => {
-    globals.dispatch(Actions.selectTimeRange(this._selectedTimeRange));
+  private selectAreaDebounced = debounce(() => {
+    globals.dispatch(Actions.selectArea(this._selectedArea));
   }, 20);
 
-  selectTimeRange(startSec: number, endSec: number) {
-    this._selectedTimeRange = {startSec, endSec, lastUpdate: Date.now() / 1000};
-    this.selectTimeRangeDebounced();
+
+  selectArea(
+      startSec: number, endSec: number,
+      tracks = this._selectedArea.area ? this._selectedArea.area.tracks : []) {
+    this._selectedArea = {
+      area: {startSec, endSec, tracks},
+      lastUpdate: Date.now() / 1000
+    };
+    this.selectAreaDebounced();
     globals.frontendLocalState.currentTab = 'time_range';
     globals.rafScheduler.scheduleFullRedraw();
   }
 
-  removeTimeRange() {
-    this._selectedTimeRange = {
-      startSec: undefined,
-      endSec: undefined,
-      lastUpdate: Date.now() / 1000
-    };
-    this.selectTimeRangeDebounced();
+  deselectArea() {
+    this._selectedArea = {lastUpdate: Date.now() / 1000};
+    this.selectAreaDebounced();
     globals.frontendLocalState.currentTab = undefined;
     globals.rafScheduler.scheduleFullRedraw();
   }
 
-  get selectedTimeRange(): SelectedTimeRange {
-    return this._selectedTimeRange;
+  get selectedArea(): TimestampedAreaSelection {
+    return this._selectedArea;
   }
 
   private setOmniboxDebounced = debounce(() => {
diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts
index b7a3c5a..b61729e 100644
--- a/ui/src/frontend/gridline_helper.ts
+++ b/ui/src/frontend/gridline_helper.ts
@@ -14,8 +14,8 @@
 
 import {TimeSpan} from '../common/time';
 
+import {TRACK_BORDER_COLOR, TRACK_SHELL_WIDTH} from './css_constants';
 import {TimeScale} from './time_scale';
-import {TRACK_BORDER_COLOR, TRACK_SHELL_WIDTH} from './track_constants';
 
 export const DESIRED_PX_PER_STEP = 80;
 
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 3a8cdc7..3132234 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -79,8 +79,12 @@
 
 function selectSliceSpan() {
   const range = findTimeRangeOfSelection();
-  if (range.startTs !== -1 && range.endTs !== -1) {
-    globals.frontendLocalState.selectTimeRange(range.startTs, range.endTs);
+  if (range.startTs !== -1 && range.endTs !== -1 &&
+      globals.state.currentSelection) {
+    const tracks = globals.state.currentSelection.trackId ?
+        [globals.state.currentSelection.trackId] :
+        [];
+    globals.frontendLocalState.selectArea(range.startTs, range.endTs, tracks);
   }
 }
 
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 3edb401..9400990 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -17,11 +17,11 @@
 import {Actions} from '../common/actions';
 import {timeToString} from '../common/time';
 
+import {randomColor} from './colorizer';
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {gridlines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
-import {randomColor} from './colorizer';
 
 const FLAG_WIDTH = 16;
 const MOVIE_WIDTH = 16;
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index bd01e9b..215e8da 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -18,11 +18,11 @@
 import {TimeSpan, timeToString} from '../common/time';
 
 import {hueForCpu} from './colorizer';
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {DragGestureHandler} from './drag_gesture_handler';
 import {globals} from './globals';
 import {Panel, PanelSize} from './panel';
 import {TimeScale} from './time_scale';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 export class OverviewTimelinePanel extends Panel {
   private width = 0;
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index e771abb..9d2bda1 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -13,10 +13,10 @@
 // limitations under the License.
 
 import {Animation} from './animation';
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {DragGestureHandler} from './drag_gesture_handler';
 import {globals} from './globals';
 import {handleKey} from './keyboard_event_handler';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 // When first starting to pan or zoom, move at least this many units.
 const INITIAL_PAN_STEP_PX = 50;
@@ -81,7 +81,6 @@
   private boundOnKeyDown = this.onKeyDown.bind(this);
   private boundOnKeyUp = this.onKeyUp.bind(this);
   private shiftDown = false;
-  private dragStartPx = -1;
   private panning: Pan = Pan.None;
   private panOffsetPx = 0;
   private targetPanOffsetPx = 0;
@@ -97,8 +96,8 @@
   private onZoomed: (zoomPositionPx: number, zoomRatio: number) => void;
   private shouldDrag: (currentPx: number) => boolean;
   private onDrag:
-      (dragStartPx: number, prevPx: number, currentPx: number,
-       editing: boolean) => void;
+      (dragStartX: number, dragStartY: number, prevX: number, currentX: number,
+       currentY: number, editing: boolean) => void;
 
   constructor(
       {element, contentOffsetX, onPanned, onZoomed, shouldDrag, onDrag}: {
@@ -108,8 +107,8 @@
         onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
         shouldDrag: (currentPx: number) => boolean,
         onDrag:
-            (dragStartPx: number, prevPx: number, currentPx: number,
-             editing: boolean) => void,
+            (dragStartX: number, dragStartY: number, prevX: number,
+             currentX: number, currentY: number, editing: boolean) => void,
       }) {
     this.element = element;
     this.contentOffsetX = contentOffsetX;
@@ -123,23 +122,26 @@
     this.element.addEventListener('mousemove', this.boundOnMouseMove);
     this.element.addEventListener('wheel', this.boundOnWheel, {passive: true});
 
-    let lastX = -1;
+    let prevX = -1;
+    let dragStartX = -1;
+    let dragStartY = -1;
     let drag = false;
     new DragGestureHandler(
         this.element,
-        x => {
+        (x, y) => {
           // If we started our drag on a time range boundary or shift is down
           // then we are drag selecting rather than panning.
           if (drag || this.shiftDown) {
-            this.onDrag(this.dragStartPx, lastX, x, !this.shiftDown);
+            this.onDrag(dragStartX, dragStartY, prevX, x, y, !this.shiftDown);
           } else {
-            this.onPanned(lastX - x);
+            this.onPanned(prevX - x);
           }
-          lastX = x;
+          prevX = x;
         },
-        x => {
-          lastX = x;
-          this.dragStartPx = x;
+        (x, y) => {
+          prevX = x;
+          dragStartX = x;
+          dragStartY = y;
           drag = this.shouldDrag(x);
           // Set the cursor style based on where the cursor is when the drag
           // starts.
@@ -153,7 +155,8 @@
           // Reset the cursor now the drag has ended.
           this.element.style.cursor =
               this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
-          this.dragStartPx = -1;
+          dragStartX = -1;
+          dragStartY = -1;
         });
   }
 
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index d040eea..9d2eaa5 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -13,9 +13,11 @@
 // limitations under the License.
 
 import * as m from 'mithril';
+import {TimestampedAreaSelection} from 'src/common/state';
 
 import {assertExists, assertTrue} from '../base/logging';
 
+import {TOPBAR_HEIGHT, TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {isPanelVNode, Panel, PanelSize} from './panel';
 import {
@@ -25,7 +27,6 @@
   RunningStatistics,
   runningStatStr
 } from './perf';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 /**
  * If the panel container scrolls, the backing canvas height is
@@ -37,20 +38,28 @@
 // tslint:disable-next-line:no-any
 export type AnyAttrsVnode = m.Vnode<any, {}>;
 
-interface Attrs {
+export interface Attrs {
   panels: AnyAttrsVnode[];
   doesScroll: boolean;
   kind: 'TRACKS'|'OVERVIEW'|'DETAILS';
 }
 
+interface PanelPosition {
+  height: number;
+  width: number;
+  x: number;
+  y: number;
+}
+
 export class PanelContainer implements m.ClassComponent<Attrs> {
   // These values are updated with proper values in oncreate.
   private parentWidth = 0;
   private parentHeight = 0;
   private scrollTop = 0;
-  private panelHeights: number[] = [];
+  private panelPositions: PanelPosition[] = [];
   private totalPanelHeight = 0;
   private canvasHeight = 0;
+  private prevAreaSelection?: TimestampedAreaSelection;
 
   private panelPerfStats = new WeakMap<Panel, RunningStatistics>();
   private perfStats = {
@@ -74,6 +83,63 @@
     return this.attrs.doesScroll ? SCROLLING_CANVAS_OVERDRAW_FACTOR : 1;
   }
 
+  getPanelsInRegion(startX: number, endX: number, startY: number, endY: number):
+      AnyAttrsVnode[] {
+    const minX = Math.min(startX, endX);
+    const maxX = Math.max(startX, endX);
+    const minY = Math.min(startY, endY);
+    const maxY = Math.max(startY, endY);
+    const panels: AnyAttrsVnode[] = [];
+    for (let i = 0; i < this.panelPositions.length; i++) {
+      const pos = this.panelPositions[i];
+      const realPosX = pos.x - TRACK_SHELL_WIDTH;
+      if (realPosX + pos.width >= minX && realPosX <= maxX &&
+          pos.y + pos.height >= minY && pos.y <= maxY) {
+        panels.push(this.attrs.panels[i]);
+      }
+    }
+    return panels;
+  }
+
+  handleAreaSelection() {
+    const selection = globals.frontendLocalState.selectedArea;
+    const area = selection.area;
+    if ((this.prevAreaSelection &&
+         this.prevAreaSelection.lastUpdate >= selection.lastUpdate) ||
+        area === undefined ||
+        globals.frontendLocalState.areaY.start === undefined ||
+        globals.frontendLocalState.areaY.end === undefined) {
+      return;
+    }
+    // The Y value is given from the top of the pan and zoom region, we want it
+    // from the top of the panel container. The parent offset corrects that.
+    const panels = this.getPanelsInRegion(
+        globals.frontendLocalState.timeScale.timeToPx(area.startSec),
+        globals.frontendLocalState.timeScale.timeToPx(area.endSec),
+        globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT,
+        globals.frontendLocalState.areaY.end + TOPBAR_HEIGHT);
+    // Get the track ids from the panels.
+    const tracks = [];
+    for (const panel of panels) {
+      if (panel.attrs.id !== undefined) {
+        tracks.push(panel.attrs.id);
+        continue;
+      }
+      if (panel.attrs.trackGroupId !== undefined) {
+        const trackGroup = globals.state.trackGroups[panel.attrs.trackGroupId];
+        // Only select a track group and all child tracks if it is closed.
+        if (trackGroup.collapsed) {
+          tracks.push(panel.attrs.trackGroupId);
+          for (const track of trackGroup.tracks) {
+            tracks.push(track);
+          }
+        }
+      }
+    }
+    globals.frontendLocalState.selectArea(area.startSec, area.endSec, tracks);
+    this.prevAreaSelection = globals.frontendLocalState.selectedArea;
+  }
+
   constructor(vnode: m.CVnode<Attrs>) {
     this.attrs = vnode.attrs;
     this.canvasRedrawer = () => this.redrawCanvas();
@@ -91,11 +157,7 @@
     }
     this.ctx = ctx;
 
-    const clientRect =
-        assertExists(vnodeDom.dom.parentElement).getBoundingClientRect();
-    this.parentWidth = clientRect.width;
-    this.parentHeight = clientRect.height;
-
+    this.readParentSizeFromDom(vnodeDom.dom);
     this.readPanelHeightsFromDom(vnodeDom.dom);
 
     this.updateCanvasDimensions();
@@ -152,7 +214,6 @@
   onupdate(vnodeDom: m.CVnodeDOM<Attrs>) {
     const totalPanelHeightChanged = this.readPanelHeightsFromDom(vnodeDom.dom);
     const parentSizeChanged = this.readParentSizeFromDom(vnodeDom.dom);
-
     const canvasSizeShouldChange =
         parentSizeChanged || !this.attrs.doesScroll && totalPanelHeightChanged;
     if (canvasSizeShouldChange) {
@@ -210,15 +271,16 @@
    */
   private readPanelHeightsFromDom(dom: Element): boolean {
     const prevHeight = this.totalPanelHeight;
-    this.panelHeights = [];
+    this.panelPositions = [];
     this.totalPanelHeight = 0;
 
     const panels = dom.parentElement!.querySelectorAll('.panel');
     assertTrue(panels.length === this.attrs.panels.length);
     for (let i = 0; i < panels.length; i++) {
-      const height = panels[i].getBoundingClientRect().height;
-      this.panelHeights[i] = height;
-      this.totalPanelHeight += height;
+      const rect = panels[i].getBoundingClientRect() as DOMRect;
+      this.panelPositions[i] =
+          {height: rect.height, width: rect.width, x: rect.x, y: rect.y};
+      this.totalPanelHeight += rect.height;
     }
 
     return this.totalPanelHeight !== prevHeight;
@@ -235,13 +297,17 @@
     const canvasYStart =
         Math.floor(this.scrollTop - this.getCanvasOverdrawHeightPerSide());
 
+    if (this.attrs.kind === 'TRACKS') {
+      this.handleAreaSelection();
+    }
+
     let panelYStart = 0;
     const panels = assertExists(this.attrs).panels;
-    assertTrue(panels.length === this.panelHeights.length);
+    assertTrue(panels.length === this.panelPositions.length);
     let totalOnCanvas = 0;
     for (let i = 0; i < panels.length; i++) {
       const panel = panels[i];
-      const panelHeight = this.panelHeights[i];
+      const panelHeight = this.panelPositions[i].height;
       const yStartOnCanvas = panelYStart - canvasYStart;
 
       if (!this.overlapsCanvas(yStartOnCanvas, yStartOnCanvas + panelHeight)) {
diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts
index ddddd7c..32fa051 100644
--- a/ui/src/frontend/tickmark_panel.ts
+++ b/ui/src/frontend/tickmark_panel.ts
@@ -15,10 +15,10 @@
 import * as m from 'mithril';
 import {fromNs} from '../common/time';
 
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {gridlines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 // This is used to display the summary of search results.
 export class TickmarkPanel extends Panel {
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index 5005b1c..112c723 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -16,10 +16,10 @@
 
 import {timeToString} from '../common/time';
 
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {gridlines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 export class TimeAxisPanel extends Panel {
   view() {
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 890a2f0..3717a57 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -17,10 +17,10 @@
 import {timeToString} from '../common/time';
 import {TimeSpan} from '../common/time';
 
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {gridlines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 export interface BBox {
   x: number;
@@ -124,13 +124,10 @@
       ctx.fillRect(xAndTime[0], 0, 1, size.height);
     }
 
-    const selectedTimeRange = globals.frontendLocalState.selectedTimeRange;
-    if (selectedTimeRange.startSec !== undefined &&
-        selectedTimeRange.endSec !== undefined) {
-      const start =
-          Math.min(selectedTimeRange.startSec, selectedTimeRange.endSec);
-      const end =
-          Math.max(selectedTimeRange.startSec, selectedTimeRange.endSec);
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
+    if (selectedArea !== undefined) {
+      const start = Math.min(selectedArea.startSec, selectedArea.endSec);
+      const end = Math.max(selectedArea.startSec, selectedArea.endSec);
       this.renderSpan(ctx, size, new TimeSpan(start, end));
     } else if (globals.frontendLocalState.showTimeSelectPreview) {
       this.renderHover(ctx, size, globals.frontendLocalState.hoveredTimestamp);
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index 8203764..f08a0e2 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -30,7 +30,7 @@
 import {trackRegistry} from './track_registry';
 import {
   drawVerticalLineAtTime,
-  drawVerticalSelection
+  drawVerticalSelection,
 } from './vertical_line_helper';
 
 
@@ -80,6 +80,12 @@
       }
     }
 
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
+    const markSelectedClass =
+        selectedArea && selectedArea.tracks.includes(attrs.trackGroupId) ?
+        'selected' :
+        '';
+
     return m(
         `.track-group-panel[collapsed=${collapsed}]`,
         {id: 'track_' + this.trackGroupId},
@@ -91,7 +97,7 @@
               })),
                   e.stopPropagation();
             },
-            class: `${highlightClass}`,
+            class: `${highlightClass} ${markSelectedClass}`,
           },
           m('h1',
             {
@@ -154,13 +160,12 @@
                             size.height,
                             `rgb(52,69,150)`);
     }
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
+    if (localState.selectedArea.area !== undefined) {
       drawVerticalSelection(
           ctx,
           localState.timeScale,
-          globals.frontendLocalState.selectedTimeRange.startSec,
-          globals.frontendLocalState.selectedTimeRange.endSec,
+          localState.selectedArea.area.startSec,
+          localState.selectedArea.area.endSec,
           size.height,
           `rgba(0,0,0,0.5)`);
     }
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index c5fc8d7..b8c778d 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -17,12 +17,12 @@
 import {Actions} from '../common/actions';
 import {TrackState} from '../common/state';
 
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
 import {drawGridLines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
 import {verticalScrollToTrack} from './scroll_helper';
 import {Track} from './track';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 import {trackRegistry} from './track_registry';
 import {
   drawVerticalLineAtTime,
@@ -63,10 +63,16 @@
 
     const dragClass = this.dragging ? `drag` : '';
     const dropClass = this.dropping ? `drop-${this.dropping}` : '';
+    const selectedArea = globals.frontendLocalState.selectedArea.area;
+    const markSelectedClass =
+        selectedArea && selectedArea.tracks.includes(attrs.trackState.id) ?
+        'selected' :
+        '';
     return m(
         `.track-shell[draggable=true]`,
         {
-          class: `${highlightClass} ${dragClass} ${dropClass}`,
+          class: `${highlightClass} ${markSelectedClass} ${dragClass} ${
+              dropClass}`,
           onmousedown: this.onmousedown.bind(this),
           ondragstart: this.ondragstart.bind(this),
           ondragend: this.ondragend.bind(this),
@@ -167,11 +173,10 @@
         // If the click is outside of the current time range, clear it.
         const clickTime = globals.frontendLocalState.timeScale.pxToTime(
             e.layerX - TRACK_SHELL_WIDTH);
-        const start = globals.frontendLocalState.selectedTimeRange.startSec;
-        const end = globals.frontendLocalState.selectedTimeRange.endSec;
-        if (start !== undefined && end !== undefined &&
-            (clickTime < start || clickTime > end)) {
-          globals.frontendLocalState.removeTimeRange();
+        const area = globals.frontendLocalState.selectedArea.area;
+        if (area !== undefined &&
+            (clickTime < area.startSec || clickTime > area.endSec)) {
+          globals.frontendLocalState.deselectArea();
           e.stopPropagation();
         } else if (attrs.track.onMouseClick(
                        {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY})) {
@@ -266,11 +271,12 @@
     const localState = globals.frontendLocalState;
     // Draw vertical line when hovering on the notes panel.
     if (localState.showNotePreview) {
-      drawVerticalLineAtTime(ctx,
-                             localState.timeScale,
-                             localState.hoveredTimestamp,
-                             size.height,
-                             `#aaa`);
+      drawVerticalLineAtTime(
+          ctx,
+          localState.timeScale,
+          localState.hoveredTimestamp,
+          size.height,
+          `#aaa`);
     }
     // Draw vertical line when shift is pressed.
     if (localState.showTimeSelectPreview) {
@@ -280,13 +286,12 @@
                              size.height,
                              `rgb(52,69,150)`);
     }
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
+    if (localState.selectedArea.area !== undefined) {
       drawVerticalSelection(
           ctx,
           localState.timeScale,
-          globals.frontendLocalState.selectedTimeRange.startSec,
-          globals.frontendLocalState.selectedTimeRange.endSec,
+          localState.selectedArea.area.startSec,
+          localState.selectedArea.area.endSec,
           size.height,
           `rgba(0,0,0,0.5)`);
     }
diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts
index 073f043..d61fd70 100644
--- a/ui/src/frontend/vertical_line_helper.ts
+++ b/ui/src/frontend/vertical_line_helper.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {TimeScale} from './time_scale';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 export function drawVerticalLineAtTime(ctx: CanvasRenderingContext2D,
                                        timeScale: TimeScale,
@@ -41,6 +41,8 @@
     ctx.lineWidth = prevLineWidth;
 }
 
+// This draws two shaded rectangles outside of the area of interest. Effectivly
+// highlighting an area by colouring/darkening the outside areas.
 export function drawVerticalSelection(
     ctx: CanvasRenderingContext2D,
     timeScale: TimeScale,
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index d9243b0..49e6d22 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -19,6 +19,7 @@
 import {TimeSpan} from '../common/time';
 
 import {copyToClipboard} from './clipboard';
+import {TRACK_SHELL_WIDTH} from './css_constants';
 import {DetailsPanel} from './details_panel';
 import {globals} from './globals';
 import {NotesPanel} from './notes_panel';
@@ -31,7 +32,6 @@
 import {TimeAxisPanel} from './time_axis_panel';
 import {computeZoom} from './time_scale';
 import {TimeSelectionPanel} from './time_selection_panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 import {TrackGroupPanel} from './track_group_panel';
 import {TrackPanel} from './track_panel';
 import {VideoPanel} from './video_panel';
@@ -101,11 +101,10 @@
 // Checks if the mousePos is within 3px of the start or end of the
 // current selected time range.
 function onTimeRangeBoundary(mousePos: number): 'START'|'END'|null {
-  const startSec = globals.frontendLocalState.selectedTimeRange.startSec;
-  const endSec = globals.frontendLocalState.selectedTimeRange.endSec;
-  if (startSec !== undefined && endSec !== undefined) {
-    const start = globals.frontendLocalState.timeScale.timeToPx(startSec);
-    const end = globals.frontendLocalState.timeScale.timeToPx(endSec);
+  const area = globals.frontendLocalState.selectedArea.area;
+  if (area !== undefined) {
+    const start = globals.frontendLocalState.timeScale.timeToPx(area.startSec);
+    const end = globals.frontendLocalState.timeScale.timeToPx(area.endSec);
     const startDrag = mousePos - TRACK_SHELL_WIDTH;
     const startDistance = Math.abs(start - startDrag);
     const endDistance = Math.abs(end - startDrag);
@@ -184,34 +183,40 @@
         return onTimeRangeBoundary(currentPx) !== null;
       },
       onDrag: (
-          dragStartPx: number,
-          prevPx: number,
-          currentPx: number,
+          dragStartX: number,
+          dragStartY: number,
+          prevX: number,
+          currentX: number,
+          currentY: number,
           editing: boolean) => {
         const traceTime = globals.state.traceTime;
         const scale = frontendLocalState.timeScale;
         this.keepCurrentSelection = true;
         if (editing) {
-          const startSec = frontendLocalState.selectedTimeRange.startSec;
-          const endSec = frontendLocalState.selectedTimeRange.endSec;
-          if (startSec !== undefined && endSec !== undefined) {
-            const newTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
+          const selectedArea = frontendLocalState.selectedArea.area;
+          if (selectedArea !== undefined) {
+            const newTime = scale.pxToTime(currentX - TRACK_SHELL_WIDTH);
             // Have to check again for when one boundary crosses over the other.
-            const curBoundary = onTimeRangeBoundary(prevPx);
+            const curBoundary = onTimeRangeBoundary(prevX);
             if (curBoundary == null) return;
-            const keepTime = curBoundary === 'START' ? endSec : startSec;
-            frontendLocalState.selectTimeRange(
+            const keepTime = curBoundary === 'START' ? selectedArea.endSec :
+                                                       selectedArea.startSec;
+            frontendLocalState.selectArea(
                 Math.max(Math.min(keepTime, newTime), traceTime.startSec),
-                Math.min(Math.max(keepTime, newTime), traceTime.endSec));
+                Math.min(Math.max(keepTime, newTime), traceTime.endSec),
+            );
           }
         } else {
           frontendLocalState.setShowTimeSelectPreview(false);
-          const dragStartTime = scale.pxToTime(dragStartPx - TRACK_SHELL_WIDTH);
-          const dragEndTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
-          frontendLocalState.selectTimeRange(
+          const dragStartTime = scale.pxToTime(dragStartX - TRACK_SHELL_WIDTH);
+          const dragEndTime = scale.pxToTime(currentX - TRACK_SHELL_WIDTH);
+          frontendLocalState.selectArea(
               Math.max(
                   Math.min(dragStartTime, dragEndTime), traceTime.startSec),
-              Math.min(Math.max(dragStartTime, dragEndTime), traceTime.endSec));
+              Math.min(Math.max(dragStartTime, dragEndTime), traceTime.endSec),
+          );
+          frontendLocalState.areaY.start = dragStartY;
+          frontendLocalState.areaY.end = currentY;
         }
         globals.rafScheduler.scheduleRedraw();
       }
diff --git a/ui/tslint.json b/ui/tslint.json
index 6cbcbcd..270eb87 100644
--- a/ui/tslint.json
+++ b/ui/tslint.json
@@ -7,13 +7,13 @@
     "array-type": [true, "array-simple"],
     "arrow-return-shorthand": true,
     "ban": [true,
-      {"name": "parseInt", "message": "See http://go/tsstyle#type-coercion"},
-      {"name": "parseFloat", "message": "See http://go/tsstyle#type-coercion"},
-      {"name": "Array", "message": "See http://go/tsstyle#array-constructor"},
-      {"name": ["*", "innerText"], "message": "Use .textContent instead. http://go/typescript/patterns#browser-oddities"}
+      {"name": "parseInt", "message": "See http://goto.google.com/tsstyle#type-coercion"},
+      {"name": "parseFloat", "message": "See http://goto.google.com/tsstyle#type-coercion"},
+      {"name": "Array", "message": "See http://goto.google.com/tsstyle#array-constructor"},
+      {"name": ["*", "innerText"], "message": "Use .textContent instead. http://goto.google.com/typescript/patterns#browser-oddities"}
     ],
     "ban-types": [true,
-      ["Object", "Use {} or 'object' instead. See http://go/ts-style#redundant-types"],
+      ["Object", "Use {} or 'object' instead. See http://goto.google.com/ts-style#redundant-types"],
       ["String", "Use 'string' instead."],
       ["Number", "Use 'number' instead."],
       ["Boolean", "Use 'boolean' instead."]