Merge "ui: Remove unused code in omnibox"
diff --git a/bazel/proto_gen.bzl b/bazel/proto_gen.bzl
index 14e7e75..50f5747 100644
--- a/bazel/proto_gen.bzl
+++ b/bazel/proto_gen.bzl
@@ -82,14 +82,17 @@
         executable = ctx.executable.protoc,
         arguments = arguments,
     )
+    cc_files = depset([f for f in out_files if f.path.endswith(".cc")])
+    h_files = depset([f for f in out_files if f.path.endswith(".h")])
     return [
-        DefaultInfo(files = depset(out_files)),
+        DefaultInfo(files = cc_files),
         OutputGroupInfo(
-            cc = depset([f for f in out_files if f.path.endswith(".cc")]),
-            h = depset([f for f in out_files if f.path.endswith(".h")]),
+            cc = cc_files,
+            h = h_files,
         ),
     ]
 
+
 proto_gen = rule(
     attrs = {
         "deps": attr.label_list(
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
index 65ff4b0..af272f5 100644
--- a/bazel/rules.bzl
+++ b/bazel/rules.bzl
@@ -197,10 +197,13 @@
         output_group = "h",
     )
 
+    # The headers from the gen plugin have implicit dependencies
+    # on each other so will fail when compiled independently. Use
+    # textual_hdrs to indicate this to Bazel.
     perfetto_cc_library(
         name = name,
         srcs = [":" + name + "_gen"],
-        hdrs = [":" + name + "_gen_h"],
+        textual_hdrs = [":" + name + "_gen_h"],
         deps = [
             PERFETTO_CONFIG.root + ":libprotozero"
         ] + _cc_deps,
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index 7c8c4d4..394f431 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -1054,6 +1054,14 @@
   INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                     \
       TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
       TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(category_group, name, id)   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+                                   category_group, name, id,               \
+                                   TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(category_group, name, id)   \
+  INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+                                   category_group, name, id,             \
+                                   TRACE_EVENT_FLAG_COPY)
 #define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(          \
     category_group, name, id, timestamp)                                \
   INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                   \
diff --git a/src/trace_processor/importers/systrace/systrace_line_tokenizer.cc b/src/trace_processor/importers/systrace/systrace_line_tokenizer.cc
index b794aec..e7fa5e8 100644
--- a/src/trace_processor/importers/systrace/systrace_line_tokenizer.cc
+++ b/src/trace_processor/importers/systrace/systrace_line_tokenizer.cc
@@ -41,7 +41,7 @@
 
 SystraceLineTokenizer::SystraceLineTokenizer()
     : line_matcher_(std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)"
-                               R"([a-zA-Z0-9.]{0,4}\s+(\d+\.\d+):\s+(\S+):)")) {
+                               R"([a-zA-Z0-9.]{0,5}\s+(\d+\.\d+):\s+(\S+):)")) {
 }
 
 // TODO(hjd): This should be more robust to being passed random input.
diff --git a/src/trace_processor/sqlite/span_join_operator_table.cc b/src/trace_processor/sqlite/span_join_operator_table.cc
index fd9d897..069d986 100644
--- a/src/trace_processor/sqlite/span_join_operator_table.cc
+++ b/src/trace_processor/sqlite/span_join_operator_table.cc
@@ -159,6 +159,15 @@
   CreateSchemaColsForDefn(t1_defn_, &cols);
   CreateSchemaColsForDefn(t2_defn_, &cols);
 
+  // Check if any column has : in its name. This often happens when SELECT *
+  // is used to create a view with the same column name in two joined tables.
+  for (const auto& col : cols) {
+    if (col.name().find(':') != std::string::npos) {
+      return util::ErrStatus("SPAN_JOIN: column %s has illegal character :",
+                             col.name().c_str());
+    }
+  }
+
   if (auto opt_dupe_col = HasDuplicateColumns(cols)) {
     return util::ErrStatus(
         "SPAN_JOIN: column %s present in both tables %s and %s",
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 6cad41b..ccb4bf3 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -516,12 +516,14 @@
     state.currentHeapProfileFlamegraph.focusRegex = args.focusRegex;
   },
 
-  selectChromeSlice(state: StateDraft, args: {id: number, trackId: string}):
+  selectChromeSlice(
+      state: StateDraft, args: {id: number, trackId: string, table: string}):
       void {
         state.currentSelection = {
           kind: 'CHROME_SLICE',
           id: args.id,
-          trackId: args.trackId
+          trackId: args.trackId,
+          table: args.table
         };
       },
 
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 49e5a98..b61218d 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -193,6 +193,7 @@
 export interface ChromeSliceSelection {
   kind: 'CHROME_SLICE';
   id: number;
+  table: string;
 }
 
 export interface ThreadStateSelection {
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 57c8ad8..34dbfd1 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -72,14 +72,23 @@
               globals.publish('CounterDetails', selected);
             }
           });
