Merge "Minor: fix a typo in a BUILD file."
diff --git a/Android.bp b/Android.bp
index 0d0ad96..deb1235 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1980,6 +1980,7 @@
         ":perfetto_src_trace_processor_sqlite_functions_functions",
         ":perfetto_src_trace_processor_sqlite_sqlite",
         ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
+        ":perfetto_src_trace_processor_stdlib_stdlib",
         ":perfetto_src_trace_processor_storage_full",
         ":perfetto_src_trace_processor_storage_minimal",
         ":perfetto_src_trace_processor_storage_storage",
@@ -2171,6 +2172,7 @@
         "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+        "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
     ],
     defaults: [
         "perfetto_defaults",
@@ -9456,12 +9458,12 @@
         "src/trace_processor/metrics/sql/trace_stats.sql",
         "src/trace_processor/metrics/sql/webview/webview_power_usage.sql",
     ],
-    cmd: "$(location tools/gen_amalgamated_sql_metrics.py) --cpp_out=$(out) $(in)",
+    cmd: "$(location tools/gen_amalgamated_sql.py) --type=METRICS --cpp_out=$(out) $(in)",
     out: [
         "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h",
     ],
     tool_files: [
-        "tools/gen_amalgamated_sql_metrics.py",
+        "tools/gen_amalgamated_sql.py",
     ],
 }
 
@@ -9553,6 +9555,26 @@
     ],
 }
 
+// GN: //src/trace_processor/stdlib:gen_amalgamated_stdlib
+genrule {
+    name: "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
+    srcs: [
+        "src/trace_processor/stdlib/android/binder.sql",
+    ],
+    cmd: "$(location tools/gen_amalgamated_sql.py) --type=LIB --cpp_out=$(out) $(in)",
+    out: [
+        "src/trace_processor/stdlib/amalgamated_stdlib.h",
+    ],
+    tool_files: [
+        "tools/gen_amalgamated_sql.py",
+    ],
+}
+
+// GN: //src/trace_processor/stdlib:stdlib
+filegroup {
+    name: "perfetto_src_trace_processor_stdlib_stdlib",
+}
+
 // GN: //src/trace_processor:storage_full
 filegroup {
     name: "perfetto_src_trace_processor_storage_full",
@@ -11102,6 +11124,7 @@
         ":perfetto_src_trace_processor_sqlite_sqlite",
         ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
         ":perfetto_src_trace_processor_sqlite_unittests",
+        ":perfetto_src_trace_processor_stdlib_stdlib",
         ":perfetto_src_trace_processor_storage_full",
         ":perfetto_src_trace_processor_storage_minimal",
         ":perfetto_src_trace_processor_storage_storage",
@@ -11322,6 +11345,7 @@
         "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+        "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
         "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
         "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
         "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
@@ -11736,6 +11760,7 @@
         ":perfetto_src_trace_processor_sqlite_functions_functions",
         ":perfetto_src_trace_processor_sqlite_sqlite",
         ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
+        ":perfetto_src_trace_processor_stdlib_stdlib",
         ":perfetto_src_trace_processor_storage_full",
         ":perfetto_src_trace_processor_storage_minimal",
         ":perfetto_src_trace_processor_storage_storage",
@@ -11804,6 +11829,7 @@
         "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+        "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
     ],
     defaults: [
         "perfetto_defaults",
@@ -11924,6 +11950,7 @@
         ":perfetto_src_trace_processor_sqlite_functions_functions",
         ":perfetto_src_trace_processor_sqlite_sqlite",
         ":perfetto_src_trace_processor_sqlite_sqlite_minimal",
+        ":perfetto_src_trace_processor_stdlib_stdlib",
         ":perfetto_src_trace_processor_storage_full",
         ":perfetto_src_trace_processor_storage_minimal",
         ":perfetto_src_trace_processor_storage_storage",
@@ -11996,6 +12023,7 @@
         "perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
         "perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+        "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
         "perfetto_src_traceconv_gen_cc_trace_descriptor",
     ],
     defaults: [
diff --git a/BUILD b/BUILD
index 780a477..f8ac8d2 100644
--- a/BUILD
+++ b/BUILD
@@ -1379,9 +1379,9 @@
     outs = [
         "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h",
     ],
-    cmd = "$(location gen_amalgamated_sql_metrics_py) --cpp_out=$@ $(SRCS)",
+    cmd = "$(location gen_amalgamated_sql_py) --type=METRICS --cpp_out=$@ $(SRCS)",
     exec_tools = [
-        ":gen_amalgamated_sql_metrics_py",
+        ":gen_amalgamated_sql_py",
     ],
 )
 
