• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2024 The Android Open Source Project
3--
4-- Licensed under the Apache License, Version 2.0 (the "License");
5-- you may not use this file except in compliance with the License.
6-- You may obtain a copy of the License at
7--
8--     https://www.apache.org/licenses/LICENSE-2.0
9--
10-- Unless required by applicable law or agreed to in writing, software
11-- distributed under the License is distributed on an "AS IS" BASIS,
12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-- See the License for the specific language governing permissions and
14-- limitations under the License.
15
16INCLUDE PERFETTO MODULE counters.intervals;
17
18INCLUDE PERFETTO MODULE android.battery.charging_states;
19
20INCLUDE PERFETTO MODULE android.screen_state;
21
22INCLUDE PERFETTO MODULE intervals.intersect;
23
24CREATE PERFETTO TABLE _job_states AS
25SELECT
26  t.id AS track_id,
27  s.ts,
28  s.id AS slice_id,
29  extract_arg(arg_set_id, 'scheduled_job_state_changed.job_name') AS job_name,
30  extract_arg(arg_set_id, 'scheduled_job_state_changed.attribution_node[0].uid') AS uid,
31  extract_arg(arg_set_id, 'scheduled_job_state_changed.state') AS state,
32  extract_arg(arg_set_id, 'scheduled_job_state_changed.internal_stop_reason') AS internal_stop_reason,
33  extract_arg(arg_set_id, 'scheduled_job_state_changed.public_stop_reason') AS public_stop_reason,
34  extract_arg(arg_set_id, 'scheduled_job_state_changed.effective_priority') AS effective_priority,
35  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_battery_not_low_constraint') AS has_battery_not_low_constraint,
36  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_charging_constraint') AS has_charging_constraint,
37  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_connectivity_constraint') AS has_connectivity_constraint,
38  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_content_trigger_constraint') AS has_content_trigger_constraint,
39  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_deadline_constraint') AS has_deadline_constraint,
40  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_idle_constraint') AS has_idle_constraint,
41  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_storage_not_low_constraint') AS has_storage_not_low_constraint,
42  extract_arg(arg_set_id, 'scheduled_job_state_changed.has_timing_delay_constraint') AS has_timing_delay_constraint,
43  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_prefetch') = 1 AS is_prefetch,
44  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_requested_expedited_job') AS is_requested_expedited_job,
45  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_running_as_expedited_job') AS is_running_as_expedited_job,
46  extract_arg(arg_set_id, 'scheduled_job_state_changed.job_id') AS job_id,
47  extract_arg(arg_set_id, 'scheduled_job_state_changed.num_previous_attempts') AS num_previous_attempts,
48  extract_arg(arg_set_id, 'scheduled_job_state_changed.requested_priority') AS requested_priority,
49  extract_arg(arg_set_id, 'scheduled_job_state_changed.standby_bucket') AS standby_bucket,
50  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_periodic') AS is_periodic,
51  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_periodic') AS has_flex_constraint,
52  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_requested_as_user_initiated_job') AS is_requested_as_user_initiated_job,
53  extract_arg(arg_set_id, 'scheduled_job_state_changed.is_running_as_user_initiated_job') AS is_running_as_user_initiated_job,
54  extract_arg(arg_set_id, 'scheduled_job_state_changed.deadline_ms') AS deadline_ms,
55  extract_arg(arg_set_id, 'scheduled_job_state_changed.job_start_latency_ms') AS job_start_latency_ms,
56  extract_arg(arg_set_id, 'scheduled_job_state_changed.num_uncompleted_work_items') AS num_uncompleted_work_items,
57  extract_arg(arg_set_id, 'scheduled_job_state_changed.proc_state') AS proc_state
58FROM track AS t
59JOIN slice AS s
60  ON (
61    s.track_id = t.id
62  )
63WHERE
64  t.name = 'Statsd Atoms' AND s.name = 'scheduled_job_state_changed';
65
66CREATE PERFETTO TABLE _job_started AS
67WITH
68  cte AS (
69    SELECT
70      *,
71      lead(state, 1) OVER (PARTITION BY uid, job_name, job_id ORDER BY uid, job_name, job_id, ts) AS lead_state,
72      lead(ts, 1, trace_end()) OVER (PARTITION BY uid, job_name, job_id ORDER BY uid, job_name, job_id, ts) AS ts_lead,
73      --- Filter out statsd lossy issue.
74      lead(ts, 1) OVER (PARTITION BY uid, job_name, job_id ORDER BY uid, job_name, job_id, ts) IS NULL AS is_end_slice,
75      lead(internal_stop_reason, 1, 'INTERNAL_STOP_REASON_UNKNOWN') OVER (PARTITION BY uid, job_name, job_id ORDER BY uid, job_name, job_id, ts) AS lead_internal_stop_reason,
76      lead(public_stop_reason, 1, 'PUBLIC_STOP_REASON_UNKNOWN') OVER (PARTITION BY uid, job_name, job_id ORDER BY uid, job_name, job_id, ts) AS lead_public_stop_reason
77    FROM _job_states
78    WHERE
79      state != 'CANCELLED'
80  )
81SELECT
82  -- Job name is based on whether the tag and/or namespace are present:
83  -- 1. Both tag and namespace are present: @<namespace>@<tag>:<package name>
84  -- 2. Only tag is present:  <tag>:<package name>
85  -- 3. Only namespace is present: @<namespace>@<package name>/<class name>
86  CASE
87    WHEN substr(job_name, 1, 1) = '@'
88    THEN CASE
89      WHEN substr(str_split(job_name, '/', 1), 1, 3) = 'com'
90      THEN str_split(job_name, '/', 1)
91      ELSE str_split(str_split(job_name, '/', 0), '@', 2)
92    END
93    ELSE str_split(job_name, '/', 0)
94  END AS package_name,
95  CASE
96    WHEN substr(job_name, 1, 1) = '@'
97    THEN str_split(job_name, '@', 1)
98    ELSE str_split(job_name, '/', 1)
99  END AS job_namespace,
100  ts_lead - ts AS dur,
101  iif(lead_state = 'SCHEDULED', TRUE, FALSE) AS is_rescheduled,
102  *
103FROM cte
104WHERE
105  is_end_slice = FALSE
106  AND (
107    ts_lead - ts
108  ) > 0
109  AND state = 'STARTED'
110  AND lead_state IN ('FINISHED', 'SCHEDULED');
111
112CREATE PERFETTO TABLE _charging_screen_states AS
113SELECT
114  row_number() OVER () AS id,
115  ii.ts,
116  ii.dur,
117  c.charging_state,
118  s.screen_state
119FROM _interval_intersect!(
120  (android_charging_states, android_screen_state),
121  ()
122) AS ii
123JOIN android_charging_states AS c
124  ON c.id = ii.id_0
125JOIN android_screen_state AS s
126  ON s.id = ii.id_1;
127
128-- This table returns constraint changes that a
129-- job will go through in a single trace.
130--
131-- Values in this table are derived from the the `ScheduledJobStateChanged`
132-- atom. This table differs from the
133-- `android_job_scheduler_with_screen_charging_states` in this module
134-- (`android.job_scheduler_states`) by only having job constraint information.
135--
136-- See documentation for the `android_job_scheduler_with_screen_charging_states`
137-- for how tables in this module differ from `android_job_scheduler_events`
138-- table in the `android.job_scheduler` module and how to populate this table.
139CREATE PERFETTO TABLE android_job_scheduler_states (
140  -- Unique identifier for job scheduler state.
141  id ID,
142  -- Timestamp of job state slice.
143  ts TIMESTAMP,
144  -- Duration of job state slice.
145  dur DURATION,
146  -- Id of the slice.
147  slice_id JOINID(slice.id),
148  -- Name of the job (as named by the app).
149  job_name STRING,
150  -- Uid associated with job.
151  uid LONG,
152  -- Id of job (assigned by app for T- builds and system generated in U+
153  -- builds).
154  job_id LONG,
155  -- Package that the job belongs (ex: associated app).
156  package_name STRING,
157  -- Namespace of job.
158  job_namespace STRING,
159  -- Priority at which JobScheduler ran the job.
160  effective_priority LONG,
161  -- True if app requested job should run when the device battery is not low.
162  has_battery_not_low_constraint BOOL,
163  -- True if app requested job should run when the device is charging.
164  has_charging_constraint BOOL,
165  -- True if app requested job should run when device has connectivity.
166  has_connectivity_constraint BOOL,
167  -- True if app requested job should run when there is a content trigger.
168  has_content_trigger_constraint BOOL,
169  -- True if app requested there is a deadline by which the job should run.
170  has_deadline_constraint BOOL,
171  -- True if app requested job should run when device is idle.
172  has_idle_constraint BOOL,
173  -- True if app requested job should run when device storage is not low.
174  has_storage_not_low_constraint BOOL,
175  -- True if app requested job has a timing delay.
176  has_timing_delay_constraint BOOL,
177  -- True if app requested job should run within hours of app launch.
178  is_prefetch BOOL,
179  -- True if app requested that the job is run as an expedited job.
180  is_requested_expedited_job BOOL,
181  -- The job is run as an expedited job.
182  is_running_as_expedited_job BOOL,
183  -- Number of previous attempts at running job.
184  num_previous_attempts TIMESTAMP,
185  -- The requested priority at which the job should run.
186  requested_priority LONG,
187  -- The job's standby bucket (one of: Active, Working Set, Frequent, Rare,
188  -- Never, Restricted, Exempt).
189  standby_bucket STRING,
190  -- Job should run in intervals.
191  is_periodic BOOL,
192  -- True if the job should run as a flex job.
193  has_flex_constraint BOOL,
194  -- True is app has requested that a job be run as a user initiated job.
195  is_requested_as_user_initiated_job BOOL,
196  -- True if job is running as a user initiated job.
197  is_running_as_user_initiated_job BOOL,
198  -- Deadline that job has requested and valid if has_deadline_constraint is
199  -- true.
200  deadline_ms LONG,
201  -- The latency in ms between when a job is scheduled and when it actually
202  -- starts.
203  job_start_latency_ms LONG,
204  -- Number of uncompleted job work items.
205  num_uncompleted_work_items LONG,
206  -- Process state of the process responsible for running the job.
207  proc_state STRING,
208  -- Internal stop reason for a job.
209  internal_stop_reason STRING,
210  -- Public stop reason for a job.
211  public_stop_reason STRING
212) AS
213SELECT
214  row_number() OVER (ORDER BY ts) AS id,
215  ts,
216  dur,
217  slice_id,
218  job_name,
219  uid,
220  job_id,
221  package_name,
222  job_namespace,
223  effective_priority,
224  has_battery_not_low_constraint,
225  has_charging_constraint,
226  has_connectivity_constraint,
227  has_content_trigger_constraint,
228  has_deadline_constraint,
229  has_idle_constraint,
230  has_storage_not_low_constraint,
231  has_timing_delay_constraint,
232  is_prefetch,
233  is_requested_expedited_job,
234  is_running_as_expedited_job,
235  num_previous_attempts,
236  requested_priority,
237  standby_bucket,
238  is_periodic,
239  has_flex_constraint,
240  is_requested_as_user_initiated_job,
241  is_running_as_user_initiated_job,
242  deadline_ms,
243  job_start_latency_ms,
244  num_uncompleted_work_items,
245  proc_state,
246  lead_internal_stop_reason AS internal_stop_reason,
247  lead_public_stop_reason AS public_stop_reason
248FROM _job_started;
249
250-- This table returns the constraint, charging,
251-- and screen state changes that a job will go through
252-- in a single trace.
253--
254-- Values from this table are derived from
255-- the `ScheduledJobStateChanged` atom. This differs from the
256-- `android_job_scheduler_events` table in the `android.job_scheduler` module
257-- which is derived from ATrace the system server category
258-- (`atrace_categories: "ss"`).
259--
260-- This also differs from the `android_job_scheduler_states` in this module
261-- (`android.job_scheduler_states`) by providing charging and screen state
262-- changes.
263--
264-- To populate this table, enable the Statsd Tracing Config with the
265-- ATOM_SCHEDULED_JOB_STATE_CHANGED push atom id.
266-- https://perfetto.dev/docs/reference/trace-config-proto#StatsdTracingConfig
267--
268-- This table is preferred over `android_job_scheduler_events`
269-- since it contains more information and should be used whenever
270-- `ATOM_SCHEDULED_JOB_STATE_CHANGED` is available in a trace.
271CREATE PERFETTO TABLE android_job_scheduler_with_screen_charging_states (
272  -- Timestamp of job.
273  ts TIMESTAMP,
274  -- Duration of slice in ns.
275  dur DURATION,
276  -- Id of the slice.
277  slice_id JOINID(slice.id),
278  -- Name of the job (as named by the app).
279  job_name STRING,
280  -- Id of job (assigned by app for T- builds and system generated in U+
281  -- builds).
282  job_id LONG,
283  -- Uid associated with job.
284  uid LONG,
285  -- Duration of entire job in ns.
286  job_dur DURATION,
287  -- Package that the job belongs (ex: associated app).
288  package_name STRING,
289  -- Namespace of job.
290  job_namespace STRING,
291  -- Device charging state during job (one of: Charging, Discharging, Not charging,
292  -- Full, Unknown).
293  charging_state STRING,
294  -- Device screen state during job (one of: Screen off, Screen on, Always-on display
295  -- (doze), Unknown).
296  screen_state STRING,
297  -- Priority at which JobScheduler ran the job.
298  effective_priority LONG,
299  -- True if app requested job should run when the device battery is not low.
300  has_battery_not_low_constraint BOOL,
301  -- True if app requested job should run when the device is charging.
302  has_charging_constraint BOOL,
303  -- True if app requested job should run when device has connectivity.
304  has_connectivity_constraint BOOL,
305  -- True if app requested job should run when there is a content trigger.
306  has_content_trigger_constraint BOOL,
307  -- True if app requested there is a deadline by which the job should run.
308  has_deadline_constraint BOOL,
309  -- True if app requested job should run when device is idle.
310  has_idle_constraint BOOL,
311  -- True if app requested job should run when device storage is not low.
312  has_storage_not_low_constraint BOOL,
313  -- True if app requested job has a timing delay.
314  has_timing_delay_constraint BOOL,
315  -- True if app requested job should run within hours of app launch.
316  is_prefetch BOOL,
317  -- True if app requested that the job is run as an expedited job.
318  is_requested_expedited_job BOOL,
319  -- The job is run as an expedited job.
320  is_running_as_expedited_job BOOL,
321  -- Number of previous attempts at running job.
322  num_previous_attempts TIMESTAMP,
323  -- The requested priority at which the job should run.
324  requested_priority LONG,
325  -- The job's standby bucket (one of: Active, Working Set, Frequent, Rare,
326  -- Never, Restricted, Exempt).
327  standby_bucket STRING,
328  -- Job should run in intervals.
329  is_periodic BOOL,
330  -- True if the job should run as a flex job.
331  has_flex_constraint BOOL,
332  -- True is app has requested that a job be run as a user initiated job.
333  is_requested_as_user_initiated_job BOOL,
334  -- True if job is running as a user initiated job.
335  is_running_as_user_initiated_job BOOL,
336  -- Deadline that job has requested and valid if has_deadline_constraint is
337  -- true.
338  deadline_ms LONG,
339  -- The latency in ms between when a job is scheduled and when it actually
340  -- starts.
341  job_start_latency_ms LONG,
342  -- Number of uncompleted job work items.
343  num_uncompleted_work_items LONG,
344  -- Process state of the process responsible for running the job.
345  proc_state STRING,
346  -- Internal stop reason for a job.
347  internal_stop_reason STRING,
348  -- Public stop reason for a job.
349  public_stop_reason STRING
350) AS
351SELECT
352  ii.ts,
353  ii.dur,
354  js.slice_id,
355  js.job_name || '_' || js.job_id AS job_name,
356  js.uid,
357  js.job_id,
358  js.dur AS job_dur,
359  js.package_name,
360  js.job_namespace,
361  c.charging_state,
362  c.screen_state,
363  js.effective_priority,
364  js.has_battery_not_low_constraint,
365  js.has_charging_constraint,
366  js.has_connectivity_constraint,
367  js.has_content_trigger_constraint,
368  js.has_deadline_constraint,
369  js.has_idle_constraint,
370  js.has_storage_not_low_constraint,
371  js.has_timing_delay_constraint,
372  js.is_prefetch,
373  js.is_requested_expedited_job,
374  js.is_running_as_expedited_job,
375  js.num_previous_attempts,
376  js.requested_priority,
377  js.standby_bucket,
378  js.is_periodic,
379  js.has_flex_constraint,
380  js.is_requested_as_user_initiated_job,
381  js.is_running_as_user_initiated_job,
382  js.deadline_ms,
383  js.job_start_latency_ms,
384  js.num_uncompleted_work_items,
385  js.proc_state,
386  js.internal_stop_reason,
387  js.public_stop_reason
388FROM _interval_intersect!(
389        (_charging_screen_states,
390        android_job_scheduler_states),
391        ()
392      ) AS ii
393JOIN _charging_screen_states AS c
394  ON c.id = ii.id_0
395JOIN android_job_scheduler_states AS js
396  ON js.id = ii.id_1;
397