-    } else if (selectedKind === 'SLICE') {
+    } else if (selection.kind === 'SLICE') {
       this.sliceDetails(selectedId as number);
-    } else if (selectedKind === 'CHROME_SLICE') {
-      const sqlQuery = `
+    } else if (selection.kind === 'CHROME_SLICE') {
+      const table = selection.table;
+      let sqlQuery = `
         SELECT ts, dur, name, cat, arg_set_id
         FROM slice
         WHERE id = ${selectedId}
       `;
+      // TODO(b/155483804): This is a hack to ensure annotation slices are
+      // selectable for now. We should tidy this up when improving this class.
+      if (table === 'annotation') {
+        sqlQuery = `
+        select ts, dur, name, cat, -1
+        from annotation_slice
+        where id = ${selectedId}`;
+      }
       this.args.engine.query(sqlQuery).then(result => {
         // Check selection is still the same on completion of query.
         const selection = globals.state.currentSelection;
@@ -92,7 +101,9 @@
           const category = result.columns[3].stringValues![0];
           const argId = result.columns[4].longValues![0] as number;
           const argsAsync = this.getArgs(argId);
-          const descriptionAsync = this.describeSlice(selectedId);
+          // Don't fetch descriptions for annotation slices.
+          const describeId = table === 'annotation' ? -1 : selectedId as number;
+          const descriptionAsync = this.describeSlice(describeId);
           Promise.all([argsAsync, descriptionAsync])
               .then(([args, description]) => {
                 const selected: SliceDetails = {
@@ -100,7 +111,7 @@
                   dur,
                   category,
                   name,
-                  id: selectedId,
+                  id: selectedId as number,
                   args,
                   description,
                 };
@@ -113,6 +124,7 @@
 
   async describeSlice(id: number): Promise<Map<string, string>> {
     const map = new Map<string, string>();
+    if (id === -1) return map;
     const query = `
       select description, doc_link
       from describe_slice
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index a18e05a..b165d2b 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -1008,6 +1008,7 @@
         ts BIG INT,
         dur BIG INT,
         depth INT,
+        cat STRING,
         name STRING,
         PRIMARY KEY (track_id, ts)
       ) WITHOUT ROWID;
@@ -1034,13 +1035,14 @@
           WHERE track_type = 'slice'
         `);
         await engine.query(`
-          INSERT INTO annotation_slice(id, track_id, ts, dur, depth, name)
+          INSERT INTO annotation_slice(id, track_id, ts, dur, depth, cat, name)
           SELECT
-            -1 as id,
+            row_number() over (order by ts) as id,
             t.id AS track_id,
             ts,
             dur,
             0 AS depth,
+            a.track_name as cat,
             slice_name AS name
           FROM ${metric}_annotations a
           JOIN annotation_slice_track t
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
index 4db56c6..65f46fe 100644
--- a/ui/src/frontend/search_handler.ts
+++ b/ui/src/frontend/search_handler.ts
@@ -79,6 +79,9 @@
   if (source === 'cpu') {
     globals.dispatch(Actions.selectSlice({id: currentId, trackId}));
   } else {
-    globals.dispatch(Actions.selectChromeSlice({id: currentId, trackId}));
+    // Search results only include slices from the slice table for now.
+    // When we include annotations we need to pass the correct table.
+    globals.dispatch(
+        Actions.selectChromeSlice({id: currentId, trackId, table: 'slice'}));
   }
 }
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 27d52c9..c477517 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -83,8 +83,8 @@
     horizontalScrollAndZoomToRange(sliceStart, sliceEnd);
     const sliceId = row.slice_id as number | undefined;
     if (sliceId !== undefined) {
-      globals.makeSelection(
-          Actions.selectChromeSlice({id: sliceId, trackId: uiTrackId}));
+      globals.makeSelection(Actions.selectChromeSlice(
+          {id: sliceId, trackId: uiTrackId, table: 'slice'}));
     }
   }
 
diff --git a/ui/src/tracks/chrome_slices/frontend.ts b/ui/src/tracks/chrome_slices/frontend.ts
index bd3d8c8..46bdf10 100644
--- a/ui/src/tracks/chrome_slices/frontend.ts
+++ b/ui/src/tracks/chrome_slices/frontend.ts
@@ -214,8 +214,11 @@
     if (data === undefined) return false;
     const sliceId = data.sliceIds[sliceIndex];
     if (sliceId !== undefined && sliceId !== -1) {
-      globals.makeSelection(Actions.selectChromeSlice(
-          {id: sliceId, trackId: this.trackState.id}));
+      globals.makeSelection(Actions.selectChromeSlice({
+        id: sliceId,
+        trackId: this.trackState.id,
+        table: this.config.namespace
+      }));
       return true;
     }
     return false;