@@ -1490,6 +1490,28 @@
     ],
 )
 
+perfetto_genrule(
+    name = "src_trace_processor_stdlib_gen_amalgamated_stdlib",
+    srcs = [
+        "src/trace_processor/stdlib/android/binder.sql",
+    ],
+    outs = [
+        "src/trace_processor/stdlib/amalgamated_stdlib.h",
+    ],
+    cmd = "$(location gen_amalgamated_sql_py) --type=LIB --cpp_out=$@ $(SRCS)",
+    exec_tools = [
+        ":gen_amalgamated_sql_py",
+    ],
+)
+
+# GN target: //src/trace_processor/stdlib:stdlib
+perfetto_filegroup(
+    name = "src_trace_processor_stdlib_stdlib",
+    srcs = [
+        "src/trace_processor/stdlib/dummy.h",
+    ],
+)
+
 # GN target: //src/trace_processor/storage:storage
 perfetto_filegroup(
     name = "src_trace_processor_storage_storage",
@@ -4254,6 +4276,7 @@
         ":src_trace_processor_sqlite_functions_functions",
         ":src_trace_processor_sqlite_sqlite",
         ":src_trace_processor_sqlite_sqlite_minimal",
+        ":src_trace_processor_stdlib_stdlib",
         ":src_trace_processor_storage_full",
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
@@ -4339,6 +4362,8 @@
            PERFETTO_CONFIG.deps.sqlite_ext_percentile +
            PERFETTO_CONFIG.deps.zlib + [
         ":cc_amalgamated_sql_metrics",
+    ] + [
+        ":cc_amalgamated_stdlib",
     ] +
            PERFETTO_CONFIG.deps.demangle_wrapper,
     linkstatic = True,
@@ -4383,6 +4408,7 @@
         ":src_trace_processor_sqlite_functions_functions",
         ":src_trace_processor_sqlite_sqlite",
         ":src_trace_processor_sqlite_sqlite_minimal",
+        ":src_trace_processor_stdlib_stdlib",
         ":src_trace_processor_storage_full",
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
@@ -4461,6 +4487,8 @@
            PERFETTO_CONFIG.deps.sqlite_ext_percentile +
            PERFETTO_CONFIG.deps.zlib + [
         ":cc_amalgamated_sql_metrics",
+    ] + [
+        ":cc_amalgamated_stdlib",
     ] +
            PERFETTO_CONFIG.deps.demangle_wrapper,
 )
@@ -4567,6 +4595,7 @@
         ":src_trace_processor_sqlite_functions_functions",
         ":src_trace_processor_sqlite_sqlite",
         ":src_trace_processor_sqlite_sqlite_minimal",
+        ":src_trace_processor_stdlib_stdlib",
         ":src_trace_processor_storage_full",
         ":src_trace_processor_storage_minimal",
         ":src_trace_processor_storage_storage",
@@ -4644,6 +4673,8 @@
            PERFETTO_CONFIG.deps.sqlite_ext_percentile +
            PERFETTO_CONFIG.deps.zlib + [
         ":cc_amalgamated_sql_metrics",
+    ] + [
+        ":cc_amalgamated_stdlib",
     ] +
            PERFETTO_CONFIG.deps.demangle_wrapper,
 )
@@ -4695,12 +4726,17 @@
     hdrs = ["src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"],
 )
 
