Merge "[parser] Parse ftrace task_newtask waker_utid"
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 29582c9..6e57384 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -1702,6 +1702,8 @@
   proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
                                        ThreadNamePriority::kFtrace);
   proc_tracker->AssociateThreads(source_utid, new_utid);
+
+  ThreadStateTracker::GetOrCreate(context_)->PushNewTaskEvent(timestamp, new_utid, source_utid);
 }
 
 void FtraceParser::ParseTaskRename(ConstBytes blob) {
diff --git a/src/trace_processor/importers/ftrace/thread_state_tracker.cc b/src/trace_processor/importers/ftrace/thread_state_tracker.cc
index 9ff75e3..227a90a 100644
--- a/src/trace_processor/importers/ftrace/thread_state_tracker.cc
+++ b/src/trace_processor/importers/ftrace/thread_state_tracker.cc
@@ -70,6 +70,12 @@
   AddOpenState(event_ts, utid, runnable_string_id_, base::nullopt, waker_utid);
 }
 
+void ThreadStateTracker::PushNewTaskEvent(int64_t event_ts,
+                                         UniqueTid utid,
+                                         UniqueTid waker_utid) {
+  AddOpenState(event_ts, utid, runnable_string_id_, base::nullopt, waker_utid);
+}
+
 void ThreadStateTracker::PushBlockedReason(
     UniqueTid utid,
     base::Optional<bool> io_wait,
diff --git a/src/trace_processor/importers/ftrace/thread_state_tracker.h b/src/trace_processor/importers/ftrace/thread_state_tracker.h
index af3ad4c..3f8b7a5 100644
--- a/src/trace_processor/importers/ftrace/thread_state_tracker.h
+++ b/src/trace_processor/importers/ftrace/thread_state_tracker.h
@@ -51,6 +51,10 @@
   // Will add a runnable state for utid and close the previously blocked one.
   void PushWakingEvent(int64_t event_ts, UniqueTid utid, UniqueTid waker_utid);
 
+  // Will add a runnable state for utid. For a new task there are no previous
+  // states to close.
+  void PushNewTaskEvent(int64_t event_ts, UniqueTid utid, UniqueTid waker_utid);
+
   // Updates the current blocked state for utid with blocked reason.
   void PushBlockedReason(UniqueTid utid,
                          base::Optional<bool> io_wait,
diff --git a/test/trace_processor/diff_tests/parsing/tests.py b/test/trace_processor/diff_tests/parsing/tests.py
index 1352521..69a8d94 100644
--- a/test/trace_processor/diff_tests/parsing/tests.py
+++ b/test/trace_processor/diff_tests/parsing/tests.py
@@ -1126,3 +1126,46 @@
         679375600673065,3797,385482,"__handle_mm_fault",0
         679375600673769,1726,385482,"alloc_pages_vma",1
         """))
+
+  # Kernel task_newtask waker_utid parsing
+  def test_task_newtask_waker_utid(self):
+    return DiffTestBlueprint(
+        trace=TextProto(r"""
+        packet {
+          first_packet_on_sequence: true
+          ftrace_events {
+            cpu: 1
+            event {
+              timestamp: 201315132677
+              pid: 518
+              task_newtask {
+                pid: 3294
+                comm: "adbd"
+                clone_flags: 18874368
+                oom_score_adj: -1000
+              }
+            }
+            event {
+              timestamp: 201319417828
+              pid: 518
+              task_newtask {
+                pid: 3295
+                comm: "adbd"
+                clone_flags: 4001536
+                oom_score_adj: -1000
+              }
+            }
+          }
+          trusted_uid: 9999
+          trusted_packet_sequence_id: 2
+          trusted_pid: 521
+          previous_packet_dropped: true
+        }
+        """),
+        query="""
+        SELECT waker_utid FROM thread_state
+        """,
+        out=Csv("""
+        "waker_utid"
+        1
+        """))
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 134d78b..4b4ee82 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -466,7 +466,7 @@
 
     // If this is the first sched slice for this utid or if the wakeup found
     // was after the previous slice then we know the wakeup was for this slice.
-    if (prevSchedResult.numRows() === 0 ||
+    if (prevSchedResult.numRows() !== 0 &&
         wakeupTs < prevSchedResult.firstRow({ts: NUM}).ts) {
       return undefined;
     }