File: input.sql

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 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 (281 lines) | stat: -rw-r--r-- 9,553 bytes parent folder | download | duplicates (6)
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
-- Copyright 2024 The Chromium Authors
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.

INCLUDE PERFETTO MODULE chrome.android_input;

INCLUDE PERFETTO MODULE intervals.intersect;

INCLUDE PERFETTO MODULE slices.with_context;

-- Processing steps of the Chrome input pipeline.
CREATE PERFETTO TABLE _chrome_input_pipeline_steps_no_input_type (
  -- Id of this Chrome input pipeline (LatencyInfo).
  latency_id LONG,
  -- Slice id
  slice_id LONG,
  -- The step timestamp.
  ts TIMESTAMP,
  -- Step duration.
  dur DURATION,
  -- Utid of the thread.
  utid LONG,
  -- Step name (ChromeLatencyInfo.step).
  step STRING,
  -- Input type.
  input_type STRING,
  -- Start time of the parent Chrome scheduler task (if any) of this step.
  task_start_time_ts TIMESTAMP
) AS
WITH
  steps_with_potential_duplicates AS (
    SELECT
      extract_arg(thread_slice.arg_set_id, 'chrome_latency_info.trace_id') AS latency_id,
      id AS slice_id,
      ts,
      dur,
      utid,
      extract_arg(thread_slice.arg_set_id, 'chrome_latency_info.step') AS step,
      extract_arg(thread_slice.arg_set_id, 'chrome_latency_info.input_type') AS input_type,
      ts - (
        extract_arg(thread_slice.arg_set_id, 'current_task.event_offset_from_task_start_time_us') * 1000
      ) AS task_start_time_ts
    FROM thread_slice
    WHERE
      NOT step IS NULL AND latency_id != -1
  ),
  steps_with_ordering AS (
    SELECT
      *,
      -- Partition the steps so that, if the same step (for the same input) was
      -- emitted more than once (e.g. due to b:390406106), the step ends up in
      -- the same partition as all its duplicates. This will enable us to
      -- deduplicate the steps later.
      -- If there are multiple STEP_RESAMPLE_SCROLL_EVENTS steps, we assume that
      -- the input was only dispatched after the last resampling, so we only
      -- care about the last STEP_RESAMPLE_SCROLL_EVENTS step. We don't have any
      -- preference for other steps but, for the sake of determinsm and
      -- consistency, let's always pick the last step.
      row_number() OVER (PARTITION BY latency_id, utid, step, input_type ORDER BY ts DESC) AS ordering_within_partition
    FROM steps_with_potential_duplicates
  )
SELECT
  latency_id,
  slice_id,
  ts,
  dur,
  utid,
  step,
  input_type,
  task_start_time_ts
FROM steps_with_ordering
WHERE
  -- This is where we actually remove duplicate steps.
  ordering_within_partition = 1
ORDER BY
  slice_id,
  ts;

-- Each row represents one input pipeline.
CREATE PERFETTO TABLE chrome_inputs (
  -- Id of this Chrome input pipeline (LatencyInfo).
  latency_id LONG,
  -- Input type.
  input_type STRING
) AS
SELECT
  -- Id of this Chrome input pipeline (LatencyInfo).
  latency_id,
  -- MIN selects the first non-null value.
  min(input_type) AS input_type
FROM _chrome_input_pipeline_steps_no_input_type
WHERE
  latency_id != -1
GROUP BY
  latency_id;

-- Since not all steps have associated input type (but all steps
-- for a given latency id should have the same input type),
-- populate input type for steps where it would be NULL.
CREATE PERFETTO TABLE chrome_input_pipeline_steps (
  -- Id of this Chrome input pipeline (LatencyInfo).
  latency_id LONG,
  -- Slice id
  slice_id LONG,
  -- The step timestamp.
  ts TIMESTAMP,
  -- Step duration.
  dur DURATION,
  -- Utid of the thread.
  utid LONG,
  -- Step name (ChromeLatencyInfo.step).
  step STRING,
  -- Input type.
  input_type STRING,
  -- Start time of the parent Chrome scheduler task (if any) of this step.
  task_start_time_ts TIMESTAMP
) AS
SELECT
  latency_id,
  slice_id,
  ts,
  dur,
  utid,
  step,
  chrome_inputs.input_type AS input_type,
  task_start_time_ts
FROM chrome_inputs
LEFT JOIN _chrome_input_pipeline_steps_no_input_type
  USING (latency_id)
WHERE
  chrome_inputs.input_type IS NOT NULL;

-- For each input, if it was coalesced into another input, get the other input's
-- latency id.
CREATE PERFETTO TABLE chrome_coalesced_inputs (
  -- The `latency_id` of the coalesced input.
  coalesced_latency_id LONG,
  -- The `latency_id` of the other input that the current input was coalesced
  -- into. Guaranteed to be different from `coalesced_latency_id`.
  presented_latency_id LONG
) AS
SELECT
  args.int_value AS coalesced_latency_id,
  latency_id AS presented_latency_id
FROM chrome_input_pipeline_steps AS step
JOIN slice
  USING (slice_id)
JOIN args
  USING (arg_set_id)
WHERE
  step.step = 'STEP_RESAMPLE_SCROLL_EVENTS'
  AND args.flat_key = 'chrome_latency_info.coalesced_trace_ids'
  AND coalesced_latency_id != presented_latency_id;