+perfetto_cc_library(
+    name = "cc_amalgamated_stdlib",
+    hdrs = ["src/trace_processor/stdlib/amalgamated_stdlib.h"],
+)
+
 perfetto_py_binary(
-    name = "gen_amalgamated_sql_metrics_py",
+    name = "gen_amalgamated_sql_py",
     srcs = [
-        "tools/gen_amalgamated_sql_metrics.py",
+        "tools/gen_amalgamated_sql.py",
     ],
-    main = "tools/gen_amalgamated_sql_metrics.py",
+    main = "tools/gen_amalgamated_sql.py",
     python_version = "PY3",
 )
 
diff --git a/BUILD.extras b/BUILD.extras
index f870aa6..5a11740 100644
--- a/BUILD.extras
+++ b/BUILD.extras
@@ -13,12 +13,17 @@
     hdrs = ["src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"],
 )
 
+perfetto_cc_library(
+    name = "cc_amalgamated_stdlib",
+    hdrs = ["src/trace_processor/stdlib/amalgamated_stdlib.h"],
+)
+
 perfetto_py_binary(
-    name = "gen_amalgamated_sql_metrics_py",
+    name = "gen_amalgamated_sql_py",
     srcs = [
-        "tools/gen_amalgamated_sql_metrics.py",
+        "tools/gen_amalgamated_sql.py",
     ],
-    main = "tools/gen_amalgamated_sql_metrics.py",
+    main = "tools/gen_amalgamated_sql.py",
     python_version = "PY3",
 )
 
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index d49469e..99627a2 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -140,7 +140,10 @@
       "-Wno-inconsistent-missing-override",
     ]
   } else if (!is_win) {  # implies gcc
-    cflags += [ "-Wno-return-type" ]
+    cflags += [
+      "-Wno-return-type",
+      "-Wno-stringop-overread",
+    ]
   }
   if (is_win) {
     cflags += [ "/W0" ]
diff --git a/docs/contributing/build-instructions.md b/docs/contributing/build-instructions.md
index 878a003..9de4f74 100644
--- a/docs/contributing/build-instructions.md
+++ b/docs/contributing/build-instructions.md
@@ -326,6 +326,12 @@
 
 Use bundled toolchain from `buildtools/` rather than system-wide one.
 
+`non_hermetic_clang_stdlib = libc++ | libstdc++`
+
+If `is_hermetic_clang` is `false`, sets the `-stdlib` flag for clang
+invocations. `libstdc++` is default on Linux hosts and `libc++` is
+default everywhere else.
+
 `cc = "gcc" / cxx = "g++"`
 
 Uses a different compiler binary (default: autodetected depending on is_clang).
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index 48c82ec..0d17328 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -88,6 +88,10 @@
   } else if (!is_clang && !is_win) {
     # Use return std::move(...) for compatibility with old GCC compilers.
     cflags += [ "-Wno-redundant-move" ]
+
+    # Use after free detection in GCC is still not good enough: it still fails
+    # on very obvious false-positives in trace processor.
+    cflags += [ "-Wno-use-after-free" ]
   }
 }
 
@@ -233,6 +237,11 @@
     not_needed([ "hermetic_clang_suppressions" ])
   }
 
