File: tasks.sql

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (712 lines) | stat: -rw-r--r-- 22,641 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
-- Copyright 2023 The Chromium Authors
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.

-- Checks if slice has an ancestor with provided name.
CREATE PERFETTO FUNCTION _has_parent_slice_with_name(
    -- Id of the slice to check parents of.
    id LONG,
    -- Name of potential ancestor slice.
    parent_name STRING
)
-- Whether `parent_name` is a name of an ancestor slice.
RETURNS BOOL AS
SELECT
  EXISTS(
    SELECT
      1
    FROM ancestor_slice($id)
    WHERE
      name = $parent_name
    LIMIT 1
  );

-- Returns the mojo ipc hash for a given task, looking it up from the
-- argument of descendant ScopedSetIpcHash slice.
-- This is relevant only for the older Chrome traces, where mojo IPC
-- hash was reported in a separate ScopedSetIpcHash slice.
CREATE PERFETTO FUNCTION _extract_mojo_ipc_hash(
    slice_id LONG
)
RETURNS LONG AS
SELECT
  extract_arg(arg_set_id, "chrome_mojo_event_info.ipc_hash")
FROM descendant_slice($slice_id)
WHERE
  name = "ScopedSetIpcHash"
ORDER BY
  id
LIMIT 1;

-- Returns the frame type (main frame vs subframe) for key navigation tasks
-- which capture the associated RenderFrameHost in an argument.
CREATE PERFETTO FUNCTION _extract_frame_type(
    slice_id LONG
)
RETURNS LONG AS
SELECT
  extract_arg(arg_set_id, "render_frame_host.frame_type")
FROM descendant_slice($slice_id)
WHERE
  name IN ("RenderFrameHostImpl::BeginNavigation", "RenderFrameHostImpl::DidCommitProvisionalLoad", "RenderFrameHostImpl::DidCommitSameDocumentNavigation", "RenderFrameHostImpl::DidStopLoading")
LIMIT 1;

-- Human-readable aliases for a few key navigation tasks.
CREATE PERFETTO FUNCTION _human_readable_navigation_task_name(
    task_name STRING
)
RETURNS STRING AS
SELECT
  CASE
    WHEN $task_name = "content.mojom.FrameHost message (hash=2168461044)"
    THEN "FrameHost::BeginNavigation"
    WHEN $task_name = "content.mojom.FrameHost message (hash=3561497419)"
    THEN "FrameHost::DidCommitProvisionalLoad"
    WHEN $task_name = "content.mojom.FrameHost message (hash=1421450774)"
    THEN "FrameHost::DidCommitSameDocumentNavigation"
    WHEN $task_name = "content.mojom.FrameHost message (hash=368650583)"
    THEN "FrameHost::DidStopLoading"
  END;

-- Takes a task name and formats it correctly for scheduler tasks.
CREATE PERFETTO FUNCTION _format_scheduler_task_name(
    task_name STRING
)
RETURNS STRING AS
SELECT
  printf("RunTask(posted_from=%s)", $task_name);

-- Takes the category and determines whether it is "Java" only, as opposed to
-- "toplevel,Java".
CREATE PERFETTO FUNCTION _java_not_top_level_category(
    category STRING
)
RETURNS BOOL AS
SELECT
  $category GLOB "*Java*" AND NOT $category GLOB "*toplevel*";

-- Takes the category and determines whether is any valid
-- toplevel category or combination of categories.
CREATE PERFETTO FUNCTION _any_top_level_category(
    category STRING
)
RETURNS BOOL AS
SELECT
  $category IN ("toplevel", "toplevel,viz", "toplevel,Java");

-- TODO(altimin): the situations with kinds in this file is a bit of a mess.
-- The idea is that it should work as `type` in the `slice` table, pointing to
-- a "child" table with more information about the task (e.g. posted_from for
-- scheduler tasks). Currently this is not the case and needs a cleanup.
-- Also we should align this with how table inheritance should work for
-- `CREATE PERFETTO TABLE`.