-- Each scroll update event (except flings) in Chrome starts its life as a touch
-- move event, which is then eventually converted to a scroll update itself.
-- Each of these events is represented by its own LatencyInfo. This table
-- contains a mapping between touch move events and scroll update events they
-- were converted into.
CREATE PERFETTO TABLE chrome_touch_move_to_scroll_update (
  -- Latency id of the touch move input (LatencyInfo).
  touch_move_latency_id LONG,
  -- Latency id of the corresponding scroll update input (LatencyInfo).
  scroll_update_latency_id LONG
) AS
WITH
  scroll_update_steps AS MATERIALIZED (
    SELECT
      *
    FROM chrome_input_pipeline_steps
    WHERE
      step = 'STEP_SEND_INPUT_EVENT_UI' AND input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
  ),
  -- By default, we map a scroll update event to an ancestor touch move event with
  -- STEP_TOUCH_EVENT_HANDLED.
  default_mapping AS MATERIALIZED (
    SELECT
      touch_move_handled_step.latency_id AS touch_move_latency_id,
      scroll_update_step.latency_id AS scroll_update_latency_id
    -- Performance optimization: we are interested in finding all of the
    -- scroll_update_steps which have a "touch_move_handled" parent: to do this,
    -- we intersect them and find all of the intersections which match
    -- a scroll_update_step.
    -- We are using `slice_id` as `id` as it's unique and 32-bit (unlike latency_id,
    -- which can be 64-bit).
    FROM _interval_intersect!(
    (
      (
        SELECT slice_id AS id, *
        FROM scroll_update_steps
        WHERE dur > 0
      ),
      (
        SELECT slice_id AS id, *
        FROM chrome_input_pipeline_steps step
        WHERE step = 'STEP_TOUCH_EVENT_HANDLED'
          AND dur > 0
      )
    ),
    (utid)
  ) AS ii
    JOIN scroll_update_steps AS scroll_update_step
      ON ii.id_0 = scroll_update_step.slice_id
    JOIN chrome_input_pipeline_steps AS touch_move_handled_step
      ON ii.id_1 = touch_move_handled_step.slice_id
    -- If intersection matches the `scroll_update_step`, then it means that
    -- `touch_move_handled_step` is an ancestor of `scroll_update_step`.
    WHERE
      ii.ts = scroll_update_step.ts AND ii.dur = scroll_update_step.dur
  ),
  -- In the rare case where there are no touch handlers in the renderer, there's
  -- no ancestor touch move event with STEP_TOUCH_EVENT_HANDLED. In that case, we
  -- try to fall back to an ancestor touch move event with
  -- STEP_SEND_INPUT_EVENT_UI instead.
  fallback_mapping AS MATERIALIZED (
    SELECT
      send_touch_move_step.latency_id AS touch_move_latency_id,
      scroll_update_step.latency_id AS scroll_update_latency_id
    -- See the comment in the default_mapping CTE for an explanation what's going on here.
    FROM _interval_intersect!(
    (
      (
        SELECT slice_id AS id, *
        FROM scroll_update_steps
        WHERE dur > 0
      ),
      (
        SELECT slice_id AS id, *
        FROM chrome_input_pipeline_steps step
        WHERE step = 'STEP_SEND_INPUT_EVENT_UI'
          AND input_type = 'TOUCH_MOVE_EVENT'
          AND dur > 0
      )
    ),
    (utid)
  ) AS ii
    JOIN scroll_update_steps AS scroll_update_step
      ON ii.id_0 = scroll_update_step.slice_id
    JOIN chrome_input_pipeline_steps AS send_touch_move_step
      ON ii.id_1 = send_touch_move_step.slice_id
    WHERE
      ii.ts = scroll_update_step.ts AND ii.dur = scroll_update_step.dur
  ),
  -- We ideally would want to do a FULL JOIN here, but it is very slow in SQLite,
  -- so instead we are doing UNION + two LEFT JOINs.
  scroll_update_latency_ids AS (
    SELECT
      scroll_update_latency_id
    FROM default_mapping
    UNION
    SELECT
      scroll_update_latency_id
    FROM fallback_mapping
  )
SELECT
  coalesce(default_mapping.touch_move_latency_id, fallback_mapping.touch_move_latency_id) AS touch_move_latency_id,
  scroll_update_latency_id
FROM scroll_update_latency_ids
LEFT JOIN default_mapping
  USING (scroll_update_latency_id)
LEFT JOIN fallback_mapping
  USING (scroll_update_latency_id);

-- Matches Android input id to the corresponding touch move event.
CREATE PERFETTO TABLE chrome_dispatch_android_input_event_to_touch_move (
  -- Input id (assigned by the system, used by InputReader and InputDispatcher)
  android_input_id STRING,
  -- Latency id.
  touch_move_latency_id LONG
) AS
SELECT
  chrome_deliver_android_input_event.android_input_id,
  latency_id AS touch_move_latency_id
FROM chrome_deliver_android_input_event
LEFT JOIN chrome_input_pipeline_steps
  USING (utid)
WHERE
  chrome_input_pipeline_steps.input_type = 'TOUCH_MOVE_EVENT'
  AND chrome_input_pipeline_steps.step = 'STEP_SEND_INPUT_EVENT_UI'
  AND chrome_deliver_android_input_event.ts <= chrome_input_pipeline_steps.ts
  AND chrome_deliver_android_input_event.ts + chrome_deliver_android_input_event.dur >= chrome_input_pipeline_steps.ts + chrome_input_pipeline_steps.dur;