+  if (is_clang && !is_hermetic_clang && !is_wasm) {
+    cflags_cc += [ "-stdlib=" + non_hermetic_clang_stdlib ]
+    ldflags += [ "-stdlib=" + non_hermetic_clang_stdlib ]
+  }
+
   if (is_lto) {
     cflags += [ "-flto=full" ]
     ldflags += [ "-flto=full" ]
diff --git a/gn/standalone/toolchain/llvm.gni b/gn/standalone/toolchain/llvm.gni
index 75bc5ff..3726411 100644
--- a/gn/standalone/toolchain/llvm.gni
+++ b/gn/standalone/toolchain/llvm.gni
@@ -16,6 +16,11 @@
 
 declare_args() {
   is_hermetic_clang = is_clang && (is_linux_host || is_win_host)
+  if (is_linux_host) {
+    non_hermetic_clang_stdlib = "libstdc++"
+  } else {
+    non_hermetic_clang_stdlib = "libc++"
+  }
 }
 
 assert(!is_hermetic_clang || is_clang, "is_hermetic_clang requires is_clang")
diff --git a/include/perfetto/trace_processor/trace_blob_view.h b/include/perfetto/trace_processor/trace_blob_view.h
index 884d3a8..f140866 100644
--- a/include/perfetto/trace_processor/trace_blob_view.h
+++ b/include/perfetto/trace_processor/trace_blob_view.h
@@ -87,13 +87,13 @@
   TraceBlobView slice(const uint8_t* data, size_t length) const {
     PERFETTO_DCHECK(data >= data_);
     PERFETTO_DCHECK(data + length <= data_ + length_);
-    return TraceBlobView(data, static_cast<uint32_t>(length), blob_);
+    return TraceBlobView(blob_, data, static_cast<uint32_t>(length));
   }
 
   // Like slice() but takes an offset rather than a pointer as 1st argument.
   TraceBlobView slice_off(size_t off, size_t length) const {
     PERFETTO_DCHECK(off + length <= length_);
-    return TraceBlobView(data_ + off, static_cast<uint32_t>(length), blob_);
+    return TraceBlobView(blob_, data_ + off, static_cast<uint32_t>(length));
   }
 
   TraceBlobView copy() const { return slice(data_, length_); }
@@ -110,12 +110,12 @@
   size_t size() const { return length_; }
 
  private:
-  TraceBlobView(const uint8_t* data, uint32_t length, RefPtr<TraceBlob> blob)
-      : data_(data), length_(length), blob_(std::move(blob)) {}
+  TraceBlobView(RefPtr<TraceBlob> blob, const uint8_t* data, uint32_t length)
+      : blob_(std::move(blob)), data_(data), length_(length) {}
 
+  RefPtr<TraceBlob> blob_;
   const uint8_t* data_ = nullptr;
   uint32_t length_ = 0;
-  RefPtr<TraceBlob> blob_;
 };
 
 }  // namespace trace_processor