-- Get task type for a given task kind.
CREATE PERFETTO FUNCTION _get_java_views_task_type(
    kind STRING
)
RETURNS STRING AS
SELECT
  CASE $kind
    WHEN "Choreographer"
    THEN "choreographer"
    WHEN "SingleThreadProxy::BeginMainFrame"
    THEN "ui_thread_begin_main_frame"
  END;

-- All slices corresponding to receiving mojo messages.
-- On the newer Chrome versions, it's just "Receive mojo message" and
-- "Receive mojo reply" slices (or "Receive {mojo_message_name}" if
-- built with `extended_tracing_enabled`. On legacy Chrome versions,
-- other appropriate messages (like "Connector::DispatchMessage") are used.
--
-- @column STRING interface_name    Name of the IPC interface.
-- @column INT ipc_hash             Hash of a message name.
-- @column STRING message_type      Either 'message' or 'reply'.
-- @column INT id                   Slice id.
--
-- Note: this might include messages received within a sync mojo call.
-- TODO(altimin): This should use EXTEND_TABLE when it becomes available.
CREATE PERFETTO TABLE _chrome_mojo_slices AS
WITH
  -- Select all new-style (post crrev.com/c/3270337) mojo slices and
  -- generate |task_name| for them.
  -- If extended tracing is enabled, the slice name will have the full method
  -- name (i.e. "Receive content::mojom::FrameHost::DidStopLoading") and we
  -- should use it as a full name.
  -- If extended tracing is not enabled, we should include the interface name
  -- and method hash into the full name.
  new_mojo_slices AS (
    SELECT
      extract_arg(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag") AS interface_name,
      extract_arg(arg_set_id, "chrome_mojo_event_info.ipc_hash") AS ipc_hash,
      CASE name
        WHEN "Receive mojo message"
        THEN "message"
        WHEN "Receive mojo reply"
        THEN "reply"
      END AS message_type,
      id
    FROM slice
    WHERE
      category GLOB '*toplevel*' AND name GLOB 'Receive *'
  ),
  -- Select old-style slices for channel-associated mojo events.
  old_associated_mojo_slices AS (
    SELECT
      name AS interface_name,
      _extract_mojo_ipc_hash(id) AS ipc_hash,
      "message" AS message_type,
      id
    FROM slice
    WHERE
      category GLOB "*mojom*" AND name GLOB '*.mojom.*'
  ),
  -- Select old-style slices for non-(channel-associated) mojo events.
  old_non_associated_mojo_slices AS (
    SELECT
      coalesce(
        extract_arg(arg_set_id, "chrome_mojo_event_info.watcher_notify_interface_tag"),
        extract_arg(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag")
      ) AS interface_name,
      _extract_mojo_ipc_hash(id) AS ipc_hash,
      "message" AS message_type,
      id
    FROM slice
    WHERE
      category GLOB "*toplevel*" AND name = "Connector::DispatchMessage"
  ),
  merged AS (
    -- Merge all mojo slices.
    SELECT
      *
    FROM new_mojo_slices
    UNION ALL
    SELECT
      *
    FROM old_associated_mojo_slices
    UNION ALL
    SELECT
      *
    FROM old_non_associated_mojo_slices
  )
SELECT
  *
FROM merged
ORDER BY
  id;

-- This table contains a list of slices corresponding to the _representative_
-- Chrome Java view operations.
-- These are the outermost Java view slices after filtering out generic framework views
-- (like FitWindowsLinearLayout) and selecting the outermost slices from the remaining ones.
--
-- @column id INT                       Slice id.
-- @column ts INT                       Timestamp.
-- @column dur INT                      Duration.
-- @column name STRING                  Name of the view.
-- @column is_software_screenshot BOOL  Whether this slice is a part of non-accelerated
--                                      capture toolbar screenshot.
-- @column is_hardware_screenshot BOOL  Whether this slice is a part of accelerated
--                                      capture toolbar screenshot.
CREATE PERFETTO TABLE _chrome_java_views AS
WITH
  -- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them.
  java_slices_with_trimmed_names AS (
    SELECT
      id,
      replace(
        replace(
          replace(replace(replace(s1.name, ".draw", ""), ".onLayout", ""), ".onMeasure", ""),
          ".Layout",
          ""
        ),
        ".Measure",
        ""
      ) AS name,
      ts,
      dur
    FROM slice AS s1
    -- Ensure that toplevel Java slices are not included, as they may be logged
    -- with either category = "toplevel" or category = "toplevel,Java".
    -- Also filter out the zero duration slices as an attempt to reduce noise as
    -- "Java" category contains misc events (as it's hard to add new categories).
    WHERE
      _java_not_top_level_category(category) AND dur > 0
  ),
  -- We filter out generic slices from various UI frameworks which don't tell us much about
  -- what exactly this view is doing.
  interesting_java_slices AS (
    SELECT
      id,
      name,
      ts,
      dur
    FROM java_slices_with_trimmed_names
    -- The names below correspond respectively to:
    -- * AndroidX.
    -- * Other non-Chrome UI libraries.
    -- * Generic Chrome frameworks.
    -- * Non-specific Chrome slices.
    -- * Screenshots custom annotations.
    -- * Non-bytecode generated slices.
    WHERE
      NOT name IN ("FitWindowsFrameLayout", "FitWindowsLinearLayout", "ContentFrameLayout", "CoordinatorLayout")
      AND NOT name IN ("ComponentHost")
      AND NOT name IN ("CompositorView:finalizeLayers", "CompositorViewHolder", "CompositorViewHolder:layout", "CompositorViewHolder:updateContentViewChildrenDimension", "CoordinatorLayoutForPointer", "OptimizedFrameLayout", "ViewResourceAdapter:getBitmap", "ViewResourceFrameLayout")
      AND NOT name IN ("AppCompatImageButton", "ScrollingBottomViewResourceFrameLayout")
      AND NOT name IN ("ViewResourceAdapter:captureWithHardwareDraw", "ViewResourceAdapter:captureWithSoftwareDraw")
      AND NOT name IN ("LayoutDriver:onUpdate")
  )
SELECT
  s1.*,
  -- While the parent slices are too generic to be used by themselves,
  -- they can provide some useful metadata.
  _has_parent_slice_with_name(s1.id, "ViewResourceAdapter:captureWithSoftwareDraw") AS is_software_screenshot,
  _has_parent_slice_with_name(s1.id, "ViewResourceAdapter:captureWithHardwareDraw") AS is_hardware_screenshot
FROM interesting_java_slices AS s1
-- We select "outermost" interesting slices: interesting slices which
-- do not another interesting slice in their parent chain.
WHERE
  (
    SELECT
      count()
    FROM ancestor_slice(s1.id) AS s2
    JOIN interesting_java_slices AS s3
      ON s2.id = s3.id
  ) = 0;

-- A list of slices corresponding to operations on interesting (non-generic)
-- Chrome Java views. The view is considered interested if it's not a system
-- (ContentFrameLayout) or generic library (CompositorViewHolder) views.
--
-- TODO(altimin): Add "columns_from slice" annotation.
-- TODO(altimin): convert this to EXTEND_TABLE when it becomes available.
CREATE PERFETTO VIEW chrome_java_views (
  -- Name of the view.
  filtered_name STRING,
  -- Whether this slice is a part of non-accelerated capture toolbar screenshot.
  is_software_screenshot BOOL,
  -- Whether this slice is a part of accelerated capture toolbar screenshot.
  is_hardware_screenshot BOOL,
  -- Slice id.
  slice_id LONG
) AS
SELECT
  java_view.name AS filtered_name,
  java_view.is_software_screenshot,
  java_view.is_hardware_screenshot,
  slice.id AS slice_id
FROM _chrome_java_views AS java_view
JOIN slice
  USING (id);

-- A list of Choreographer tasks (Android frame generation) in Chrome.
CREATE PERFETTO VIEW _chrome_choreographer_tasks AS
SELECT
  id,
  "Choreographer" AS kind,
  ts,
  dur,
  name
FROM slice
WHERE
  name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*";

-- Extract task's posted_from information from task's arguments.
CREATE PERFETTO FUNCTION _get_posted_from(
    arg_set_id LONG
)
RETURNS STRING AS
WITH
  posted_from AS (
    SELECT
      extract_arg($arg_set_id, "task.posted_from.file_name") AS file_name,
      extract_arg($arg_set_id, "task.posted_from.function_name") AS function_name
  )
SELECT
  file_name || ":" || function_name AS posted_from
FROM posted_from;

-- Selects the BeginMainFrame slices (which as posted from ScheduledActionSendBeginMainFrame),
-- used for root-level processing. In top-level/Java based slices, these will correspond to the
-- ancestor of descendant slices; in long-task tracking, these tasks will be
-- on a custom track and will need to be associated with children by timestamp
-- and duration. Corresponds with the Choreographer root slices in
-- chrome_choreographer_tasks below.
--
-- Schema:
-- @column is            The slice id.
-- @column kind          The type of Java slice.
-- @column ts            The timestamp of the slice.
-- @column name          The name of the slice.
CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices(
    name STRING
)
RETURNS TABLE (
  id LONG,
  kind STRING,
  ts TIMESTAMP,
  dur DURATION,
  name STRING
) AS
SELECT
  id,
  "SingleThreadProxy::BeginMainFrame" AS kind,
  ts,
  dur,
  name
FROM slice
WHERE
  (
    name = $name
    AND _get_posted_from(arg_set_id) = "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame"
  );

-- A list of Chrome tasks which were performing operations with Java views,
-- together with the names of these views.
-- @column id INT            Slice id.
-- @column kind STRING       Type of the task.
-- @column java_views STRING Concatenated names of Java views used by the task.
CREATE PERFETTO VIEW _chrome_slices_with_java_views AS
WITH
  -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and
  -- Choreographer frames (which are looper tasks).
  root_slices AS (
    SELECT
      id,
      kind
    FROM _select_begin_main_frame_java_slices('ThreadControllerImpl::RunTask')
    UNION ALL
    SELECT
      id,
      kind
    FROM _chrome_choreographer_tasks
  ),
  -- Intermediate step to allow us to sort java view names.
  root_slice_and_java_view_not_grouped AS (
    SELECT
      root.id,
      root.kind,
      java_view.name AS java_view_name
    FROM root_slices AS root, descendant_slice(root.id) AS child
    JOIN _chrome_java_views AS java_view
      ON java_view.id = child.id
  )
SELECT
  root.id,
  root.kind,
  GROUP_CONCAT(DISTINCT java_view.java_view_name) AS java_views
FROM root_slices AS root
LEFT JOIN root_slice_and_java_view_not_grouped AS java_view
  USING (id)
GROUP BY
  root.id;

-- A list of tasks executed by Chrome scheduler.
CREATE PERFETTO TABLE _chrome_scheduler_tasks AS
SELECT
  id
FROM slice
WHERE
  category GLOB "*toplevel*"
  AND (
    name = "ThreadControllerImpl::RunTask" OR name = "ThreadPool_RunTask"
  )
ORDER BY
  id;

-- A list of tasks executed by Chrome scheduler.
CREATE PERFETTO VIEW chrome_scheduler_tasks (
  -- Slice id.
  id LONG,
  -- Type.
  type STRING,
  -- Name of the task.
  name STRING,
  -- Timestamp.
  ts TIMESTAMP,
  -- Duration.
  dur DURATION,
  -- Utid of the thread this task run on.
  utid LONG,
  -- Name of the thread this task run on.
  thread_name STRING,
  -- Upid of the process of this task.
  upid LONG,
  -- Name of the process of this task.
  process_name STRING,
  -- Same as slice.track_id.
  track_id LONG,
  -- Same as slice.category.
  category STRING,
  -- Same as slice.depth.
  depth LONG,
  -- Same as slice.parent_id.
  parent_id LONG,
  -- Same as slice.arg_set_id.
  arg_set_id LONG,
  -- Same as slice.thread_ts.
  thread_ts TIMESTAMP,
  -- Same as slice.thread_dur.
  thread_dur DURATION,
  -- Source location where the PostTask was called.
  posted_from STRING
) AS
SELECT
  task.id,
  "chrome_scheduler_tasks" AS type,
  _format_scheduler_task_name(_get_posted_from(slice.arg_set_id)) AS name,
  slice.ts,
  slice.dur,
  thread.utid,
  thread.name AS thread_name,
  process.upid,
  process.name AS process_name,
  slice.track_id,
  slice.category,
  slice.depth,
  slice.parent_id,
  slice.arg_set_id,
  slice.thread_ts,
  slice.thread_dur,
  _get_posted_from(slice.arg_set_id) AS posted_from
FROM _chrome_scheduler_tasks AS task
JOIN slice
  USING (id)
JOIN thread_track
  ON slice.track_id = thread_track.id
JOIN thread
  USING (utid)
JOIN process
  USING (upid)
ORDER BY
  task.id;

-- Select the slice that might be the descendant mojo slice for the given task
-- slice if it exists.
CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate(
    slice_id LONG
)
RETURNS LONG AS
SELECT
  id
FROM descendant_slice($slice_id)
WHERE
  -- The tricky case here is dealing with sync mojo IPCs: we do not want to
  -- pick up sync IPCs when we are in a non-IPC task.
  -- So we look at all toplevel events and pick up the first one:
  -- for sync mojo messages, it will be "Send mojo message", which then
  -- will fail.
  -- Some events are excluded as they can legimately appear under "RunTask"
  -- before "Receive mojo message".
  category GLOB "*toplevel*"
  AND NOT name IN ("SimpleWatcher::OnHandleReady", "MessagePipe peer closed")
ORDER BY
  depth,
  ts
LIMIT 1;

CREATE PERFETTO FUNCTION _descendant_mojo_slice(
    slice_id LONG
)
RETURNS TABLE (
  task_name STRING
) AS
SELECT
  printf("%s %s (hash=%d)", mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name
FROM slice AS task
JOIN _chrome_mojo_slices AS mojo
  ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id)
WHERE
  task.id = $slice_id;

-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
-- IPCs / system callbacks) run by Chrome. For a given thread, the tasks
-- will not intersect.
--
-- @column task_name STRING  Name for the given task.
-- @column task_type STRING  Type of the task (e.g. "scheduler").
-- @column scheduling_delay LONG
CREATE PERFETTO TABLE _chrome_tasks AS
WITH
  -- Select slices from "toplevel" category which do not have another
  -- "toplevel" slice as ancestor. The possible cases include sync mojo messages
  -- and tasks in nested runloops. Toplevel events may also be logged as with
  -- the Java category.
  non_embedded_toplevel_slices AS (
    SELECT
      *
    FROM slice
    WHERE
      _any_top_level_category(category)
      AND (
        SELECT
          count()
        FROM ancestor_slice(slice.id) AS anc
        WHERE
          anc.category GLOB "*toplevel*" OR anc.category GLOB "*toplevel.viz*"
      ) = 0
  ),
  -- Select slices from "Java" category which do not have another "Java" or
  -- "toplevel" slice as parent. In the longer term they should probably belong
  -- to "toplevel" category as well, but for now this will have to do. Ensure
  -- that "Java" slices do not include "toplevel" slices as those would be
  -- handled elsewhere.
  non_embedded_java_slices AS (
    SELECT
      id,
      name AS task_name,
      "java" AS task_type
    FROM slice AS s
    WHERE
      _java_not_top_level_category(category)
      AND (
        SELECT
          count()
        FROM ancestor_slice(s.id) AS s2
        WHERE
          s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*"
      ) = 0
  ),
  -- Generate full names for tasks with java views.
  java_views_tasks AS (
    SELECT
      id,
      printf('%s(java_views=%s)', kind, java_views) AS task_name,
      _get_java_views_task_type(kind) AS task_type
    FROM _chrome_slices_with_java_views
  ),
  scheduler_tasks AS (
    SELECT
      id,
      name AS task_name,
      "scheduler" AS task_type
    FROM chrome_scheduler_tasks
  ),
  -- Select scheduler tasks which are used to run mojo messages and use the mojo names
  -- as full names for these slices.
  -- We restrict this to specific scheduler tasks which are expected to run mojo
  -- tasks due to sync mojo events, which also emit similar events.
  scheduler_tasks_with_mojo AS (
    SELECT
      -- We use the "RunTask" as the task, and pick up the name from its child
      -- "Receive mojo message" event.
      task.id,
      receive_message.task_name,
      "mojo" AS task_type
    FROM chrome_scheduler_tasks AS task, _descendant_mojo_slice(task.id) AS receive_message
    WHERE
      task.posted_from IN ("mojo/public/cpp/system/simple_watcher.cc:Notify", "mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify", "mojo/public/cpp/bindings/lib/connector.cc:PostDispatchNextMessageFromPipe", "ipc/ipc_mojo_bootstrap.cc:Accept")
  ),
  navigation_tasks AS (
    WITH
      tasks_with_readable_names AS (
        SELECT
          id,
          _human_readable_navigation_task_name(task_name) AS readable_name,
          coalesce(_extract_frame_type(id), 'unknown frame type') AS frame_type
        FROM scheduler_tasks_with_mojo
      )
    SELECT
      id,
      printf("%s (%s)", readable_name, frame_type) AS task_name,
      'navigation_task' AS task_type
    FROM tasks_with_readable_names
    WHERE
      readable_name IS NOT NULL
  ),
  -- Add scheduler and mojo full names to non-embedded slices from
  -- the "toplevel" category, with mojo ones taking precedence.
  non_embedded_toplevel_slices_with_task_name AS (
    SELECT
      task.id AS id,
      coalesce(
        navigation.task_name,
        java_views.task_name,
        mojo.task_name,
        scheduler.task_name,
        task.name
      ) AS name,
      coalesce(navigation.task_type, java_views.task_type, mojo.task_type, scheduler.task_type, "other") AS task_type
    FROM non_embedded_toplevel_slices AS task
    LEFT JOIN scheduler_tasks_with_mojo AS mojo
      ON mojo.id = task.id
    LEFT JOIN scheduler_tasks AS scheduler
      ON scheduler.id = task.id
    LEFT JOIN java_views_tasks AS java_views
      ON java_views.id = task.id
    LEFT JOIN navigation_tasks AS navigation
      ON navigation.id = task.id
  )
-- Merge slices from toplevel and Java categories.
SELECT
  *
FROM non_embedded_toplevel_slices_with_task_name
UNION ALL
SELECT
  *
FROM non_embedded_java_slices
ORDER BY
  id;

-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
-- IPCs / system callbacks) run by Chrome. For a given thread, the slices
-- corresponding to these tasks will not intersect.
CREATE PERFETTO VIEW chrome_tasks (
  -- Id for the given task, also the id of the slice this task corresponds to.
  id LONG,
  -- Name for the given task.
  name STRING,
  -- Type of the task (e.g. "scheduler").
  task_type STRING,
  -- Thread name.
  thread_name STRING,
  -- Utid.
  utid LONG,
  -- Process name.
  process_name STRING,
  -- Upid.
  upid LONG,
  -- Alias of |slice.ts|.
  ts TIMESTAMP,
  -- Alias of |slice.dur|.
  dur DURATION,
  -- Alias of |slice.track_id|.
  track_id LONG,
  -- Alias of |slice.category|.
  category STRING,
  -- Alias of |slice.arg_set_id|.
  arg_set_id LONG,
  -- Alias of |slice.thread_ts|.
  thread_ts TIMESTAMP,
  -- Alias of |slice.thread_dur|.
  thread_dur DURATION,
  -- STRING    Legacy alias for |name|.
  full_name STRING
) AS
SELECT
  cti.id,
  cti.name,
  task_type,
  thread.name AS thread_name,
  thread.utid,
  process.name AS process_name,
  thread.upid,
  s.ts,
  s.dur,
  s.track_id,
  s.category,
  s.arg_set_id,
  s.thread_ts,
  s.thread_dur,
  cti.name AS full_name
FROM _chrome_tasks AS cti
JOIN slice AS s
  ON cti.id = s.id
JOIN thread_track AS tt
  ON s.track_id = tt.id
JOIN thread
  USING (utid)
JOIN process
  USING (upid);