diff --git a/infra/ci/config.py b/infra/ci/config.py
index 9c56f8b..ba8bf93 100755
--- a/infra/ci/config.py
+++ b/infra/ci/config.py
@@ -66,8 +66,10 @@
 # Only variables starting with PERFETTO_ are propagated into the sandbox.
 JOB_CONFIGS = {
     'linux-clang-x86_64-debug': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=true is_hermetic_clang=false',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
+        'PERFETTO_TEST_GN_ARGS':
+            'is_debug=true is_hermetic_clang=false non_hermetic_clang_stdlib="libc++"',
+        'PERFETTO_TEST_SCRIPT':
+            'test/ci/linux_tests.sh',
     },
     'linux-clang-x86_64-tsan': {
         'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_tsan=true',
diff --git a/infra/ci/sandbox/Dockerfile b/infra/ci/sandbox/Dockerfile
index 79da8d4..ebd5539 100644
--- a/infra/ci/sandbox/Dockerfile
+++ b/infra/ci/sandbox/Dockerfile
@@ -26,7 +26,8 @@
     apt-get -y install python3 python3-pip git curl sudo lz4 tar ccache tini \
                        libpulse0 libgl1 libxml2 libc6-dev-i386 libtinfo5 \
                        gnupg2 pkg-config zip g++ zlib1g-dev unzip \
-                       python3-distutils clang-8 gcc-7 g++-7; \
+                       python3-distutils gcc-7 g++-7; \
+    apt-get -y install libc++-8-dev libc++abi-8-dev clang-8; \
     update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1; \
     gcc-7 --version; \
     g++-7 --version; \
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 9b1cc09..d815d04 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -367,6 +367,7 @@
       "metrics",
       "sqlite",
       "sqlite/functions",
+      "stdlib",
       "storage",
       "tables",
       "types",
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index a84612a..28ba43c 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -193,9 +193,10 @@
 }
 
 action("gen_amalgamated_sql_metrics") {
-  script = "../../../../tools/gen_amalgamated_sql_metrics.py"
+  script = "../../../../tools/gen_amalgamated_sql.py"
   generated_header = "${target_gen_dir}/amalgamated_sql_metrics.h"
   args = rebase_path(sql_files, root_build_dir) + [
+           "--type=METRICS",
            "--cpp_out",
            rebase_path(generated_header, root_build_dir),
          ]
diff --git a/src/trace_processor/stdlib/BUILD.gn b/src/trace_processor/stdlib/BUILD.gn
new file mode 100644
index 0000000..e447993
--- /dev/null
+++ b/src/trace_processor/stdlib/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 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("../../../gn/perfetto.gni")
+import("android/sql_files.gni")
+
+config("gen_config") {
+  include_dirs = [ "${root_gen_dir}/${perfetto_root_path}" ]
+}
+
+sql_files = android_sql_files
+
+action("gen_amalgamated_stdlib") {
+  script = "../../../tools/gen_amalgamated_sql.py"
+  generated_header = "${target_gen_dir}/amalgamated_stdlib.h"
+  args = rebase_path(sql_files, root_build_dir) + [
+           "--type=LIB",
+           "--cpp_out",
+           rebase_path(generated_header, root_build_dir),
+         ]
+  inputs = sql_files
+  outputs = [ generated_header ]
+  public_configs = [ ":gen_config" ]
+}
+
+if (enable_perfetto_trace_processor_sqlite) {
+  source_set("stdlib") {
+    sources = [ "dummy.h" ]
+    deps = [ ":gen_amalgamated_stdlib" ]
+  }
+}
diff --git a/src/trace_processor/stdlib/android/binder.sql b/src/trace_processor/stdlib/android/binder.sql
new file mode 100644
index 0000000..261916e
--- /dev/null
+++ b/src/trace_processor/stdlib/android/binder.sql
@@ -0,0 +1,33 @@
+--
+-- Copyright 2022 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.
+--
+
+-- Count Binder transactions per process
+DROP VIEW IF EXISTS binder_metrics_by_process;
+CREATE VIEW binder_metrics_by_process AS
+SELECT
+  process.name as process_name,
+  process.pid as pid,
+  slice.name as slice_name,
+  COUNT(*) as event_count
+FROM slice
+  INNER JOIN thread_track ON slice.track_id=thread_track.id
+  INNER JOIN thread ON thread.utid=thread_track.utid
+  INNER JOIN process ON thread.upid=process.upid
+WHERE
+  slice.name glob 'binder*'
+GROUP BY
+  process_name,
+  slice_name;
diff --git a/src/trace_processor/stdlib/android/sql_files.gni b/src/trace_processor/stdlib/android/sql_files.gni
new file mode 100644
index 0000000..4304349
--- /dev/null
+++ b/src/trace_processor/stdlib/android/sql_files.gni
@@ -0,0 +1,16 @@
+# Copyright (C) 2022 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.
+
+# Keep this list sorted.
+android_sql_files = [ "android/binder.sql" ]
diff --git a/src/trace_processor/stdlib/dummy.h b/src/trace_processor/stdlib/dummy.h
new file mode 100644
index 0000000..ad3dfc9
--- /dev/null
+++ b/src/trace_processor/stdlib/dummy.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+// TODO(mayzner): Remove this file when implementing IMPORT function
+
+#ifndef SRC_TRACE_PROCESSOR_STDLIB_DUMMY_H_
+#define SRC_TRACE_PROCESSOR_STDLIB_DUMMY_H_
+
+namespace perfetto {
+namespace trace_processor {}
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_STDLIB_DUMMY_H_
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index a122227..425a3cb 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -119,7 +119,7 @@
     filter_str = base::Join(parts, " || ");
   }
 
-  for (const std::string& event : {"sys_enter", "sys_exit"}) {
+  for (const char* event : {"sys_enter", "sys_exit"}) {
     std::string path = root_ + "events/raw_syscalls/" + event + "/filter";
     if (!WriteToFile(path, filter_str)) {
       PERFETTO_ELOG("Failed to write file: %s", path.c_str());
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 219b413..729bdb4 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -46,6 +46,7 @@
 #include "src/tracing/core/null_trace_writer.h"
 #include "src/tracing/internal/tracing_muxer_fake.h"
 
+#include "protos/perfetto/config/chrome/chrome_config.gen.h"
 #include "protos/perfetto/config/interceptor_config.gen.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
@@ -144,6 +145,14 @@
   config.set_trace_duration_ms(0);
   config.set_stop_timeout_ms(0);
   config.set_enable_extra_guardrails(false);
+  // Clear client priority inside Chrome config, because Chrome always sets
+  // the priority to USER_INITIATED when setting up startup tracing.
+  // TODO(khokhlov): Remove this when Chrome correctly sets client_priority
+  // for startup tracing (and propagates it to all child processes).
+  if (config.has_chrome_config()) {
+    config.mutable_chrome_config()->set_client_priority(
+        perfetto::protos::gen::ChromeConfig::UNKNOWN);
+  }
   base::Hasher hasher;
   std::string config_bytes = config.SerializeAsString();
   hasher.Update(config_bytes.data(), config_bytes.size());
diff --git a/tools/gen_amalgamated_sql_metrics.py b/tools/gen_amalgamated_sql.py
similarity index 81%
rename from tools/gen_amalgamated_sql_metrics.py
rename to tools/gen_amalgamated_sql.py
index 16f6aac..099bc92 100755
--- a/tools/gen_amalgamated_sql_metrics.py
+++ b/tools/gen_amalgamated_sql.py
@@ -21,7 +21,7 @@
 # as a string constant to allow trace processor to exectue the metrics.
 
 REPLACEMENT_HEADER = '''/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -45,13 +45,32 @@
  #include <string.h>
 '''
 
-NAMESPACE_BEGIN = '''
+STDLIB_NAMESPACE_BEGIN = '''
+namespace perfetto {
+namespace trace_processor {
+namespace stdlib {
+'''
+
+STDLIB_NAMESPACE_END = '''
+}  // namespace stdlib
+}  // namespace trace_processor
+}  // namespace perfetto
+'''
+
+METRICS_NAMESPACE_BEGIN = '''
 namespace perfetto {
 namespace trace_processor {
 namespace metrics {
 namespace sql_metrics {
 '''
 
+METRICS_NAMESPACE_END = '''
+}  // namespace sql_metrics
+}  // namespace metrics
+}  // namespace trace_processor
+}  // namespace perfetto
+'''
+
 FILE_TO_SQL_STRUCT = '''
 struct FileToSql {
   const char* path;
@@ -59,12 +78,8 @@
 };
 '''
 
-NAMESPACE_END = '''
-}  // namespace sql_metrics
-}  // namespace metrics
-}  // namespace trace_processor
-}  // namsepace perfetto
-'''
+ROOT = '''
+const char kRootPath[] = '''
 
 
 def filename_to_variable(filename):
@@ -73,11 +88,14 @@
 
 def main():
   parser = argparse.ArgumentParser()
+  parser.add_argument('--type', required=True)
   parser.add_argument('--cpp_out', required=True)
   parser.add_argument('sql_files', nargs='*')
   args = parser.parse_args()
 
   root_path = os.path.commonprefix([os.path.abspath(x) for x in args.sql_files])
+  if '.sql' in root_path:
+    root_path = root_path.rsplit('/', 1)[0]
 
   # Extract the SQL output from each file.
   sql_outputs = {}
@@ -89,7 +107,13 @@
 
   with open(args.cpp_out, 'w+') as output:
     output.write(REPLACEMENT_HEADER)
-    output.write(NAMESPACE_BEGIN)
+    output.write(
+        METRICS_NAMESPACE_BEGIN) if args.type == 'METRICS' else output.write(
+            STDLIB_NAMESPACE_BEGIN)
+
+    if args.type == "LIB":
+      output.write(ROOT + f'''"{root_path.rsplit("stdlib/")[-1]}";
+      ''')
 
     # Create the C++ variable for each SQL file.
     for path, sql in sql_outputs.items():
@@ -122,7 +146,9 @@
       output.write('\n  {{"{}", {}}},\n'.format(path, variable))
     output.write("};\n")
 
-    output.write(NAMESPACE_END)
+    output.write(
+        METRICS_NAMESPACE_END) if args.type == 'METRICS' else output.write(
+            STDLIB_NAMESPACE_END)
 
   return 0
 
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 2469958..0fc587c 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -771,10 +771,11 @@
   bp_module_name = label_to_module_name(target.name)
   module = Module('genrule', bp_module_name, target.name)
   module.tool_files = [
-      'tools/gen_amalgamated_sql_metrics.py',
+      'tools/gen_amalgamated_sql.py',
   ]
   module.cmd = ' '.join([
-      '$(location tools/gen_amalgamated_sql_metrics.py)',
+      '$(location tools/gen_amalgamated_sql.py)',
+      '--type=METRICS',
       '--cpp_out=$(out)',
       '$(in)',
   ])
@@ -784,6 +785,23 @@
   blueprint.add_module(module)
   return module
 
+def create_amalgamated_stdlib_module(blueprint, target):
+  bp_module_name = label_to_module_name(target.name)
+  module = Module('genrule', bp_module_name, target.name)
+  module.tool_files = [
+      'tools/gen_amalgamated_sql.py',
+  ]
+  module.cmd = ' '.join([
+      '$(location tools/gen_amalgamated_sql.py)',
+      '--type=LIB',
+      '--cpp_out=$(out)',
+      '$(in)',
+  ])
+  module.genrule_headers.add(module.name)
+  module.out.update(target.outputs)
+  module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
+  blueprint.add_module(module)
+  return module
 
 def create_cc_proto_descriptor_module(blueprint, target):
   bp_module_name = label_to_module_name(target.name)
@@ -891,6 +909,8 @@
   elif target.type == 'action':
     if 'gen_amalgamated_sql_metrics' in target.name:
       module = create_amalgamated_sql_metrics_module(blueprint, target)
+    elif 'gen_amalgamated_stdlib' in target.name:
+      module = create_amalgamated_stdlib_module(blueprint, target)
     elif re.match('.*gen_cc_.*_descriptor$', name_without_toolchain):
       module = create_cc_proto_descriptor_module(blueprint, target)
     elif target.type == 'action' and \
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 1c64257..e64307a 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -114,6 +114,9 @@
     '//src/trace_processor/metrics/sql:gen_amalgamated_sql_metrics': [[
         ':cc_amalgamated_sql_metrics'
     ]],
+    '//src/trace_processor/stdlib:gen_amalgamated_stdlib': [[
+        ':cc_amalgamated_stdlib'
+    ]],
     gn_utils.GEN_VERSION_TARGET: ['PERFETTO_CONFIG.deps.version_header'],
 }
 
@@ -122,8 +125,18 @@
   label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_genrule')
   label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)]
   label.outs += target.outputs
-  label.cmd = r'$(location gen_amalgamated_sql_metrics_py) --cpp_out=$@ $(SRCS)'
-  label.exec_tools += [':gen_amalgamated_sql_metrics_py']
+  label.cmd = (r'$(location gen_amalgamated_sql_py) ' 
+  r'--type=METRICS --cpp_out=$@ $(SRCS)')
+  label.exec_tools += [':gen_amalgamated_sql_py']
+  return [label]
+
+def gen_amalgamated_stdlib(target):
+  label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_genrule')
+  label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)]
+  label.outs += target.outputs
+  label.cmd = (r'$(location gen_amalgamated_sql_py) '
+  r'--type=LIB --cpp_out=$@ $(SRCS)')
+  label.exec_tools += [':gen_amalgamated_sql_py']
   return [label]
 
 
@@ -152,6 +165,8 @@
         gen_version_header,
     '//src/trace_processor/metrics/sql:gen_amalgamated_sql_metrics':
         gen_amalgamated_sql_metrics,
+    '//src/trace_processor/stdlib:gen_amalgamated_stdlib':
+        gen_amalgamated_stdlib,
 }
 
 # ------------------------------------------------------------------------------
diff --git a/ui/src/common/query_result.ts b/ui/src/common/query_result.ts
index 347c4ed..bae847d 100644
--- a/ui/src/common/query_result.ts
+++ b/ui/src/common/query_result.ts
@@ -183,6 +183,12 @@
   // have been fetched. The promise return value is always the object iself.
   waitAllRows(): Promise<QueryResult>;
 
+  // Returns a promise that is resolved when either:
+  // - more rows are available
+  // - all rows are available
+  // The promise return value is always the object iself.
+  waitMoreRows(): Promise<QueryResult>;
+
   // Can return an empty array if called before the first batch is resolved.
   // This should be called only after having awaited for at least one batch.
   columns(): string[];
@@ -194,10 +200,6 @@
   // Returns the number of SQL statement that produced output rows. This number
   // is <= statementCount().
   statementWithOutputCount(): number;
-
-  // TODO(primiano): next CLs will introduce a waitMoreRows() to allow tracks
-  // to await until some more data (but not necessarily all) is available. For
-  // now everything uses waitAllRows().
 }
 
 // Interface exposed to engine.ts to pump in the data as new row batches arrive.
@@ -248,6 +250,10 @@
   // last result batch has been been retrieved.
   private allRowsPromise?: Deferred<QueryResult>;
 
+  // Promise awaiting on waitMoreRows(). This resolved when the next
+  // batch is appended via appendResultBatch.
+  private moreRowsPromise?: Deferred<QueryResult>;
+
   isComplete(): boolean {
     return this._isComplete;
   }
@@ -288,6 +294,20 @@
     return this.allRowsPromise;
   }
 
+  waitMoreRows(): Promise<QueryResult> {
+    if (this.moreRowsPromise !== undefined) {
+      return this.moreRowsPromise;
+    }
+
+    const moreRowsPromise = defer<QueryResult>();
+    if (this._isComplete) {
+      this.resolveOrReject(moreRowsPromise, this);
+    } else {
+      this.moreRowsPromise = moreRowsPromise;
+    }
+    return moreRowsPromise;
+  }
+
   // --- WritableQueryResult implementation.
 
   // Called by the engine when a new QueryResult is available. Note that a
@@ -369,6 +389,11 @@
       }  // switch (tag)
     }    // while (pos < end)
 
+    if (this.moreRowsPromise !== undefined) {
+      this.resolveOrReject(this.moreRowsPromise, this);
+      this.moreRowsPromise = undefined;
+    }
+
     if (this._isComplete && this.allRowsPromise !== undefined) {
       this.resolveOrReject(this.allRowsPromise, this);
     }
@@ -768,6 +793,9 @@
   waitAllRows() {
     return this.impl.waitAllRows();
   }
+  waitMoreRows() {
+    return this.impl.waitMoreRows();
+  }
   isComplete() {
     return this.impl.isComplete();
   }
diff --git a/ui/src/common/query_result_unittest.ts b/ui/src/common/query_result_unittest.ts
index 5fad6fe..8f508e7 100644
--- a/ui/src/common/query_result_unittest.ts
+++ b/ui/src/common/query_result_unittest.ts
@@ -300,3 +300,45 @@
   }
   expect(() => qr.iter({x_3: NUM})).toThrowError(/\bx_3\b.*not found/);
 });
+
+
+test('QueryResult.WaitMoreRows', async () => {
+  const batchA = QueryResultProto.CellsBatch.create({
+    cells: [T.CELL_VARINT],
+    varintCells: [42],
+    isLastBatch: false,
+  });
+  const resProtoA = QueryResultProto.create({
+    columnNames: ['a_int'],
+    batch: [batchA],
+  });
+
+  const qr = createQueryResult({query: 'Some query'});
+  qr.appendResultBatch(QueryResultProto.encode(resProtoA).finish());
+
+  const batchB = QueryResultProto.CellsBatch.create({
+    cells: [T.CELL_VARINT],
+    varintCells: [43],
+    isLastBatch: true,
+  });
+  const resProtoB = QueryResultProto.create({
+    columnNames: [],
+    batch: [batchB],
+  });
+
+  const waitPromise = qr.waitMoreRows();
+  const appendPromise = new Promise<void>((resolve, _) => {
+    setTimeout(() => {
+      qr.appendResultBatch(QueryResultProto.encode(resProtoB).finish());
+      resolve();
+    }, 0);
+  });
+
+  expect(qr.isComplete()).toBe(false);
+  expect(qr.numRows()).toBe(1);
+
+  await Promise.all([waitPromise, appendPromise]);
+
+  expect(qr.isComplete()).toBe(true);
+  expect(qr.numRows()).toBe(2);
+});