xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.AndroidLongBatteryTracing/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 The Android Open Source Project
2*6dbdd20aSAndroid Build Coastguard Worker//
3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*6dbdd20aSAndroid Build Coastguard Worker//
7*6dbdd20aSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*6dbdd20aSAndroid Build Coastguard Worker//
9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License.
14*6dbdd20aSAndroid Build Coastguard Worker
15*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace';
16*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin';
17*6dbdd20aSAndroid Build Coastguard Workerimport {Engine} from '../../trace_processor/engine';
18*6dbdd20aSAndroid Build Coastguard Workerimport {createQuerySliceTrack} from '../../components/tracks/query_slice_track';
19*6dbdd20aSAndroid Build Coastguard Workerimport {CounterOptions} from '../../components/tracks/base_counter_track';
20*6dbdd20aSAndroid Build Coastguard Workerimport {createQueryCounterTrack} from '../../components/tracks/query_counter_track';
21*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace';
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Workerinterface ContainedTrace {
24*6dbdd20aSAndroid Build Coastguard Worker  uuid: string;
25*6dbdd20aSAndroid Build Coastguard Worker  subscription: string;
26*6dbdd20aSAndroid Build Coastguard Worker  trigger: string;
27*6dbdd20aSAndroid Build Coastguard Worker  // NB: these are millis.
28*6dbdd20aSAndroid Build Coastguard Worker  ts: number;
29*6dbdd20aSAndroid Build Coastguard Worker  dur: number;
30*6dbdd20aSAndroid Build Coastguard Worker}
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Workerconst PACKAGE_LOOKUP = `
33*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto table package_name_lookup as
34*6dbdd20aSAndroid Build Coastguard Worker  with installed as (
35*6dbdd20aSAndroid Build Coastguard Worker    select uid, string_agg(package_name, ',') as name
36*6dbdd20aSAndroid Build Coastguard Worker    from package_list
37*6dbdd20aSAndroid Build Coastguard Worker    where uid >= 10000
38*6dbdd20aSAndroid Build Coastguard Worker    group by 1
39*6dbdd20aSAndroid Build Coastguard Worker  ),
40*6dbdd20aSAndroid Build Coastguard Worker  system(uid, name) as (
41*6dbdd20aSAndroid Build Coastguard Worker    values
42*6dbdd20aSAndroid Build Coastguard Worker      (0, 'AID_ROOT'),
43*6dbdd20aSAndroid Build Coastguard Worker      (1000, 'AID_SYSTEM_USER'),
44*6dbdd20aSAndroid Build Coastguard Worker      (1001, 'AID_RADIO'),
45*6dbdd20aSAndroid Build Coastguard Worker      (1082, 'AID_ARTD')
46*6dbdd20aSAndroid Build Coastguard Worker  )
47*6dbdd20aSAndroid Build Coastguard Worker  select uid, name from installed
48*6dbdd20aSAndroid Build Coastguard Worker  union all
49*6dbdd20aSAndroid Build Coastguard Worker  select uid, name from system
50*6dbdd20aSAndroid Build Coastguard Worker  order by uid;
51*6dbdd20aSAndroid Build Coastguard Worker
52*6dbdd20aSAndroid Build Coastguard Worker  -- Adds a "package_name" column by joining on "uid" from the source table.
53*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto macro add_package_name(src TableOrSubquery) returns TableOrSubquery as (
54*6dbdd20aSAndroid Build Coastguard Worker    select A.*, ifnull(B.name, "uid=" || A.uid) as package_name
55*6dbdd20aSAndroid Build Coastguard Worker    from $src as A
56*6dbdd20aSAndroid Build Coastguard Worker    left join package_name_lookup as B
57*6dbdd20aSAndroid Build Coastguard Worker    on (B.uid = (A.uid % 100000))
58*6dbdd20aSAndroid Build Coastguard Worker  );
59*6dbdd20aSAndroid Build Coastguard Worker`;
60*6dbdd20aSAndroid Build Coastguard Worker
61*6dbdd20aSAndroid Build Coastguard Workerconst DEFAULT_NETWORK = `
62*6dbdd20aSAndroid Build Coastguard Worker  with base as (
63*6dbdd20aSAndroid Build Coastguard Worker      select
64*6dbdd20aSAndroid Build Coastguard Worker          ts,
65*6dbdd20aSAndroid Build Coastguard Worker          substr(s.name, 6) as conn
66*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
67*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'battery_stats.conn'
68*6dbdd20aSAndroid Build Coastguard Worker  ),
69*6dbdd20aSAndroid Build Coastguard Worker  diff as (
70*6dbdd20aSAndroid Build Coastguard Worker      select
71*6dbdd20aSAndroid Build Coastguard Worker          ts,
72*6dbdd20aSAndroid Build Coastguard Worker          conn,
73*6dbdd20aSAndroid Build Coastguard Worker          conn != lag(conn) over (order by ts) as keep
74*6dbdd20aSAndroid Build Coastguard Worker      from base
75*6dbdd20aSAndroid Build Coastguard Worker  )
76*6dbdd20aSAndroid Build Coastguard Worker  select
77*6dbdd20aSAndroid Build Coastguard Worker      ts,
78*6dbdd20aSAndroid Build Coastguard Worker      ifnull(lead(ts) over (order by ts), (select end_ts from trace_bounds)) - ts as dur,
79*6dbdd20aSAndroid Build Coastguard Worker      case
80*6dbdd20aSAndroid Build Coastguard Worker        when conn like '-1:%' then 'Disconnected'
81*6dbdd20aSAndroid Build Coastguard Worker        when conn like '0:%' then 'Modem'
82*6dbdd20aSAndroid Build Coastguard Worker        when conn like '1:%' then 'WiFi'
83*6dbdd20aSAndroid Build Coastguard Worker        when conn like '4:%' then 'VPN'
84*6dbdd20aSAndroid Build Coastguard Worker        else conn
85*6dbdd20aSAndroid Build Coastguard Worker      end as name
86*6dbdd20aSAndroid Build Coastguard Worker  from diff where keep is null or keep`;
87*6dbdd20aSAndroid Build Coastguard Worker
88*6dbdd20aSAndroid Build Coastguard Workerconst RADIO_TRANSPORT_TYPE = `
89*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto view radio_transport_data_conn as
90*6dbdd20aSAndroid Build Coastguard Worker  select ts, safe_dur AS dur, value_name as data_conn, value AS data_conn_val
91*6dbdd20aSAndroid Build Coastguard Worker  from android_battery_stats_state
92*6dbdd20aSAndroid Build Coastguard Worker  where track_name = "battery_stats.data_conn";
93*6dbdd20aSAndroid Build Coastguard Worker
94*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto view radio_transport_nr_state as
95*6dbdd20aSAndroid Build Coastguard Worker  select ts, safe_dur AS dur, value AS nr_state_val
96*6dbdd20aSAndroid Build Coastguard Worker  from android_battery_stats_state
97*6dbdd20aSAndroid Build Coastguard Worker  where track_name = "battery_stats.nr_state";
98*6dbdd20aSAndroid Build Coastguard Worker
99*6dbdd20aSAndroid Build Coastguard Worker  drop table if exists radio_transport_join;
100*6dbdd20aSAndroid Build Coastguard Worker  create virtual table radio_transport_join
101*6dbdd20aSAndroid Build Coastguard Worker  using span_left_join(radio_transport_data_conn, radio_transport_nr_state);
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto view radio_transport as
104*6dbdd20aSAndroid Build Coastguard Worker  select
105*6dbdd20aSAndroid Build Coastguard Worker    ts, dur,
106*6dbdd20aSAndroid Build Coastguard Worker    case data_conn_val
107*6dbdd20aSAndroid Build Coastguard Worker      -- On LTE with NR connected is 5G NSA.
108*6dbdd20aSAndroid Build Coastguard Worker      when 13 then iif(nr_state_val = 3, '5G (NSA)', data_conn)
109*6dbdd20aSAndroid Build Coastguard Worker      -- On NR with NR state present, is 5G SA.
110*6dbdd20aSAndroid Build Coastguard Worker      when 20 then iif(nr_state_val is null, '5G (SA or NSA)', '5G (SA)')
111*6dbdd20aSAndroid Build Coastguard Worker      else data_conn
112*6dbdd20aSAndroid Build Coastguard Worker    end as name
113*6dbdd20aSAndroid Build Coastguard Worker  from radio_transport_join;`;
114*6dbdd20aSAndroid Build Coastguard Worker
115*6dbdd20aSAndroid Build Coastguard Workerconst TETHERING = `
116*6dbdd20aSAndroid Build Coastguard Worker  with base as (
117*6dbdd20aSAndroid Build Coastguard Worker      select
118*6dbdd20aSAndroid Build Coastguard Worker          ts as ts_end,
119*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'network_tethering_reported.duration_millis') * 1000000 as dur
120*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
121*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
122*6dbdd20aSAndroid Build Coastguard Worker        and s.name = 'network_tethering_reported'
123*6dbdd20aSAndroid Build Coastguard Worker  )
124*6dbdd20aSAndroid Build Coastguard Worker  select ts_end - dur as ts, dur, 'Tethering' as name from base`;
125*6dbdd20aSAndroid Build Coastguard Worker
126*6dbdd20aSAndroid Build Coastguard Workerconst NETWORK_SUMMARY = `
127*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto table network_summary as
128*6dbdd20aSAndroid Build Coastguard Worker  with base as (
129*6dbdd20aSAndroid Build Coastguard Worker      select
130*6dbdd20aSAndroid Build Coastguard Worker          cast(ts / 5000000000 as int64) * 5000000000 AS ts,
131*6dbdd20aSAndroid Build Coastguard Worker          case
132*6dbdd20aSAndroid Build Coastguard Worker              when track_name glob '*wlan*' then 'wifi'
133*6dbdd20aSAndroid Build Coastguard Worker              when track_name glob '*rmnet*' then 'modem'
134*6dbdd20aSAndroid Build Coastguard Worker              else 'unknown'
135*6dbdd20aSAndroid Build Coastguard Worker          end as dev_type,
136*6dbdd20aSAndroid Build Coastguard Worker          package_name as pkg,
137*6dbdd20aSAndroid Build Coastguard Worker          sum(packet_length) AS value
138*6dbdd20aSAndroid Build Coastguard Worker      from android_network_packets
139*6dbdd20aSAndroid Build Coastguard Worker      where (track_name glob '*wlan*' or track_name glob '*rmnet*')
140*6dbdd20aSAndroid Build Coastguard Worker      group by 1,2,3
141*6dbdd20aSAndroid Build Coastguard Worker  ),
142*6dbdd20aSAndroid Build Coastguard Worker  zeroes as (
143*6dbdd20aSAndroid Build Coastguard Worker      select
144*6dbdd20aSAndroid Build Coastguard Worker          ts,
145*6dbdd20aSAndroid Build Coastguard Worker          dev_type,
146*6dbdd20aSAndroid Build Coastguard Worker          pkg,
147*6dbdd20aSAndroid Build Coastguard Worker          value
148*6dbdd20aSAndroid Build Coastguard Worker      from base
149*6dbdd20aSAndroid Build Coastguard Worker      union all
150*6dbdd20aSAndroid Build Coastguard Worker      select
151*6dbdd20aSAndroid Build Coastguard Worker          ts + 5000000000 as ts,
152*6dbdd20aSAndroid Build Coastguard Worker          dev_type,
153*6dbdd20aSAndroid Build Coastguard Worker          pkg,
154*6dbdd20aSAndroid Build Coastguard Worker          0 as value
155*6dbdd20aSAndroid Build Coastguard Worker      from base
156*6dbdd20aSAndroid Build Coastguard Worker  ),
157*6dbdd20aSAndroid Build Coastguard Worker  final as (
158*6dbdd20aSAndroid Build Coastguard Worker      select
159*6dbdd20aSAndroid Build Coastguard Worker          ts,
160*6dbdd20aSAndroid Build Coastguard Worker          dev_type,
161*6dbdd20aSAndroid Build Coastguard Worker          pkg,
162*6dbdd20aSAndroid Build Coastguard Worker          sum(value) as value
163*6dbdd20aSAndroid Build Coastguard Worker      from zeroes
164*6dbdd20aSAndroid Build Coastguard Worker      group by 1, 2, 3
165*6dbdd20aSAndroid Build Coastguard Worker  )
166*6dbdd20aSAndroid Build Coastguard Worker  select * from final where ts is not null`;
167*6dbdd20aSAndroid Build Coastguard Worker
168*6dbdd20aSAndroid Build Coastguard Workerconst MODEM_RIL_STRENGTH = `
169*6dbdd20aSAndroid Build Coastguard Worker  DROP VIEW IF EXISTS ScreenOn;
170*6dbdd20aSAndroid Build Coastguard Worker  CREATE VIEW ScreenOn AS
171*6dbdd20aSAndroid Build Coastguard Worker  SELECT ts, dur FROM (
172*6dbdd20aSAndroid Build Coastguard Worker      SELECT
173*6dbdd20aSAndroid Build Coastguard Worker          ts, value,
174*6dbdd20aSAndroid Build Coastguard Worker          LEAD(ts, 1, TRACE_END()) OVER (ORDER BY ts)-ts AS dur
175*6dbdd20aSAndroid Build Coastguard Worker      FROM counter, track ON (counter.track_id = track.id)
176*6dbdd20aSAndroid Build Coastguard Worker      WHERE track.name = 'ScreenState'
177*6dbdd20aSAndroid Build Coastguard Worker  ) WHERE value = 2;
178*6dbdd20aSAndroid Build Coastguard Worker
179*6dbdd20aSAndroid Build Coastguard Worker  DROP VIEW IF EXISTS RilSignalStrength;
180*6dbdd20aSAndroid Build Coastguard Worker  CREATE VIEW RilSignalStrength AS
181*6dbdd20aSAndroid Build Coastguard Worker  With RilMessages AS (
182*6dbdd20aSAndroid Build Coastguard Worker      SELECT
183*6dbdd20aSAndroid Build Coastguard Worker          ts, slice.name,
184*6dbdd20aSAndroid Build Coastguard Worker          LEAD(ts, 1, TRACE_END()) OVER (ORDER BY ts)-ts AS dur
185*6dbdd20aSAndroid Build Coastguard Worker      FROM slice, track
186*6dbdd20aSAndroid Build Coastguard Worker      ON (slice.track_id = track.id)
187*6dbdd20aSAndroid Build Coastguard Worker      WHERE track.name = 'RIL'
188*6dbdd20aSAndroid Build Coastguard Worker        AND slice.name GLOB 'UNSOL_SIGNAL_STRENGTH*'
189*6dbdd20aSAndroid Build Coastguard Worker  ),
190*6dbdd20aSAndroid Build Coastguard Worker  BandTypes(band_ril, band_name) AS (
191*6dbdd20aSAndroid Build Coastguard Worker      VALUES ("CellSignalStrengthLte:", "LTE"),
192*6dbdd20aSAndroid Build Coastguard Worker              ("CellSignalStrengthNr:", "NR")
193*6dbdd20aSAndroid Build Coastguard Worker  ),
194*6dbdd20aSAndroid Build Coastguard Worker  ValueTypes(value_ril, value_name) AS (
195*6dbdd20aSAndroid Build Coastguard Worker      VALUES ("rsrp=", "rsrp"),
196*6dbdd20aSAndroid Build Coastguard Worker              ("rssi=", "rssi")
197*6dbdd20aSAndroid Build Coastguard Worker  ),
198*6dbdd20aSAndroid Build Coastguard Worker  Extracted AS (
199*6dbdd20aSAndroid Build Coastguard Worker      SELECT ts, dur, band_name, value_name, (
200*6dbdd20aSAndroid Build Coastguard Worker          SELECT CAST(SUBSTR(key_str, start_idx+1, end_idx-start_idx-1) AS INT64) AS value
201*6dbdd20aSAndroid Build Coastguard Worker          FROM (
202*6dbdd20aSAndroid Build Coastguard Worker              SELECT key_str, INSTR(key_str, "=") AS start_idx, INSTR(key_str, " ") AS end_idx
203*6dbdd20aSAndroid Build Coastguard Worker              FROM (
204*6dbdd20aSAndroid Build Coastguard Worker                  SELECT SUBSTR(band_str, INSTR(band_str, value_ril)) AS key_str
205*6dbdd20aSAndroid Build Coastguard Worker                  FROM (SELECT SUBSTR(name, INSTR(name, band_ril)) AS band_str)
206*6dbdd20aSAndroid Build Coastguard Worker              )
207*6dbdd20aSAndroid Build Coastguard Worker          )
208*6dbdd20aSAndroid Build Coastguard Worker      ) AS value
209*6dbdd20aSAndroid Build Coastguard Worker      FROM RilMessages
210*6dbdd20aSAndroid Build Coastguard Worker      JOIN BandTypes
211*6dbdd20aSAndroid Build Coastguard Worker      JOIN ValueTypes
212*6dbdd20aSAndroid Build Coastguard Worker  )
213*6dbdd20aSAndroid Build Coastguard Worker  SELECT
214*6dbdd20aSAndroid Build Coastguard Worker  ts, dur, band_name, value_name, value,
215*6dbdd20aSAndroid Build Coastguard Worker  value_name || "=" || IIF(value = 2147483647, "unknown", ""||value) AS name,
216*6dbdd20aSAndroid Build Coastguard Worker  ROW_NUMBER() OVER (ORDER BY ts) as id,
217*6dbdd20aSAndroid Build Coastguard Worker  DENSE_RANK() OVER (ORDER BY band_name, value_name) AS track_id
218*6dbdd20aSAndroid Build Coastguard Worker  FROM Extracted;
219*6dbdd20aSAndroid Build Coastguard Worker
220*6dbdd20aSAndroid Build Coastguard Worker  DROP TABLE IF EXISTS RilScreenOn;
221*6dbdd20aSAndroid Build Coastguard Worker  CREATE VIRTUAL TABLE RilScreenOn
222*6dbdd20aSAndroid Build Coastguard Worker  USING SPAN_JOIN(RilSignalStrength PARTITIONED track_id, ScreenOn)`;
223*6dbdd20aSAndroid Build Coastguard Worker
224*6dbdd20aSAndroid Build Coastguard Workerconst MODEM_RIL_CHANNELS_PREAMBLE = `
225*6dbdd20aSAndroid Build Coastguard Worker  CREATE OR REPLACE PERFETTO FUNCTION EXTRACT_KEY_VALUE(source STRING, key_name STRING) RETURNS STRING AS
226*6dbdd20aSAndroid Build Coastguard Worker  SELECT SUBSTR(trimmed, INSTR(trimmed, "=")+1, INSTR(trimmed, ",") - INSTR(trimmed, "=") - 1)
227*6dbdd20aSAndroid Build Coastguard Worker  FROM (SELECT SUBSTR($source, INSTR($source, $key_name)) AS trimmed);`;
228*6dbdd20aSAndroid Build Coastguard Worker
229*6dbdd20aSAndroid Build Coastguard Workerconst MODEM_RIL_CHANNELS = `
230*6dbdd20aSAndroid Build Coastguard Worker  With RawChannelConfig AS (
231*6dbdd20aSAndroid Build Coastguard Worker      SELECT ts, slice.name AS raw_config
232*6dbdd20aSAndroid Build Coastguard Worker      FROM slice, track
233*6dbdd20aSAndroid Build Coastguard Worker      ON (slice.track_id = track.id)
234*6dbdd20aSAndroid Build Coastguard Worker      WHERE track.name = 'RIL'
235*6dbdd20aSAndroid Build Coastguard Worker      AND slice.name LIKE 'UNSOL_PHYSICAL_CHANNEL_CONFIG%'
236*6dbdd20aSAndroid Build Coastguard Worker  ),
237*6dbdd20aSAndroid Build Coastguard Worker  Attributes(attribute, attrib_name) AS (
238*6dbdd20aSAndroid Build Coastguard Worker      VALUES ("mCellBandwidthDownlinkKhz", "downlink"),
239*6dbdd20aSAndroid Build Coastguard Worker          ("mCellBandwidthUplinkKhz", "uplink"),
240*6dbdd20aSAndroid Build Coastguard Worker          ("mNetworkType", "network"),
241*6dbdd20aSAndroid Build Coastguard Worker          ("mBand", "band")
242*6dbdd20aSAndroid Build Coastguard Worker  ),
243*6dbdd20aSAndroid Build Coastguard Worker  Slots(idx, slot_name) AS (
244*6dbdd20aSAndroid Build Coastguard Worker      VALUES (0, "primary"),
245*6dbdd20aSAndroid Build Coastguard Worker          (1, "secondary 1"),
246*6dbdd20aSAndroid Build Coastguard Worker          (2, "secondary 2")
247*6dbdd20aSAndroid Build Coastguard Worker  ),
248*6dbdd20aSAndroid Build Coastguard Worker  Stage1 AS (
249*6dbdd20aSAndroid Build Coastguard Worker      SELECT *, IFNULL(EXTRACT_KEY_VALUE(STR_SPLIT(raw_config, "}, {", idx), attribute), "") AS name
250*6dbdd20aSAndroid Build Coastguard Worker      FROM RawChannelConfig
251*6dbdd20aSAndroid Build Coastguard Worker      JOIN Attributes
252*6dbdd20aSAndroid Build Coastguard Worker      JOIN Slots
253*6dbdd20aSAndroid Build Coastguard Worker  ),
254*6dbdd20aSAndroid Build Coastguard Worker  Stage2 AS (
255*6dbdd20aSAndroid Build Coastguard Worker      SELECT *, LAG(name) OVER (PARTITION BY idx, attribute ORDER BY ts) AS last_name
256*6dbdd20aSAndroid Build Coastguard Worker      FROM Stage1
257*6dbdd20aSAndroid Build Coastguard Worker  ),
258*6dbdd20aSAndroid Build Coastguard Worker  Stage3 AS (
259*6dbdd20aSAndroid Build Coastguard Worker      SELECT *, LEAD(ts, 1, TRACE_END()) OVER (PARTITION BY idx, attribute ORDER BY ts) - ts AS dur
260*6dbdd20aSAndroid Build Coastguard Worker      FROM Stage2 WHERE name != last_name
261*6dbdd20aSAndroid Build Coastguard Worker  )
262*6dbdd20aSAndroid Build Coastguard Worker  SELECT ts, dur, slot_name || "-" || attrib_name || "=" || name AS name
263*6dbdd20aSAndroid Build Coastguard Worker  FROM Stage3`;
264*6dbdd20aSAndroid Build Coastguard Worker
265*6dbdd20aSAndroid Build Coastguard Workerconst MODEM_CELL_RESELECTION = `
266*6dbdd20aSAndroid Build Coastguard Worker  with base as (
267*6dbdd20aSAndroid Build Coastguard Worker    select
268*6dbdd20aSAndroid Build Coastguard Worker        ts,
269*6dbdd20aSAndroid Build Coastguard Worker        s.name as raw_ril,
270*6dbdd20aSAndroid Build Coastguard Worker        ifnull(str_split(str_split(s.name, 'CellIdentityLte{', 1), ', operatorNames', 0),
271*6dbdd20aSAndroid Build Coastguard Worker            str_split(str_split(s.name, 'CellIdentityNr{', 1), ', operatorNames', 0)) as cell_id
272*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
273*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'RIL' and s.name like '%DATA_REGISTRATION_STATE%'
274*6dbdd20aSAndroid Build Coastguard Worker  ),
275*6dbdd20aSAndroid Build Coastguard Worker  base2 as (
276*6dbdd20aSAndroid Build Coastguard Worker    select
277*6dbdd20aSAndroid Build Coastguard Worker        ts,
278*6dbdd20aSAndroid Build Coastguard Worker        raw_ril,
279*6dbdd20aSAndroid Build Coastguard Worker        case
280*6dbdd20aSAndroid Build Coastguard Worker            when cell_id like '%earfcn%' then 'LTE ' || cell_id
281*6dbdd20aSAndroid Build Coastguard Worker            when cell_id like '%nrarfcn%' then 'NR ' || cell_id
282*6dbdd20aSAndroid Build Coastguard Worker            when cell_id is null then 'Unknown'
283*6dbdd20aSAndroid Build Coastguard Worker            else cell_id
284*6dbdd20aSAndroid Build Coastguard Worker        end as cell_id
285*6dbdd20aSAndroid Build Coastguard Worker    from base
286*6dbdd20aSAndroid Build Coastguard Worker  ),
287*6dbdd20aSAndroid Build Coastguard Worker  base3 as (
288*6dbdd20aSAndroid Build Coastguard Worker    select ts, cell_id , lag(cell_id) over (order by ts) as lag_cell_id, raw_ril
289*6dbdd20aSAndroid Build Coastguard Worker    from base2
290*6dbdd20aSAndroid Build Coastguard Worker  )
291*6dbdd20aSAndroid Build Coastguard Worker  select ts, 0 as dur, cell_id as name, raw_ril
292*6dbdd20aSAndroid Build Coastguard Worker  from base3
293*6dbdd20aSAndroid Build Coastguard Worker  where cell_id != lag_cell_id
294*6dbdd20aSAndroid Build Coastguard Worker  order by ts`;
295*6dbdd20aSAndroid Build Coastguard Worker
296*6dbdd20aSAndroid Build Coastguard Workerconst SUSPEND_RESUME = `
297*6dbdd20aSAndroid Build Coastguard Worker  SELECT
298*6dbdd20aSAndroid Build Coastguard Worker    ts,
299*6dbdd20aSAndroid Build Coastguard Worker    dur,
300*6dbdd20aSAndroid Build Coastguard Worker    'Suspended' AS name
301*6dbdd20aSAndroid Build Coastguard Worker  FROM android_suspend_state
302*6dbdd20aSAndroid Build Coastguard Worker  WHERE power_state = 'suspended'`;
303*6dbdd20aSAndroid Build Coastguard Worker
304*6dbdd20aSAndroid Build Coastguard Workerconst SCREEN_STATE = `
305*6dbdd20aSAndroid Build Coastguard Worker  WITH _counter AS (
306*6dbdd20aSAndroid Build Coastguard Worker    SELECT counter.id, ts, 0 AS track_id, value
307*6dbdd20aSAndroid Build Coastguard Worker    FROM counter
308*6dbdd20aSAndroid Build Coastguard Worker    JOIN counter_track ON counter_track.id = counter.track_id
309*6dbdd20aSAndroid Build Coastguard Worker    WHERE name = 'ScreenState'
310*6dbdd20aSAndroid Build Coastguard Worker  )
311*6dbdd20aSAndroid Build Coastguard Worker  SELECT
312*6dbdd20aSAndroid Build Coastguard Worker    ts,
313*6dbdd20aSAndroid Build Coastguard Worker    dur,
314*6dbdd20aSAndroid Build Coastguard Worker    CASE value
315*6dbdd20aSAndroid Build Coastguard Worker      WHEN 1 THEN 'Screen off'
316*6dbdd20aSAndroid Build Coastguard Worker      WHEN 2 THEN 'Screen on'
317*6dbdd20aSAndroid Build Coastguard Worker      WHEN 3 THEN 'Always-on display (doze)'
318*6dbdd20aSAndroid Build Coastguard Worker      ELSE 'unknown'
319*6dbdd20aSAndroid Build Coastguard Worker    END AS name
320*6dbdd20aSAndroid Build Coastguard Worker  FROM counter_leading_intervals!(_counter)`;
321*6dbdd20aSAndroid Build Coastguard Worker
322*6dbdd20aSAndroid Build Coastguard Worker// See DeviceIdleController.java for where these states come from and how
323*6dbdd20aSAndroid Build Coastguard Worker// they transition.
324*6dbdd20aSAndroid Build Coastguard Workerconst DOZE_LIGHT = `
325*6dbdd20aSAndroid Build Coastguard Worker  WITH _counter AS (
326*6dbdd20aSAndroid Build Coastguard Worker    SELECT counter.id, ts, 0 AS track_id, value
327*6dbdd20aSAndroid Build Coastguard Worker    FROM counter
328*6dbdd20aSAndroid Build Coastguard Worker    JOIN counter_track ON counter_track.id = counter.track_id
329*6dbdd20aSAndroid Build Coastguard Worker    WHERE name = 'DozeLightState'
330*6dbdd20aSAndroid Build Coastguard Worker  )
331*6dbdd20aSAndroid Build Coastguard Worker  SELECT
332*6dbdd20aSAndroid Build Coastguard Worker    ts,
333*6dbdd20aSAndroid Build Coastguard Worker    dur,
334*6dbdd20aSAndroid Build Coastguard Worker    CASE value
335*6dbdd20aSAndroid Build Coastguard Worker      WHEN 0 THEN 'active'
336*6dbdd20aSAndroid Build Coastguard Worker      WHEN 1 THEN 'inactive'
337*6dbdd20aSAndroid Build Coastguard Worker      WHEN 4 THEN 'idle'
338*6dbdd20aSAndroid Build Coastguard Worker      WHEN 5 THEN 'waiting_for_network'
339*6dbdd20aSAndroid Build Coastguard Worker      WHEN 6 THEN 'idle_maintenance'
340*6dbdd20aSAndroid Build Coastguard Worker      WHEN 7 THEN 'override'
341*6dbdd20aSAndroid Build Coastguard Worker      ELSE 'unknown'
342*6dbdd20aSAndroid Build Coastguard Worker    END AS name
343*6dbdd20aSAndroid Build Coastguard Worker  FROM counter_leading_intervals!(_counter)`;
344*6dbdd20aSAndroid Build Coastguard Worker
345*6dbdd20aSAndroid Build Coastguard Workerconst DOZE_DEEP = `
346*6dbdd20aSAndroid Build Coastguard Worker  WITH _counter AS (
347*6dbdd20aSAndroid Build Coastguard Worker    SELECT counter.id, ts, 0 AS track_id, value
348*6dbdd20aSAndroid Build Coastguard Worker    FROM counter
349*6dbdd20aSAndroid Build Coastguard Worker    JOIN counter_track ON counter_track.id = counter.track_id
350*6dbdd20aSAndroid Build Coastguard Worker    WHERE name = 'DozeDeepState'
351*6dbdd20aSAndroid Build Coastguard Worker  )
352*6dbdd20aSAndroid Build Coastguard Worker  SELECT
353*6dbdd20aSAndroid Build Coastguard Worker    ts,
354*6dbdd20aSAndroid Build Coastguard Worker    dur,
355*6dbdd20aSAndroid Build Coastguard Worker    CASE value
356*6dbdd20aSAndroid Build Coastguard Worker      WHEN 0 THEN 'active'
357*6dbdd20aSAndroid Build Coastguard Worker      WHEN 1 THEN 'inactive'
358*6dbdd20aSAndroid Build Coastguard Worker      WHEN 2 THEN 'idle_pending'
359*6dbdd20aSAndroid Build Coastguard Worker      WHEN 3 THEN 'sensing'
360*6dbdd20aSAndroid Build Coastguard Worker      WHEN 4 THEN 'locating'
361*6dbdd20aSAndroid Build Coastguard Worker      WHEN 5 THEN 'idle'
362*6dbdd20aSAndroid Build Coastguard Worker      WHEN 6 THEN 'idle_maintenance'
363*6dbdd20aSAndroid Build Coastguard Worker      WHEN 7 THEN 'quick_doze_delay'
364*6dbdd20aSAndroid Build Coastguard Worker      ELSE 'unknown'
365*6dbdd20aSAndroid Build Coastguard Worker    END AS name
366*6dbdd20aSAndroid Build Coastguard Worker  FROM counter_leading_intervals!(_counter)`;
367*6dbdd20aSAndroid Build Coastguard Worker
368*6dbdd20aSAndroid Build Coastguard Workerconst CHARGING = `
369*6dbdd20aSAndroid Build Coastguard Worker  WITH _counter AS (
370*6dbdd20aSAndroid Build Coastguard Worker    SELECT counter.id, ts, 0 AS track_id, value
371*6dbdd20aSAndroid Build Coastguard Worker    FROM counter
372*6dbdd20aSAndroid Build Coastguard Worker    JOIN counter_track ON counter_track.id = counter.track_id
373*6dbdd20aSAndroid Build Coastguard Worker    WHERE name = 'BatteryStatus'
374*6dbdd20aSAndroid Build Coastguard Worker  )
375*6dbdd20aSAndroid Build Coastguard Worker  SELECT
376*6dbdd20aSAndroid Build Coastguard Worker    ts,
377*6dbdd20aSAndroid Build Coastguard Worker    dur,
378*6dbdd20aSAndroid Build Coastguard Worker    CASE value
379*6dbdd20aSAndroid Build Coastguard Worker      -- 0 and 1 are both unknown
380*6dbdd20aSAndroid Build Coastguard Worker      WHEN 2 THEN 'Charging'
381*6dbdd20aSAndroid Build Coastguard Worker      WHEN 3 THEN 'Discharging'
382*6dbdd20aSAndroid Build Coastguard Worker      -- special case when charger is present but battery isn't charging
383*6dbdd20aSAndroid Build Coastguard Worker      WHEN 4 THEN 'Not charging'
384*6dbdd20aSAndroid Build Coastguard Worker      WHEN 5 THEN 'Full'
385*6dbdd20aSAndroid Build Coastguard Worker      ELSE 'unknown'
386*6dbdd20aSAndroid Build Coastguard Worker    END AS name
387*6dbdd20aSAndroid Build Coastguard Worker  FROM counter_leading_intervals!(_counter)`;
388*6dbdd20aSAndroid Build Coastguard Worker
389*6dbdd20aSAndroid Build Coastguard Workerconst THERMAL_THROTTLING = `
390*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
391*6dbdd20aSAndroid Build Coastguard Worker      select
392*6dbdd20aSAndroid Build Coastguard Worker          ts,
393*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'thermal_throttling_severity_state_changed.sensor_type') as sensor_type,
394*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'thermal_throttling_severity_state_changed.sensor_name') as sensor_name,
395*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'thermal_throttling_severity_state_changed.temperature_deci_celsius') / 10.0 as temperature_celcius,
396*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'thermal_throttling_severity_state_changed.severity') as severity
397*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
398*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
399*6dbdd20aSAndroid Build Coastguard Worker      and s.name = 'thermal_throttling_severity_state_changed'
400*6dbdd20aSAndroid Build Coastguard Worker  ),
401*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
402*6dbdd20aSAndroid Build Coastguard Worker      select
403*6dbdd20aSAndroid Build Coastguard Worker          ts,
404*6dbdd20aSAndroid Build Coastguard Worker          lead(ts) over (partition by sensor_type, sensor_name order by ts) - ts as dur,
405*6dbdd20aSAndroid Build Coastguard Worker          sensor_type,
406*6dbdd20aSAndroid Build Coastguard Worker          sensor_name,
407*6dbdd20aSAndroid Build Coastguard Worker          temperature_celcius,
408*6dbdd20aSAndroid Build Coastguard Worker          severity
409*6dbdd20aSAndroid Build Coastguard Worker      from step1
410*6dbdd20aSAndroid Build Coastguard Worker      where sensor_type not like 'TEMPERATURE_TYPE_BCL_%'
411*6dbdd20aSAndroid Build Coastguard Worker  )
412*6dbdd20aSAndroid Build Coastguard Worker  select
413*6dbdd20aSAndroid Build Coastguard Worker    ts,
414*6dbdd20aSAndroid Build Coastguard Worker    dur,
415*6dbdd20aSAndroid Build Coastguard Worker    case sensor_name
416*6dbdd20aSAndroid Build Coastguard Worker        when 'VIRTUAL-SKIN' then ''
417*6dbdd20aSAndroid Build Coastguard Worker        else sensor_name || ' is '
418*6dbdd20aSAndroid Build Coastguard Worker    end || severity || ' (' || temperature_celcius || 'C)' as name
419*6dbdd20aSAndroid Build Coastguard Worker  from step2
420*6dbdd20aSAndroid Build Coastguard Worker  where severity != 'NONE'`;
421*6dbdd20aSAndroid Build Coastguard Worker
422*6dbdd20aSAndroid Build Coastguard Workerconst KERNEL_WAKELOCKS = `
423*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto table kernel_wakelocks as
424*6dbdd20aSAndroid Build Coastguard Worker  with kernel_wakelock_args as (
425*6dbdd20aSAndroid Build Coastguard Worker    select
426*6dbdd20aSAndroid Build Coastguard Worker      arg_set_id,
427*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'kernel_wakelock.name', string_value, null)) as wakelock_name,
428*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'kernel_wakelock.count', int_value, null)) as count,
429*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'kernel_wakelock.time_micros', int_value, null)) as time_micros
430*6dbdd20aSAndroid Build Coastguard Worker    from args
431*6dbdd20aSAndroid Build Coastguard Worker    where key in (
432*6dbdd20aSAndroid Build Coastguard Worker      'kernel_wakelock.name',
433*6dbdd20aSAndroid Build Coastguard Worker      'kernel_wakelock.count',
434*6dbdd20aSAndroid Build Coastguard Worker      'kernel_wakelock.time_micros'
435*6dbdd20aSAndroid Build Coastguard Worker    )
436*6dbdd20aSAndroid Build Coastguard Worker    group by 1
437*6dbdd20aSAndroid Build Coastguard Worker  ),
438*6dbdd20aSAndroid Build Coastguard Worker  interesting as (
439*6dbdd20aSAndroid Build Coastguard Worker    select wakelock_name
440*6dbdd20aSAndroid Build Coastguard Worker    from (
441*6dbdd20aSAndroid Build Coastguard Worker      select wakelock_name, max(time_micros)-min(time_micros) as delta_us
442*6dbdd20aSAndroid Build Coastguard Worker      from kernel_wakelock_args
443*6dbdd20aSAndroid Build Coastguard Worker      group by 1
444*6dbdd20aSAndroid Build Coastguard Worker    )
445*6dbdd20aSAndroid Build Coastguard Worker    -- Only consider wakelocks with over 1 second of time during the whole trace
446*6dbdd20aSAndroid Build Coastguard Worker    where delta_us > 1e6
447*6dbdd20aSAndroid Build Coastguard Worker  ),
448*6dbdd20aSAndroid Build Coastguard Worker  step1 as (
449*6dbdd20aSAndroid Build Coastguard Worker    select ts, wakelock_name, count, time_micros
450*6dbdd20aSAndroid Build Coastguard Worker    from kernel_wakelock_args
451*6dbdd20aSAndroid Build Coastguard Worker    join interesting using (wakelock_name)
452*6dbdd20aSAndroid Build Coastguard Worker    join slice using (arg_set_id)
453*6dbdd20aSAndroid Build Coastguard Worker  ),
454*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
455*6dbdd20aSAndroid Build Coastguard Worker    select
456*6dbdd20aSAndroid Build Coastguard Worker      ts,
457*6dbdd20aSAndroid Build Coastguard Worker      wakelock_name,
458*6dbdd20aSAndroid Build Coastguard Worker      lead(ts) over (partition by wakelock_name order by ts) as ts_end,
459*6dbdd20aSAndroid Build Coastguard Worker      lead(count) over (partition by wakelock_name order by ts) - count as count,
460*6dbdd20aSAndroid Build Coastguard Worker      (lead(time_micros) over (partition by wakelock_name order by ts) - time_micros) * 1000 as wakelock_dur
461*6dbdd20aSAndroid Build Coastguard Worker    from step1
462*6dbdd20aSAndroid Build Coastguard Worker  ),
463*6dbdd20aSAndroid Build Coastguard Worker  step3 as (
464*6dbdd20aSAndroid Build Coastguard Worker    select
465*6dbdd20aSAndroid Build Coastguard Worker      ts,
466*6dbdd20aSAndroid Build Coastguard Worker      ts_end,
467*6dbdd20aSAndroid Build Coastguard Worker      ifnull((select sum(dur) from android_suspend_state s
468*6dbdd20aSAndroid Build Coastguard Worker              where power_state = 'suspended'
469*6dbdd20aSAndroid Build Coastguard Worker                and s.ts > step2.ts
470*6dbdd20aSAndroid Build Coastguard Worker                and s.ts < step2.ts_end), 0) as suspended_dur,
471*6dbdd20aSAndroid Build Coastguard Worker      wakelock_name,
472*6dbdd20aSAndroid Build Coastguard Worker      count,
473*6dbdd20aSAndroid Build Coastguard Worker      wakelock_dur
474*6dbdd20aSAndroid Build Coastguard Worker    from step2
475*6dbdd20aSAndroid Build Coastguard Worker    where wakelock_dur is not null
476*6dbdd20aSAndroid Build Coastguard Worker      and wakelock_dur >= 0
477*6dbdd20aSAndroid Build Coastguard Worker  )
478*6dbdd20aSAndroid Build Coastguard Worker  select
479*6dbdd20aSAndroid Build Coastguard Worker    ts,
480*6dbdd20aSAndroid Build Coastguard Worker    ts_end - ts as dur,
481*6dbdd20aSAndroid Build Coastguard Worker    wakelock_name,
482*6dbdd20aSAndroid Build Coastguard Worker    min(100.0 * wakelock_dur / (ts_end - ts - suspended_dur), 100) as value
483*6dbdd20aSAndroid Build Coastguard Worker  from step3`;
484*6dbdd20aSAndroid Build Coastguard Worker
485*6dbdd20aSAndroid Build Coastguard Workerconst KERNEL_WAKELOCKS_SUMMARY = `
486*6dbdd20aSAndroid Build Coastguard Worker  select wakelock_name, max(value) as max_value
487*6dbdd20aSAndroid Build Coastguard Worker  from kernel_wakelocks
488*6dbdd20aSAndroid Build Coastguard Worker  where wakelock_name not in ('PowerManager.SuspendLockout', 'PowerManagerService.Display')
489*6dbdd20aSAndroid Build Coastguard Worker  group by 1
490*6dbdd20aSAndroid Build Coastguard Worker  having max_value > 1
491*6dbdd20aSAndroid Build Coastguard Worker  order by 1;`;
492*6dbdd20aSAndroid Build Coastguard Worker
493*6dbdd20aSAndroid Build Coastguard Workerconst HIGH_CPU = `
494*6dbdd20aSAndroid Build Coastguard Worker  create or replace perfetto table high_cpu as
495*6dbdd20aSAndroid Build Coastguard Worker  with cpu_cycles_args AS (
496*6dbdd20aSAndroid Build Coastguard Worker    select
497*6dbdd20aSAndroid Build Coastguard Worker      arg_set_id,
498*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'cpu_cycles_per_uid_cluster.uid', int_value, null)) as uid,
499*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'cpu_cycles_per_uid_cluster.cluster', int_value, null)) as cluster,
500*6dbdd20aSAndroid Build Coastguard Worker      min(iif(key = 'cpu_cycles_per_uid_cluster.time_millis', int_value, null)) as time_millis
501*6dbdd20aSAndroid Build Coastguard Worker    from args
502*6dbdd20aSAndroid Build Coastguard Worker    where key in (
503*6dbdd20aSAndroid Build Coastguard Worker      'cpu_cycles_per_uid_cluster.uid',
504*6dbdd20aSAndroid Build Coastguard Worker      'cpu_cycles_per_uid_cluster.cluster',
505*6dbdd20aSAndroid Build Coastguard Worker      'cpu_cycles_per_uid_cluster.time_millis'
506*6dbdd20aSAndroid Build Coastguard Worker    )
507*6dbdd20aSAndroid Build Coastguard Worker    group by 1
508*6dbdd20aSAndroid Build Coastguard Worker  ),
509*6dbdd20aSAndroid Build Coastguard Worker  interesting AS (
510*6dbdd20aSAndroid Build Coastguard Worker    select uid, cluster
511*6dbdd20aSAndroid Build Coastguard Worker    from (
512*6dbdd20aSAndroid Build Coastguard Worker      select uid, cluster, max(time_millis)-min(time_millis) as delta_ms
513*6dbdd20aSAndroid Build Coastguard Worker      from cpu_cycles_args
514*6dbdd20aSAndroid Build Coastguard Worker      group by 1, 2
515*6dbdd20aSAndroid Build Coastguard Worker    )
516*6dbdd20aSAndroid Build Coastguard Worker    -- Only consider tracks with over 1 second of cpu during the whole trace
517*6dbdd20aSAndroid Build Coastguard Worker    where delta_ms > 1e3
518*6dbdd20aSAndroid Build Coastguard Worker  ),
519*6dbdd20aSAndroid Build Coastguard Worker  base as (
520*6dbdd20aSAndroid Build Coastguard Worker    select ts, uid, cluster, sum(time_millis) as time_millis
521*6dbdd20aSAndroid Build Coastguard Worker    from cpu_cycles_args
522*6dbdd20aSAndroid Build Coastguard Worker    join interesting using (uid, cluster)
523*6dbdd20aSAndroid Build Coastguard Worker    join slice using (arg_set_id)
524*6dbdd20aSAndroid Build Coastguard Worker    group by 1, 2, 3
525*6dbdd20aSAndroid Build Coastguard Worker  ),
526*6dbdd20aSAndroid Build Coastguard Worker  with_windows as (
527*6dbdd20aSAndroid Build Coastguard Worker    select
528*6dbdd20aSAndroid Build Coastguard Worker      ts,
529*6dbdd20aSAndroid Build Coastguard Worker      uid,
530*6dbdd20aSAndroid Build Coastguard Worker      cluster,
531*6dbdd20aSAndroid Build Coastguard Worker      lead(ts) over (partition by uid, cluster order by ts) - ts as dur,
532*6dbdd20aSAndroid Build Coastguard Worker      (lead(time_millis) over (partition by uid, cluster order by ts) - time_millis) * 1000000.0 as cpu_dur
533*6dbdd20aSAndroid Build Coastguard Worker    from base
534*6dbdd20aSAndroid Build Coastguard Worker  ),
535*6dbdd20aSAndroid Build Coastguard Worker  with_ratio as (
536*6dbdd20aSAndroid Build Coastguard Worker    select
537*6dbdd20aSAndroid Build Coastguard Worker      ts,
538*6dbdd20aSAndroid Build Coastguard Worker      iif(dur is null, 0, max(0, 100.0 * cpu_dur / dur)) as value,
539*6dbdd20aSAndroid Build Coastguard Worker      case cluster when 0 then 'little' when 1 then 'mid' when 2 then 'big' else 'cl-' || cluster end as cluster,
540*6dbdd20aSAndroid Build Coastguard Worker      package_name as pkg
541*6dbdd20aSAndroid Build Coastguard Worker    from add_package_name!(with_windows)
542*6dbdd20aSAndroid Build Coastguard Worker  )
543*6dbdd20aSAndroid Build Coastguard Worker  select ts, sum(value) as value, cluster, pkg
544*6dbdd20aSAndroid Build Coastguard Worker  from with_ratio
545*6dbdd20aSAndroid Build Coastguard Worker  group by 1, 3, 4`;
546*6dbdd20aSAndroid Build Coastguard Worker
547*6dbdd20aSAndroid Build Coastguard Workerconst WAKEUPS = `
548*6dbdd20aSAndroid Build Coastguard Worker  drop table if exists wakeups;
549*6dbdd20aSAndroid Build Coastguard Worker  create table wakeups as
550*6dbdd20aSAndroid Build Coastguard Worker  with wakeup_reason as (
551*6dbdd20aSAndroid Build Coastguard Worker      select
552*6dbdd20aSAndroid Build Coastguard Worker      ts,
553*6dbdd20aSAndroid Build Coastguard Worker      substr(i.name, 0, instr(i.name, ' ')) as id_timestamp,
554*6dbdd20aSAndroid Build Coastguard Worker      substr(i.name, instr(i.name, ' ') + 1) as raw_wakeup
555*6dbdd20aSAndroid Build Coastguard Worker      from track t join instant i on t.id = i.track_id
556*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'wakeup_reason'
557*6dbdd20aSAndroid Build Coastguard Worker  ),
558*6dbdd20aSAndroid Build Coastguard Worker  wakeup_attribution as (
559*6dbdd20aSAndroid Build Coastguard Worker      select
560*6dbdd20aSAndroid Build Coastguard Worker      substr(i.name, 0, instr(i.name, ' ')) as id_timestamp,
561*6dbdd20aSAndroid Build Coastguard Worker      substr(i.name, instr(i.name, ' ') + 1) as attribution
562*6dbdd20aSAndroid Build Coastguard Worker      from track t join instant i on t.id = i.track_id
563*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'wakeup_attribution'
564*6dbdd20aSAndroid Build Coastguard Worker  ),
565*6dbdd20aSAndroid Build Coastguard Worker  step1 as(
566*6dbdd20aSAndroid Build Coastguard Worker    select
567*6dbdd20aSAndroid Build Coastguard Worker      ts,
568*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
569*6dbdd20aSAndroid Build Coastguard Worker      attribution,
570*6dbdd20aSAndroid Build Coastguard Worker      null as raw_backoff
571*6dbdd20aSAndroid Build Coastguard Worker    from wakeup_reason r
572*6dbdd20aSAndroid Build Coastguard Worker      left outer join wakeup_attribution using(id_timestamp)
573*6dbdd20aSAndroid Build Coastguard Worker    union all
574*6dbdd20aSAndroid Build Coastguard Worker    select
575*6dbdd20aSAndroid Build Coastguard Worker      ts,
576*6dbdd20aSAndroid Build Coastguard Worker      null as raw_wakeup,
577*6dbdd20aSAndroid Build Coastguard Worker      null as attribution,
578*6dbdd20aSAndroid Build Coastguard Worker      i.name as raw_backoff
579*6dbdd20aSAndroid Build Coastguard Worker    from track t join instant i on t.id = i.track_id
580*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'suspend_backoff'
581*6dbdd20aSAndroid Build Coastguard Worker  ),
582*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
583*6dbdd20aSAndroid Build Coastguard Worker    select
584*6dbdd20aSAndroid Build Coastguard Worker      ts,
585*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
586*6dbdd20aSAndroid Build Coastguard Worker      attribution,
587*6dbdd20aSAndroid Build Coastguard Worker      lag(raw_backoff) over (order by ts) as raw_backoff
588*6dbdd20aSAndroid Build Coastguard Worker    from step1
589*6dbdd20aSAndroid Build Coastguard Worker  ),
590*6dbdd20aSAndroid Build Coastguard Worker  step3 as (
591*6dbdd20aSAndroid Build Coastguard Worker    select
592*6dbdd20aSAndroid Build Coastguard Worker      ts,
593*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
594*6dbdd20aSAndroid Build Coastguard Worker      attribution,
595*6dbdd20aSAndroid Build Coastguard Worker      str_split(raw_backoff, ' ', 0) as suspend_quality,
596*6dbdd20aSAndroid Build Coastguard Worker      str_split(raw_backoff, ' ', 1) as backoff_state,
597*6dbdd20aSAndroid Build Coastguard Worker      str_split(raw_backoff, ' ', 2) as backoff_reason,
598*6dbdd20aSAndroid Build Coastguard Worker      cast(str_split(raw_backoff, ' ', 3) as int) as backoff_count,
599*6dbdd20aSAndroid Build Coastguard Worker      cast(str_split(raw_backoff, ' ', 4) as int) as backoff_millis,
600*6dbdd20aSAndroid Build Coastguard Worker      false as suspend_end
601*6dbdd20aSAndroid Build Coastguard Worker    from step2
602*6dbdd20aSAndroid Build Coastguard Worker    where raw_wakeup is not null
603*6dbdd20aSAndroid Build Coastguard Worker    union all
604*6dbdd20aSAndroid Build Coastguard Worker    select
605*6dbdd20aSAndroid Build Coastguard Worker      ts,
606*6dbdd20aSAndroid Build Coastguard Worker      null as raw_wakeup,
607*6dbdd20aSAndroid Build Coastguard Worker      null as attribution,
608*6dbdd20aSAndroid Build Coastguard Worker      null as suspend_quality,
609*6dbdd20aSAndroid Build Coastguard Worker      null as backoff_state,
610*6dbdd20aSAndroid Build Coastguard Worker      null as backoff_reason,
611*6dbdd20aSAndroid Build Coastguard Worker      null as backoff_count,
612*6dbdd20aSAndroid Build Coastguard Worker      null as backoff_millis,
613*6dbdd20aSAndroid Build Coastguard Worker      true as suspend_end
614*6dbdd20aSAndroid Build Coastguard Worker    from android_suspend_state
615*6dbdd20aSAndroid Build Coastguard Worker    where power_state = 'suspended'
616*6dbdd20aSAndroid Build Coastguard Worker  ),
617*6dbdd20aSAndroid Build Coastguard Worker  step4 as (
618*6dbdd20aSAndroid Build Coastguard Worker    select
619*6dbdd20aSAndroid Build Coastguard Worker      ts,
620*6dbdd20aSAndroid Build Coastguard Worker      case suspend_quality
621*6dbdd20aSAndroid Build Coastguard Worker        when 'good' then
622*6dbdd20aSAndroid Build Coastguard Worker          min(
623*6dbdd20aSAndroid Build Coastguard Worker            lead(ts, 1, ts + 5e9) over (order by ts) - ts,
624*6dbdd20aSAndroid Build Coastguard Worker            5e9
625*6dbdd20aSAndroid Build Coastguard Worker          )
626*6dbdd20aSAndroid Build Coastguard Worker        when 'bad' then backoff_millis * 1000000
627*6dbdd20aSAndroid Build Coastguard Worker        else 0
628*6dbdd20aSAndroid Build Coastguard Worker      end as dur,
629*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
630*6dbdd20aSAndroid Build Coastguard Worker      attribution,
631*6dbdd20aSAndroid Build Coastguard Worker      suspend_quality,
632*6dbdd20aSAndroid Build Coastguard Worker      backoff_state,
633*6dbdd20aSAndroid Build Coastguard Worker      backoff_reason,
634*6dbdd20aSAndroid Build Coastguard Worker      backoff_count,
635*6dbdd20aSAndroid Build Coastguard Worker      backoff_millis,
636*6dbdd20aSAndroid Build Coastguard Worker      suspend_end
637*6dbdd20aSAndroid Build Coastguard Worker    from step3
638*6dbdd20aSAndroid Build Coastguard Worker  ),
639*6dbdd20aSAndroid Build Coastguard Worker  step5 as (
640*6dbdd20aSAndroid Build Coastguard Worker    select
641*6dbdd20aSAndroid Build Coastguard Worker      ts,
642*6dbdd20aSAndroid Build Coastguard Worker      dur,
643*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
644*6dbdd20aSAndroid Build Coastguard Worker      attribution,
645*6dbdd20aSAndroid Build Coastguard Worker      suspend_quality,
646*6dbdd20aSAndroid Build Coastguard Worker      backoff_state,
647*6dbdd20aSAndroid Build Coastguard Worker      backoff_reason,
648*6dbdd20aSAndroid Build Coastguard Worker      backoff_count,
649*6dbdd20aSAndroid Build Coastguard Worker      backoff_millis
650*6dbdd20aSAndroid Build Coastguard Worker    from step4
651*6dbdd20aSAndroid Build Coastguard Worker    where not suspend_end
652*6dbdd20aSAndroid Build Coastguard Worker  ),
653*6dbdd20aSAndroid Build Coastguard Worker  step6 as (
654*6dbdd20aSAndroid Build Coastguard Worker    select
655*6dbdd20aSAndroid Build Coastguard Worker      ts,
656*6dbdd20aSAndroid Build Coastguard Worker      dur,
657*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
658*6dbdd20aSAndroid Build Coastguard Worker      attribution,
659*6dbdd20aSAndroid Build Coastguard Worker      suspend_quality,
660*6dbdd20aSAndroid Build Coastguard Worker      backoff_state,
661*6dbdd20aSAndroid Build Coastguard Worker      backoff_reason,
662*6dbdd20aSAndroid Build Coastguard Worker      backoff_count,
663*6dbdd20aSAndroid Build Coastguard Worker      backoff_millis,
664*6dbdd20aSAndroid Build Coastguard Worker      case
665*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: Pending Wakeup Sources: %' then 'abort_pending'
666*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: Last active Wakeup Source: %' then 'abort_last_active'
667*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: %' then 'abort_other'
668*6dbdd20aSAndroid Build Coastguard Worker        else 'normal'
669*6dbdd20aSAndroid Build Coastguard Worker      end as type,
670*6dbdd20aSAndroid Build Coastguard Worker      case
671*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: Pending Wakeup Sources: %' then substr(raw_wakeup, 32)
672*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: Last active Wakeup Source: %' then substr(raw_wakeup, 35)
673*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: %' then substr(raw_wakeup, 8)
674*6dbdd20aSAndroid Build Coastguard Worker        else raw_wakeup
675*6dbdd20aSAndroid Build Coastguard Worker      end as main,
676*6dbdd20aSAndroid Build Coastguard Worker      case
677*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: Pending Wakeup Sources: %' then ' '
678*6dbdd20aSAndroid Build Coastguard Worker        when raw_wakeup like 'Abort: %' then 'no delimiter needed'
679*6dbdd20aSAndroid Build Coastguard Worker        else ':'
680*6dbdd20aSAndroid Build Coastguard Worker      end as delimiter
681*6dbdd20aSAndroid Build Coastguard Worker    from step5
682*6dbdd20aSAndroid Build Coastguard Worker  ),
683*6dbdd20aSAndroid Build Coastguard Worker  step7 as (
684*6dbdd20aSAndroid Build Coastguard Worker    select
685*6dbdd20aSAndroid Build Coastguard Worker      ts,
686*6dbdd20aSAndroid Build Coastguard Worker      dur,
687*6dbdd20aSAndroid Build Coastguard Worker      raw_wakeup,
688*6dbdd20aSAndroid Build Coastguard Worker      attribution,
689*6dbdd20aSAndroid Build Coastguard Worker      suspend_quality,
690*6dbdd20aSAndroid Build Coastguard Worker      backoff_state,
691*6dbdd20aSAndroid Build Coastguard Worker      backoff_reason,
692*6dbdd20aSAndroid Build Coastguard Worker      backoff_count,
693*6dbdd20aSAndroid Build Coastguard Worker      backoff_millis,
694*6dbdd20aSAndroid Build Coastguard Worker      type,
695*6dbdd20aSAndroid Build Coastguard Worker      str_split(main, delimiter, 0) as item_0,
696*6dbdd20aSAndroid Build Coastguard Worker      str_split(main, delimiter, 1) as item_1,
697*6dbdd20aSAndroid Build Coastguard Worker      str_split(main, delimiter, 2) as item_2,
698*6dbdd20aSAndroid Build Coastguard Worker      str_split(main, delimiter, 3) as item_3
699*6dbdd20aSAndroid Build Coastguard Worker    from step6
700*6dbdd20aSAndroid Build Coastguard Worker  ),
701*6dbdd20aSAndroid Build Coastguard Worker  step8 as (
702*6dbdd20aSAndroid Build Coastguard Worker    select ts, dur, raw_wakeup, attribution, suspend_quality, backoff_state, backoff_reason, backoff_count, backoff_millis, type, item_0 as item from step7
703*6dbdd20aSAndroid Build Coastguard Worker    union all
704*6dbdd20aSAndroid Build Coastguard Worker    select ts, dur, raw_wakeup, attribution, suspend_quality, backoff_state, backoff_reason, backoff_count, backoff_millis, type, item_1 as item from step7 where item_1 is not null
705*6dbdd20aSAndroid Build Coastguard Worker    union all
706*6dbdd20aSAndroid Build Coastguard Worker    select ts, dur, raw_wakeup, attribution, suspend_quality, backoff_state, backoff_reason, backoff_count, backoff_millis, type, item_2 as item from step7 where item_2 is not null
707*6dbdd20aSAndroid Build Coastguard Worker    union all
708*6dbdd20aSAndroid Build Coastguard Worker    select ts, dur, raw_wakeup, attribution, suspend_quality, backoff_state, backoff_reason, backoff_count, backoff_millis, type, item_3 as item from step7 where item_3 is not null
709*6dbdd20aSAndroid Build Coastguard Worker  )
710*6dbdd20aSAndroid Build Coastguard Worker  select
711*6dbdd20aSAndroid Build Coastguard Worker    ts,
712*6dbdd20aSAndroid Build Coastguard Worker    dur,
713*6dbdd20aSAndroid Build Coastguard Worker    ts + dur as ts_end,
714*6dbdd20aSAndroid Build Coastguard Worker    raw_wakeup,
715*6dbdd20aSAndroid Build Coastguard Worker    attribution,
716*6dbdd20aSAndroid Build Coastguard Worker    suspend_quality,
717*6dbdd20aSAndroid Build Coastguard Worker    backoff_state,
718*6dbdd20aSAndroid Build Coastguard Worker    ifnull(backoff_reason, 'none') as backoff_reason,
719*6dbdd20aSAndroid Build Coastguard Worker    backoff_count,
720*6dbdd20aSAndroid Build Coastguard Worker    backoff_millis,
721*6dbdd20aSAndroid Build Coastguard Worker    type,
722*6dbdd20aSAndroid Build Coastguard Worker    case when type = 'normal' then ifnull(str_split(item, ' ', 1), item) else item end as item
723*6dbdd20aSAndroid Build Coastguard Worker  from step8`;
724*6dbdd20aSAndroid Build Coastguard Worker
725*6dbdd20aSAndroid Build Coastguard Workerconst WAKEUPS_COLUMNS = [
726*6dbdd20aSAndroid Build Coastguard Worker  'item',
727*6dbdd20aSAndroid Build Coastguard Worker  'type',
728*6dbdd20aSAndroid Build Coastguard Worker  'raw_wakeup',
729*6dbdd20aSAndroid Build Coastguard Worker  'attribution',
730*6dbdd20aSAndroid Build Coastguard Worker  'suspend_quality',
731*6dbdd20aSAndroid Build Coastguard Worker  'backoff_state',
732*6dbdd20aSAndroid Build Coastguard Worker  'backoff_reason',
733*6dbdd20aSAndroid Build Coastguard Worker  'backoff_count',
734*6dbdd20aSAndroid Build Coastguard Worker  'backoff_millis',
735*6dbdd20aSAndroid Build Coastguard Worker];
736*6dbdd20aSAndroid Build Coastguard Worker
737*6dbdd20aSAndroid Build Coastguard Workerfunction bleScanQuery(condition: string) {
738*6dbdd20aSAndroid Build Coastguard Worker  return `
739*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
740*6dbdd20aSAndroid Build Coastguard Worker      select
741*6dbdd20aSAndroid Build Coastguard Worker          ts,
742*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_state_changed.attribution_node[0].tag') as name,
743*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_state_changed.is_opportunistic') as opportunistic,
744*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_state_changed.is_filtered') as filtered,
745*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_state_changed.state') as state
746*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
747*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
748*6dbdd20aSAndroid Build Coastguard Worker      and s.name = 'ble_scan_state_changed'
749*6dbdd20aSAndroid Build Coastguard Worker  ),
750*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
751*6dbdd20aSAndroid Build Coastguard Worker      select
752*6dbdd20aSAndroid Build Coastguard Worker          ts,
753*6dbdd20aSAndroid Build Coastguard Worker          name,
754*6dbdd20aSAndroid Build Coastguard Worker          state,
755*6dbdd20aSAndroid Build Coastguard Worker          opportunistic,
756*6dbdd20aSAndroid Build Coastguard Worker          filtered,
757*6dbdd20aSAndroid Build Coastguard Worker          lead(ts) over (partition by name order by ts) - ts as dur
758*6dbdd20aSAndroid Build Coastguard Worker      from step1
759*6dbdd20aSAndroid Build Coastguard Worker  )
760*6dbdd20aSAndroid Build Coastguard Worker  select ts, dur, name from step2 where state = 'ON' and ${condition} and dur is not null`;
761*6dbdd20aSAndroid Build Coastguard Worker}
762*6dbdd20aSAndroid Build Coastguard Worker
763*6dbdd20aSAndroid Build Coastguard Workerconst BLE_RESULTS = `
764*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
765*6dbdd20aSAndroid Build Coastguard Worker      select
766*6dbdd20aSAndroid Build Coastguard Worker          ts,
767*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_result_received.attribution_node[0].tag') as name,
768*6dbdd20aSAndroid Build Coastguard Worker          extract_arg(arg_set_id, 'ble_scan_result_received.num_results') as num_results
769*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
770*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
771*6dbdd20aSAndroid Build Coastguard Worker      and s.name = 'ble_scan_result_received'
772*6dbdd20aSAndroid Build Coastguard Worker  )
773*6dbdd20aSAndroid Build Coastguard Worker  select
774*6dbdd20aSAndroid Build Coastguard Worker      ts,
775*6dbdd20aSAndroid Build Coastguard Worker      0 as dur,
776*6dbdd20aSAndroid Build Coastguard Worker      name || ' (' || num_results || ' results)' as name
777*6dbdd20aSAndroid Build Coastguard Worker  from step1`;
778*6dbdd20aSAndroid Build Coastguard Worker
779*6dbdd20aSAndroid Build Coastguard Workerconst BT_A2DP_AUDIO = `
780*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
781*6dbdd20aSAndroid Build Coastguard Worker    select
782*6dbdd20aSAndroid Build Coastguard Worker        ts,
783*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_a2dp_playback_state_changed.playback_state') as playback_state,
784*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_a2dp_playback_state_changed.audio_coding_mode') as audio_coding_mode,
785*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_a2dp_playback_state_changed.metric_id') as metric_id
786*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
787*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
788*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_a2dp_playback_state_changed'
789*6dbdd20aSAndroid Build Coastguard Worker  ),
790*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
791*6dbdd20aSAndroid Build Coastguard Worker    select
792*6dbdd20aSAndroid Build Coastguard Worker        ts,
793*6dbdd20aSAndroid Build Coastguard Worker        lead(ts) over (partition by metric_id order by ts) - ts as dur,
794*6dbdd20aSAndroid Build Coastguard Worker        playback_state,
795*6dbdd20aSAndroid Build Coastguard Worker        audio_coding_mode,
796*6dbdd20aSAndroid Build Coastguard Worker        metric_id
797*6dbdd20aSAndroid Build Coastguard Worker    from step1
798*6dbdd20aSAndroid Build Coastguard Worker  )
799*6dbdd20aSAndroid Build Coastguard Worker  select
800*6dbdd20aSAndroid Build Coastguard Worker    ts,
801*6dbdd20aSAndroid Build Coastguard Worker    dur,
802*6dbdd20aSAndroid Build Coastguard Worker    audio_coding_mode as name
803*6dbdd20aSAndroid Build Coastguard Worker  from step2
804*6dbdd20aSAndroid Build Coastguard Worker  where playback_state = 'PLAYBACK_STATE_PLAYING'`;
805*6dbdd20aSAndroid Build Coastguard Worker
806*6dbdd20aSAndroid Build Coastguard Workerconst BT_CONNS_ACL = `
807*6dbdd20aSAndroid Build Coastguard Worker    with acl1 as (
808*6dbdd20aSAndroid Build Coastguard Worker        select
809*6dbdd20aSAndroid Build Coastguard Worker            ts,
810*6dbdd20aSAndroid Build Coastguard Worker            EXTRACT_ARG(arg_set_id, 'bluetooth_acl_connection_state_changed.state') as state,
811*6dbdd20aSAndroid Build Coastguard Worker            EXTRACT_ARG(arg_set_id, 'bluetooth_acl_connection_state_changed.transport') as transport,
812*6dbdd20aSAndroid Build Coastguard Worker            EXTRACT_ARG(arg_set_id, 'bluetooth_acl_connection_state_changed.metric_id') as metric_id
813*6dbdd20aSAndroid Build Coastguard Worker        from track t join slice s on t.id = s.track_id
814*6dbdd20aSAndroid Build Coastguard Worker        where t.name = 'Statsd Atoms'
815*6dbdd20aSAndroid Build Coastguard Worker        and s.name = 'bluetooth_acl_connection_state_changed'
816*6dbdd20aSAndroid Build Coastguard Worker    ),
817*6dbdd20aSAndroid Build Coastguard Worker    acl2 as (
818*6dbdd20aSAndroid Build Coastguard Worker        select
819*6dbdd20aSAndroid Build Coastguard Worker            ts,
820*6dbdd20aSAndroid Build Coastguard Worker            lead(ts) over (partition by metric_id, transport order by ts) - ts as dur,
821*6dbdd20aSAndroid Build Coastguard Worker            state,
822*6dbdd20aSAndroid Build Coastguard Worker            transport,
823*6dbdd20aSAndroid Build Coastguard Worker            metric_id
824*6dbdd20aSAndroid Build Coastguard Worker        from acl1
825*6dbdd20aSAndroid Build Coastguard Worker    )
826*6dbdd20aSAndroid Build Coastguard Worker    select
827*6dbdd20aSAndroid Build Coastguard Worker        ts,
828*6dbdd20aSAndroid Build Coastguard Worker        dur,
829*6dbdd20aSAndroid Build Coastguard Worker        'Device ' || metric_id ||
830*6dbdd20aSAndroid Build Coastguard Worker          ' (' || case transport when 'TRANSPORT_TYPE_BREDR' then 'Classic' when 'TRANSPORT_TYPE_LE' then 'BLE' end || ')' as name
831*6dbdd20aSAndroid Build Coastguard Worker    from acl2
832*6dbdd20aSAndroid Build Coastguard Worker    where state != 'CONNECTION_STATE_DISCONNECTED' and dur is not null`;
833*6dbdd20aSAndroid Build Coastguard Worker
834*6dbdd20aSAndroid Build Coastguard Workerconst BT_CONNS_SCO = `
835*6dbdd20aSAndroid Build Coastguard Worker  with sco1 as (
836*6dbdd20aSAndroid Build Coastguard Worker    select
837*6dbdd20aSAndroid Build Coastguard Worker        ts,
838*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_sco_connection_state_changed.state') as state,
839*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_sco_connection_state_changed.codec') as codec,
840*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_sco_connection_state_changed.metric_id') as metric_id
841*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
842*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
843*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_sco_connection_state_changed'
844*6dbdd20aSAndroid Build Coastguard Worker  ),
845*6dbdd20aSAndroid Build Coastguard Worker  sco2 as (
846*6dbdd20aSAndroid Build Coastguard Worker    select
847*6dbdd20aSAndroid Build Coastguard Worker        ts,
848*6dbdd20aSAndroid Build Coastguard Worker        lead(ts) over (partition by metric_id, codec order by ts) - ts as dur,
849*6dbdd20aSAndroid Build Coastguard Worker        state,
850*6dbdd20aSAndroid Build Coastguard Worker        codec,
851*6dbdd20aSAndroid Build Coastguard Worker        metric_id
852*6dbdd20aSAndroid Build Coastguard Worker    from sco1
853*6dbdd20aSAndroid Build Coastguard Worker  )
854*6dbdd20aSAndroid Build Coastguard Worker  select
855*6dbdd20aSAndroid Build Coastguard Worker    ts,
856*6dbdd20aSAndroid Build Coastguard Worker    dur,
857*6dbdd20aSAndroid Build Coastguard Worker    case state when 'CONNECTION_STATE_CONNECTED' then '' when 'CONNECTION_STATE_CONNECTING' then 'Connecting ' when 'CONNECTION_STATE_DISCONNECTING' then 'Disconnecting ' else 'unknown ' end ||
858*6dbdd20aSAndroid Build Coastguard Worker      'Device ' || metric_id || ' (' ||
859*6dbdd20aSAndroid Build Coastguard Worker      case codec when 'SCO_CODEC_CVSD' then 'CVSD' when 'SCO_CODEC_MSBC' then 'MSBC' end || ')' as name
860*6dbdd20aSAndroid Build Coastguard Worker  from sco2
861*6dbdd20aSAndroid Build Coastguard Worker  where state != 'CONNECTION_STATE_DISCONNECTED' and dur is not null`;
862*6dbdd20aSAndroid Build Coastguard Worker
863*6dbdd20aSAndroid Build Coastguard Workerconst BT_LINK_LEVEL_EVENTS = `
864*6dbdd20aSAndroid Build Coastguard Worker  with base as (
865*6dbdd20aSAndroid Build Coastguard Worker    select
866*6dbdd20aSAndroid Build Coastguard Worker        ts,
867*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.direction') as direction,
868*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.type') as type,
869*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.hci_cmd') as hci_cmd,
870*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.hci_event') as hci_event,
871*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.hci_ble_event') as hci_ble_event,
872*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.cmd_status') as cmd_status,
873*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.reason_code') as reason_code,
874*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_link_layer_connection_event.metric_id') as metric_id
875*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
876*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
877*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_link_layer_connection_event'
878*6dbdd20aSAndroid Build Coastguard Worker  )
879*6dbdd20aSAndroid Build Coastguard Worker  select
880*6dbdd20aSAndroid Build Coastguard Worker    *,
881*6dbdd20aSAndroid Build Coastguard Worker    0 as dur,
882*6dbdd20aSAndroid Build Coastguard Worker    'Device '|| metric_id as name
883*6dbdd20aSAndroid Build Coastguard Worker  from base`;
884*6dbdd20aSAndroid Build Coastguard Worker
885*6dbdd20aSAndroid Build Coastguard Workerconst BT_LINK_LEVEL_EVENTS_COLUMNS = [
886*6dbdd20aSAndroid Build Coastguard Worker  'direction',
887*6dbdd20aSAndroid Build Coastguard Worker  'type',
888*6dbdd20aSAndroid Build Coastguard Worker  'hci_cmd',
889*6dbdd20aSAndroid Build Coastguard Worker  'hci_event',
890*6dbdd20aSAndroid Build Coastguard Worker  'hci_ble_event',
891*6dbdd20aSAndroid Build Coastguard Worker  'cmd_status',
892*6dbdd20aSAndroid Build Coastguard Worker  'reason_code',
893*6dbdd20aSAndroid Build Coastguard Worker  'metric_id',
894*6dbdd20aSAndroid Build Coastguard Worker];
895*6dbdd20aSAndroid Build Coastguard Worker
896*6dbdd20aSAndroid Build Coastguard Workerconst BT_QUALITY_REPORTS = `
897*6dbdd20aSAndroid Build Coastguard Worker  with base as (
898*6dbdd20aSAndroid Build Coastguard Worker      select
899*6dbdd20aSAndroid Build Coastguard Worker          ts,
900*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.quality_report_id') as quality_report_id,
901*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.packet_types') as packet_types,
902*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.connection_handle') as connection_handle,
903*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.connection_role') as connection_role,
904*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.tx_power_level') as tx_power_level,
905*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.rssi') as rssi,
906*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.snr') as snr,
907*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.unused_afh_channel_count') as unused_afh_channel_count,
908*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.afh_select_unideal_channel_count') as afh_select_unideal_channel_count,
909*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.lsto') as lsto,
910*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.connection_piconet_clock') as connection_piconet_clock,
911*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.retransmission_count') as retransmission_count,
912*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.no_rx_count') as no_rx_count,
913*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.nak_count') as nak_count,
914*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.flow_off_count') as flow_off_count,
915*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.buffer_overflow_bytes') as buffer_overflow_bytes,
916*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_quality_report_reported.buffer_underflow_bytes') as buffer_underflow_bytes
917*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
918*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
919*6dbdd20aSAndroid Build Coastguard Worker      and s.name = 'bluetooth_quality_report_reported'
920*6dbdd20aSAndroid Build Coastguard Worker  )
921*6dbdd20aSAndroid Build Coastguard Worker  select
922*6dbdd20aSAndroid Build Coastguard Worker      *,
923*6dbdd20aSAndroid Build Coastguard Worker      0 as dur,
924*6dbdd20aSAndroid Build Coastguard Worker      'Connection '|| connection_handle as name
925*6dbdd20aSAndroid Build Coastguard Worker  from base`;
926*6dbdd20aSAndroid Build Coastguard Worker
927*6dbdd20aSAndroid Build Coastguard Workerconst BT_QUALITY_REPORTS_COLUMNS = [
928*6dbdd20aSAndroid Build Coastguard Worker  'quality_report_id',
929*6dbdd20aSAndroid Build Coastguard Worker  'packet_types',
930*6dbdd20aSAndroid Build Coastguard Worker  'connection_handle',
931*6dbdd20aSAndroid Build Coastguard Worker  'connection_role',
932*6dbdd20aSAndroid Build Coastguard Worker  'tx_power_level',
933*6dbdd20aSAndroid Build Coastguard Worker  'rssi',
934*6dbdd20aSAndroid Build Coastguard Worker  'snr',
935*6dbdd20aSAndroid Build Coastguard Worker  'unused_afh_channel_count',
936*6dbdd20aSAndroid Build Coastguard Worker  'afh_select_unideal_channel_count',
937*6dbdd20aSAndroid Build Coastguard Worker  'lsto',
938*6dbdd20aSAndroid Build Coastguard Worker  'connection_piconet_clock',
939*6dbdd20aSAndroid Build Coastguard Worker  'retransmission_count',
940*6dbdd20aSAndroid Build Coastguard Worker  'no_rx_count',
941*6dbdd20aSAndroid Build Coastguard Worker  'nak_count',
942*6dbdd20aSAndroid Build Coastguard Worker  'flow_off_count',
943*6dbdd20aSAndroid Build Coastguard Worker  'buffer_overflow_bytes',
944*6dbdd20aSAndroid Build Coastguard Worker  'buffer_underflow_bytes',
945*6dbdd20aSAndroid Build Coastguard Worker];
946*6dbdd20aSAndroid Build Coastguard Worker
947*6dbdd20aSAndroid Build Coastguard Workerconst BT_RSSI_REPORTS = `
948*6dbdd20aSAndroid Build Coastguard Worker  with base as (
949*6dbdd20aSAndroid Build Coastguard Worker    select
950*6dbdd20aSAndroid Build Coastguard Worker        ts,
951*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_device_rssi_reported.connection_handle') as connection_handle,
952*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_device_rssi_reported.hci_status') as hci_status,
953*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_device_rssi_reported.rssi') as rssi,
954*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_device_rssi_reported.metric_id') as metric_id
955*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
956*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
957*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_device_rssi_reported'
958*6dbdd20aSAndroid Build Coastguard Worker  )
959*6dbdd20aSAndroid Build Coastguard Worker  select
960*6dbdd20aSAndroid Build Coastguard Worker    *,
961*6dbdd20aSAndroid Build Coastguard Worker    0 as dur,
962*6dbdd20aSAndroid Build Coastguard Worker    'Connection '|| connection_handle as name
963*6dbdd20aSAndroid Build Coastguard Worker  from base`;
964*6dbdd20aSAndroid Build Coastguard Worker
965*6dbdd20aSAndroid Build Coastguard Workerconst BT_RSSI_REPORTS_COLUMNS = [
966*6dbdd20aSAndroid Build Coastguard Worker  'connection_handle',
967*6dbdd20aSAndroid Build Coastguard Worker  'hci_status',
968*6dbdd20aSAndroid Build Coastguard Worker  'rssi',
969*6dbdd20aSAndroid Build Coastguard Worker  'metric_id',
970*6dbdd20aSAndroid Build Coastguard Worker];
971*6dbdd20aSAndroid Build Coastguard Worker
972*6dbdd20aSAndroid Build Coastguard Workerconst BT_CODE_PATH_COUNTER = `
973*6dbdd20aSAndroid Build Coastguard Worker  with base as (
974*6dbdd20aSAndroid Build Coastguard Worker    select
975*6dbdd20aSAndroid Build Coastguard Worker        ts,
976*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_code_path_counter.key') as key,
977*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_code_path_counter.number') as number
978*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
979*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
980*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_code_path_counter'
981*6dbdd20aSAndroid Build Coastguard Worker  )
982*6dbdd20aSAndroid Build Coastguard Worker  select
983*6dbdd20aSAndroid Build Coastguard Worker    *,
984*6dbdd20aSAndroid Build Coastguard Worker    0 as dur,
985*6dbdd20aSAndroid Build Coastguard Worker    key as name
986*6dbdd20aSAndroid Build Coastguard Worker  from base`;
987*6dbdd20aSAndroid Build Coastguard Worker
988*6dbdd20aSAndroid Build Coastguard Workerconst BT_CODE_PATH_COUNTER_COLUMNS = ['key', 'number'];
989*6dbdd20aSAndroid Build Coastguard Worker
990*6dbdd20aSAndroid Build Coastguard Workerconst BT_HAL_CRASHES = `
991*6dbdd20aSAndroid Build Coastguard Worker  with base as (
992*6dbdd20aSAndroid Build Coastguard Worker      select
993*6dbdd20aSAndroid Build Coastguard Worker          ts,
994*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_hal_crash_reason_reported.metric_id') as metric_id,
995*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_hal_crash_reason_reported.error_code') as error_code,
996*6dbdd20aSAndroid Build Coastguard Worker          EXTRACT_ARG(arg_set_id, 'bluetooth_hal_crash_reason_reported.vendor_error_code') as vendor_error_code
997*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
998*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'
999*6dbdd20aSAndroid Build Coastguard Worker      and s.name = 'bluetooth_hal_crash_reason_reported'
1000*6dbdd20aSAndroid Build Coastguard Worker  )
1001*6dbdd20aSAndroid Build Coastguard Worker  select
1002*6dbdd20aSAndroid Build Coastguard Worker      *,
1003*6dbdd20aSAndroid Build Coastguard Worker      0 as dur,
1004*6dbdd20aSAndroid Build Coastguard Worker      'Device ' || metric_id as name
1005*6dbdd20aSAndroid Build Coastguard Worker  from base`;
1006*6dbdd20aSAndroid Build Coastguard Worker
1007*6dbdd20aSAndroid Build Coastguard Workerconst BT_HAL_CRASHES_COLUMNS = ['metric_id', 'error_code', 'vendor_error_code'];
1008*6dbdd20aSAndroid Build Coastguard Worker
1009*6dbdd20aSAndroid Build Coastguard Workerconst BT_BYTES = `
1010*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
1011*6dbdd20aSAndroid Build Coastguard Worker    select
1012*6dbdd20aSAndroid Build Coastguard Worker        ts,
1013*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_bytes_transfer.uid') as uid,
1014*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_bytes_transfer.tx_bytes') as tx_bytes,
1015*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_bytes_transfer.rx_bytes') as rx_bytes
1016*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
1017*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
1018*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_bytes_transfer'
1019*6dbdd20aSAndroid Build Coastguard Worker  ),
1020*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
1021*6dbdd20aSAndroid Build Coastguard Worker    select
1022*6dbdd20aSAndroid Build Coastguard Worker        ts,
1023*6dbdd20aSAndroid Build Coastguard Worker        lead(ts) over (partition by uid order by ts) - ts as dur,
1024*6dbdd20aSAndroid Build Coastguard Worker        uid,
1025*6dbdd20aSAndroid Build Coastguard Worker        lead(tx_bytes) over (partition by uid order by ts) - tx_bytes as tx_bytes,
1026*6dbdd20aSAndroid Build Coastguard Worker        lead(rx_bytes) over (partition by uid order by ts) - rx_bytes as rx_bytes
1027*6dbdd20aSAndroid Build Coastguard Worker    from step1
1028*6dbdd20aSAndroid Build Coastguard Worker  ),
1029*6dbdd20aSAndroid Build Coastguard Worker  step3 as (
1030*6dbdd20aSAndroid Build Coastguard Worker    select
1031*6dbdd20aSAndroid Build Coastguard Worker        ts,
1032*6dbdd20aSAndroid Build Coastguard Worker        dur,
1033*6dbdd20aSAndroid Build Coastguard Worker        uid % 100000 as uid,
1034*6dbdd20aSAndroid Build Coastguard Worker        sum(tx_bytes) as tx_bytes,
1035*6dbdd20aSAndroid Build Coastguard Worker        sum(rx_bytes) as rx_bytes
1036*6dbdd20aSAndroid Build Coastguard Worker    from step2
1037*6dbdd20aSAndroid Build Coastguard Worker    where tx_bytes >=0 and rx_bytes >=0
1038*6dbdd20aSAndroid Build Coastguard Worker    group by 1,2,3
1039*6dbdd20aSAndroid Build Coastguard Worker    having tx_bytes > 0 or rx_bytes > 0
1040*6dbdd20aSAndroid Build Coastguard Worker  )
1041*6dbdd20aSAndroid Build Coastguard Worker    select
1042*6dbdd20aSAndroid Build Coastguard Worker        ts,
1043*6dbdd20aSAndroid Build Coastguard Worker        dur,
1044*6dbdd20aSAndroid Build Coastguard Worker        format("%s: TX %d bytes / RX %d bytes", package_name, tx_bytes, rx_bytes) as name
1045*6dbdd20aSAndroid Build Coastguard Worker    from add_package_name!(step3)
1046*6dbdd20aSAndroid Build Coastguard Worker`;
1047*6dbdd20aSAndroid Build Coastguard Worker
1048*6dbdd20aSAndroid Build Coastguard Worker// See go/bt_system_context_report for reference on the bit-twiddling.
1049*6dbdd20aSAndroid Build Coastguard Workerconst BT_ACTIVITY = `
1050*6dbdd20aSAndroid Build Coastguard Worker  create perfetto table bt_activity as
1051*6dbdd20aSAndroid Build Coastguard Worker  with step1 as (
1052*6dbdd20aSAndroid Build Coastguard Worker    select
1053*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_activity_info.timestamp_millis') * 1000000 as ts,
1054*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_activity_info.bluetooth_stack_state') as bluetooth_stack_state,
1055*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_activity_info.controller_idle_time_millis') * 1000000 as controller_idle_dur,
1056*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_activity_info.controller_tx_time_millis') * 1000000 as controller_tx_dur,
1057*6dbdd20aSAndroid Build Coastguard Worker        EXTRACT_ARG(arg_set_id, 'bluetooth_activity_info.controller_rx_time_millis') * 1000000 as controller_rx_dur
1058*6dbdd20aSAndroid Build Coastguard Worker    from track t join slice s on t.id = s.track_id
1059*6dbdd20aSAndroid Build Coastguard Worker    where t.name = 'Statsd Atoms'
1060*6dbdd20aSAndroid Build Coastguard Worker    and s.name = 'bluetooth_activity_info'
1061*6dbdd20aSAndroid Build Coastguard Worker  ),
1062*6dbdd20aSAndroid Build Coastguard Worker  step2 as (
1063*6dbdd20aSAndroid Build Coastguard Worker    select
1064*6dbdd20aSAndroid Build Coastguard Worker        ts,
1065*6dbdd20aSAndroid Build Coastguard Worker        lead(ts) over (order by ts) - ts as dur,
1066*6dbdd20aSAndroid Build Coastguard Worker        bluetooth_stack_state,
1067*6dbdd20aSAndroid Build Coastguard Worker        lead(controller_idle_dur) over (order by ts) - controller_idle_dur as controller_idle_dur,
1068*6dbdd20aSAndroid Build Coastguard Worker        lead(controller_tx_dur) over (order by ts) - controller_tx_dur as controller_tx_dur,
1069*6dbdd20aSAndroid Build Coastguard Worker        lead(controller_rx_dur) over (order by ts) - controller_rx_dur as controller_rx_dur
1070*6dbdd20aSAndroid Build Coastguard Worker    from step1
1071*6dbdd20aSAndroid Build Coastguard Worker  )
1072*6dbdd20aSAndroid Build Coastguard Worker  select
1073*6dbdd20aSAndroid Build Coastguard Worker    ts,
1074*6dbdd20aSAndroid Build Coastguard Worker    dur,
1075*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x0000000F as acl_active_count,
1076*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x000000F0 >> 4 as acl_sniff_count,
1077*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x00000F00 >> 8 as acl_ble_count,
1078*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x0000F000 >> 12 as advertising_count,
1079*6dbdd20aSAndroid Build Coastguard Worker    case bluetooth_stack_state & 0x000F0000 >> 16
1080*6dbdd20aSAndroid Build Coastguard Worker      when 0 then 0
1081*6dbdd20aSAndroid Build Coastguard Worker      when 1 then 5
1082*6dbdd20aSAndroid Build Coastguard Worker      when 2 then 10
1083*6dbdd20aSAndroid Build Coastguard Worker      when 3 then 25
1084*6dbdd20aSAndroid Build Coastguard Worker      when 4 then 100
1085*6dbdd20aSAndroid Build Coastguard Worker      else -1
1086*6dbdd20aSAndroid Build Coastguard Worker    end as le_scan_duty_cycle,
1087*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x00100000 >> 20 as inquiry_active,
1088*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x00200000 >> 21 as sco_active,
1089*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x00400000 >> 22 as a2dp_active,
1090*6dbdd20aSAndroid Build Coastguard Worker    bluetooth_stack_state & 0x00800000 >> 23 as le_audio_active,
1091*6dbdd20aSAndroid Build Coastguard Worker    max(0, 100.0 * controller_idle_dur / dur) as controller_idle_pct,
1092*6dbdd20aSAndroid Build Coastguard Worker    max(0, 100.0 * controller_tx_dur / dur) as controller_tx_pct,
1093*6dbdd20aSAndroid Build Coastguard Worker    max(0, 100.0 * controller_rx_dur / dur) as controller_rx_pct
1094*6dbdd20aSAndroid Build Coastguard Worker  from step2
1095*6dbdd20aSAndroid Build Coastguard Worker`;
1096*6dbdd20aSAndroid Build Coastguard Worker
1097*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin {
1098*6dbdd20aSAndroid Build Coastguard Worker  static readonly id = 'dev.perfetto.AndroidLongBatteryTracing';
1099*6dbdd20aSAndroid Build Coastguard Worker  private readonly groups = new Map<string, TrackNode>();
1100*6dbdd20aSAndroid Build Coastguard Worker
1101*6dbdd20aSAndroid Build Coastguard Worker  private addTrack(ctx: Trace, track: TrackNode, groupName?: string): void {
1102*6dbdd20aSAndroid Build Coastguard Worker    if (groupName) {
1103*6dbdd20aSAndroid Build Coastguard Worker      const existingGroup = this.groups.get(groupName);
1104*6dbdd20aSAndroid Build Coastguard Worker      if (existingGroup) {
1105*6dbdd20aSAndroid Build Coastguard Worker        existingGroup.addChildInOrder(track);
1106*6dbdd20aSAndroid Build Coastguard Worker      } else {
1107*6dbdd20aSAndroid Build Coastguard Worker        const group = new TrackNode({title: groupName, isSummary: true});
1108*6dbdd20aSAndroid Build Coastguard Worker        group.addChildInOrder(track);
1109*6dbdd20aSAndroid Build Coastguard Worker        this.groups.set(groupName, group);
1110*6dbdd20aSAndroid Build Coastguard Worker        ctx.workspace.addChildInOrder(group);
1111*6dbdd20aSAndroid Build Coastguard Worker      }
1112*6dbdd20aSAndroid Build Coastguard Worker    } else {
1113*6dbdd20aSAndroid Build Coastguard Worker      ctx.workspace.addChildInOrder(track);
1114*6dbdd20aSAndroid Build Coastguard Worker    }
1115*6dbdd20aSAndroid Build Coastguard Worker  }
1116*6dbdd20aSAndroid Build Coastguard Worker
1117*6dbdd20aSAndroid Build Coastguard Worker  async addSliceTrack(
1118*6dbdd20aSAndroid Build Coastguard Worker    ctx: Trace,
1119*6dbdd20aSAndroid Build Coastguard Worker    name: string,
1120*6dbdd20aSAndroid Build Coastguard Worker    query: string,
1121*6dbdd20aSAndroid Build Coastguard Worker    groupName?: string,
1122*6dbdd20aSAndroid Build Coastguard Worker    columns: string[] = [],
1123*6dbdd20aSAndroid Build Coastguard Worker  ) {
1124*6dbdd20aSAndroid Build Coastguard Worker    const uri = `/long_battery_tracing_${name}`;
1125*6dbdd20aSAndroid Build Coastguard Worker    const track = await createQuerySliceTrack({
1126*6dbdd20aSAndroid Build Coastguard Worker      trace: ctx,
1127*6dbdd20aSAndroid Build Coastguard Worker      uri,
1128*6dbdd20aSAndroid Build Coastguard Worker      data: {
1129*6dbdd20aSAndroid Build Coastguard Worker        sqlSource: query,
1130*6dbdd20aSAndroid Build Coastguard Worker        columns: ['ts', 'dur', 'name', ...columns],
1131*6dbdd20aSAndroid Build Coastguard Worker      },
1132*6dbdd20aSAndroid Build Coastguard Worker      argColumns: columns,
1133*6dbdd20aSAndroid Build Coastguard Worker    });
1134*6dbdd20aSAndroid Build Coastguard Worker    ctx.tracks.registerTrack({
1135*6dbdd20aSAndroid Build Coastguard Worker      uri,
1136*6dbdd20aSAndroid Build Coastguard Worker      title: name,
1137*6dbdd20aSAndroid Build Coastguard Worker      track,
1138*6dbdd20aSAndroid Build Coastguard Worker    });
1139*6dbdd20aSAndroid Build Coastguard Worker    const trackNode = new TrackNode({uri, title: name});
1140*6dbdd20aSAndroid Build Coastguard Worker    this.addTrack(ctx, trackNode, groupName);
1141*6dbdd20aSAndroid Build Coastguard Worker  }
1142*6dbdd20aSAndroid Build Coastguard Worker
1143*6dbdd20aSAndroid Build Coastguard Worker  async addCounterTrack(
1144*6dbdd20aSAndroid Build Coastguard Worker    ctx: Trace,
1145*6dbdd20aSAndroid Build Coastguard Worker    name: string,
1146*6dbdd20aSAndroid Build Coastguard Worker    query: string,
1147*6dbdd20aSAndroid Build Coastguard Worker    groupName: string,
1148*6dbdd20aSAndroid Build Coastguard Worker    options?: Partial<CounterOptions>,
1149*6dbdd20aSAndroid Build Coastguard Worker  ) {
1150*6dbdd20aSAndroid Build Coastguard Worker    const uri = `/long_battery_tracing_${name}`;
1151*6dbdd20aSAndroid Build Coastguard Worker    const track = await createQueryCounterTrack({
1152*6dbdd20aSAndroid Build Coastguard Worker      trace: ctx,
1153*6dbdd20aSAndroid Build Coastguard Worker      uri,
1154*6dbdd20aSAndroid Build Coastguard Worker      data: {
1155*6dbdd20aSAndroid Build Coastguard Worker        sqlSource: query,
1156*6dbdd20aSAndroid Build Coastguard Worker        columns: ['ts', 'value'],
1157*6dbdd20aSAndroid Build Coastguard Worker      },
1158*6dbdd20aSAndroid Build Coastguard Worker      options,
1159*6dbdd20aSAndroid Build Coastguard Worker    });
1160*6dbdd20aSAndroid Build Coastguard Worker    ctx.tracks.registerTrack({
1161*6dbdd20aSAndroid Build Coastguard Worker      uri,
1162*6dbdd20aSAndroid Build Coastguard Worker      title: name,
1163*6dbdd20aSAndroid Build Coastguard Worker      track,
1164*6dbdd20aSAndroid Build Coastguard Worker    });
1165*6dbdd20aSAndroid Build Coastguard Worker    const trackNode = new TrackNode({uri, title: name});
1166*6dbdd20aSAndroid Build Coastguard Worker    this.addTrack(ctx, trackNode, groupName);
1167*6dbdd20aSAndroid Build Coastguard Worker  }
1168*6dbdd20aSAndroid Build Coastguard Worker
1169*6dbdd20aSAndroid Build Coastguard Worker  async addBatteryStatsState(
1170*6dbdd20aSAndroid Build Coastguard Worker    ctx: Trace,
1171*6dbdd20aSAndroid Build Coastguard Worker    name: string,
1172*6dbdd20aSAndroid Build Coastguard Worker    track: string,
1173*6dbdd20aSAndroid Build Coastguard Worker    groupName: string,
1174*6dbdd20aSAndroid Build Coastguard Worker    features: Set<string>,
1175*6dbdd20aSAndroid Build Coastguard Worker  ) {
1176*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has(`track.${track}`)) {
1177*6dbdd20aSAndroid Build Coastguard Worker      return;
1178*6dbdd20aSAndroid Build Coastguard Worker    }
1179*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1180*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1181*6dbdd20aSAndroid Build Coastguard Worker      name,
1182*6dbdd20aSAndroid Build Coastguard Worker      `SELECT ts, safe_dur AS dur, value_name AS name
1183*6dbdd20aSAndroid Build Coastguard Worker    FROM android_battery_stats_state
1184*6dbdd20aSAndroid Build Coastguard Worker    WHERE track_name = "${track}"`,
1185*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1186*6dbdd20aSAndroid Build Coastguard Worker    );
1187*6dbdd20aSAndroid Build Coastguard Worker  }
1188*6dbdd20aSAndroid Build Coastguard Worker
1189*6dbdd20aSAndroid Build Coastguard Worker  async addBatteryStatsEvent(
1190*6dbdd20aSAndroid Build Coastguard Worker    ctx: Trace,
1191*6dbdd20aSAndroid Build Coastguard Worker    name: string,
1192*6dbdd20aSAndroid Build Coastguard Worker    track: string,
1193*6dbdd20aSAndroid Build Coastguard Worker    groupName: string | undefined,
1194*6dbdd20aSAndroid Build Coastguard Worker    features: Set<string>,
1195*6dbdd20aSAndroid Build Coastguard Worker  ) {
1196*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has(`track.${track}`)) {
1197*6dbdd20aSAndroid Build Coastguard Worker      return;
1198*6dbdd20aSAndroid Build Coastguard Worker    }
1199*6dbdd20aSAndroid Build Coastguard Worker
1200*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1201*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1202*6dbdd20aSAndroid Build Coastguard Worker      name,
1203*6dbdd20aSAndroid Build Coastguard Worker      `SELECT ts, safe_dur AS dur, str_value AS name
1204*6dbdd20aSAndroid Build Coastguard Worker    FROM android_battery_stats_event_slices
1205*6dbdd20aSAndroid Build Coastguard Worker    WHERE track_name = "${track}"`,
1206*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1207*6dbdd20aSAndroid Build Coastguard Worker    );
1208*6dbdd20aSAndroid Build Coastguard Worker  }
1209*6dbdd20aSAndroid Build Coastguard Worker
1210*6dbdd20aSAndroid Build Coastguard Worker  async addDeviceState(ctx: Trace, features: Set<string>): Promise<void> {
1211*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has('track.battery_stats.*')) {
1212*6dbdd20aSAndroid Build Coastguard Worker      return;
1213*6dbdd20aSAndroid Build Coastguard Worker    }
1214*6dbdd20aSAndroid Build Coastguard Worker
1215*6dbdd20aSAndroid Build Coastguard Worker    const query = (name: string, track: string) =>
1216*6dbdd20aSAndroid Build Coastguard Worker      this.addBatteryStatsEvent(ctx, name, track, undefined, features);
1217*6dbdd20aSAndroid Build Coastguard Worker
1218*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1219*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.battery_stats;`);
1220*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.suspend;`);
1221*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE counters.intervals;`);
1222*6dbdd20aSAndroid Build Coastguard Worker
1223*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Device State: Screen state', SCREEN_STATE);
1224*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Device State: Charging', CHARGING);
1225*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1226*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1227*6dbdd20aSAndroid Build Coastguard Worker      'Device State: Suspend / resume',
1228*6dbdd20aSAndroid Build Coastguard Worker      SUSPEND_RESUME,
1229*6dbdd20aSAndroid Build Coastguard Worker    );
1230*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Device State: Doze light state', DOZE_LIGHT);
1231*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Device State: Doze deep state', DOZE_DEEP);
1232*6dbdd20aSAndroid Build Coastguard Worker
1233*6dbdd20aSAndroid Build Coastguard Worker    query('Device State: Top app', 'battery_stats.top');
1234*6dbdd20aSAndroid Build Coastguard Worker
1235*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1236*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1237*6dbdd20aSAndroid Build Coastguard Worker      'Device State: Long wakelocks',
1238*6dbdd20aSAndroid Build Coastguard Worker      `SELECT
1239*6dbdd20aSAndroid Build Coastguard Worker            ts - 60000000000 as ts,
1240*6dbdd20aSAndroid Build Coastguard Worker            safe_dur + 60000000000 as dur,
1241*6dbdd20aSAndroid Build Coastguard Worker            str_value AS name,
1242*6dbdd20aSAndroid Build Coastguard Worker            package_name as package
1243*6dbdd20aSAndroid Build Coastguard Worker        FROM add_package_name!((
1244*6dbdd20aSAndroid Build Coastguard Worker          select *, int_value as uid
1245*6dbdd20aSAndroid Build Coastguard Worker          from android_battery_stats_event_slices
1246*6dbdd20aSAndroid Build Coastguard Worker          WHERE track_name = "battery_stats.longwake"
1247*6dbdd20aSAndroid Build Coastguard Worker        ))`,
1248*6dbdd20aSAndroid Build Coastguard Worker      undefined,
1249*6dbdd20aSAndroid Build Coastguard Worker      ['package'],
1250*6dbdd20aSAndroid Build Coastguard Worker    );
1251*6dbdd20aSAndroid Build Coastguard Worker
1252*6dbdd20aSAndroid Build Coastguard Worker    query('Device State: Foreground apps', 'battery_stats.fg');
1253*6dbdd20aSAndroid Build Coastguard Worker    query('Device State: Jobs', 'battery_stats.job');
1254*6dbdd20aSAndroid Build Coastguard Worker
1255*6dbdd20aSAndroid Build Coastguard Worker    if (features.has('atom.thermal_throttling_severity_state_changed')) {
1256*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1257*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1258*6dbdd20aSAndroid Build Coastguard Worker        'Device State: Thermal throttling',
1259*6dbdd20aSAndroid Build Coastguard Worker        THERMAL_THROTTLING,
1260*6dbdd20aSAndroid Build Coastguard Worker      );
1261*6dbdd20aSAndroid Build Coastguard Worker    }
1262*6dbdd20aSAndroid Build Coastguard Worker  }
1263*6dbdd20aSAndroid Build Coastguard Worker
1264*6dbdd20aSAndroid Build Coastguard Worker  async addAtomCounters(ctx: Trace): Promise<void> {
1265*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1266*6dbdd20aSAndroid Build Coastguard Worker
1267*6dbdd20aSAndroid Build Coastguard Worker    try {
1268*6dbdd20aSAndroid Build Coastguard Worker      await e.query(
1269*6dbdd20aSAndroid Build Coastguard Worker        `INCLUDE PERFETTO MODULE
1270*6dbdd20aSAndroid Build Coastguard Worker            google3.wireless.android.telemetry.trace_extractor.modules.atom_counters_slices`,
1271*6dbdd20aSAndroid Build Coastguard Worker      );
1272*6dbdd20aSAndroid Build Coastguard Worker    } catch (e) {
1273*6dbdd20aSAndroid Build Coastguard Worker      return;
1274*6dbdd20aSAndroid Build Coastguard Worker    }
1275*6dbdd20aSAndroid Build Coastguard Worker
1276*6dbdd20aSAndroid Build Coastguard Worker    const counters = await e.query(
1277*6dbdd20aSAndroid Build Coastguard Worker      `select distinct ui_group, ui_name, ui_unit, counter_name
1278*6dbdd20aSAndroid Build Coastguard Worker       from atom_counters
1279*6dbdd20aSAndroid Build Coastguard Worker       where ui_name is not null`,
1280*6dbdd20aSAndroid Build Coastguard Worker    );
1281*6dbdd20aSAndroid Build Coastguard Worker    const countersIt = counters.iter({
1282*6dbdd20aSAndroid Build Coastguard Worker      ui_group: 'str',
1283*6dbdd20aSAndroid Build Coastguard Worker      ui_name: 'str',
1284*6dbdd20aSAndroid Build Coastguard Worker      ui_unit: 'str',
1285*6dbdd20aSAndroid Build Coastguard Worker      counter_name: 'str',
1286*6dbdd20aSAndroid Build Coastguard Worker    });
1287*6dbdd20aSAndroid Build Coastguard Worker    for (; countersIt.valid(); countersIt.next()) {
1288*6dbdd20aSAndroid Build Coastguard Worker      const unit = countersIt.ui_unit;
1289*6dbdd20aSAndroid Build Coastguard Worker      const opts =
1290*6dbdd20aSAndroid Build Coastguard Worker        unit === '%'
1291*6dbdd20aSAndroid Build Coastguard Worker          ? {yOverrideMaximum: 100, unit: '%'}
1292*6dbdd20aSAndroid Build Coastguard Worker          : unit !== undefined
1293*6dbdd20aSAndroid Build Coastguard Worker            ? {unit}
1294*6dbdd20aSAndroid Build Coastguard Worker            : undefined;
1295*6dbdd20aSAndroid Build Coastguard Worker
1296*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1297*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1298*6dbdd20aSAndroid Build Coastguard Worker        countersIt.ui_name,
1299*6dbdd20aSAndroid Build Coastguard Worker        `select ts, ${unit === '%' ? 100.0 : 1.0} * counter_value as value
1300*6dbdd20aSAndroid Build Coastguard Worker         from atom_counters
1301*6dbdd20aSAndroid Build Coastguard Worker         where counter_name = '${countersIt.counter_name}'`,
1302*6dbdd20aSAndroid Build Coastguard Worker        countersIt.ui_group,
1303*6dbdd20aSAndroid Build Coastguard Worker        opts,
1304*6dbdd20aSAndroid Build Coastguard Worker      );
1305*6dbdd20aSAndroid Build Coastguard Worker    }
1306*6dbdd20aSAndroid Build Coastguard Worker  }
1307*6dbdd20aSAndroid Build Coastguard Worker
1308*6dbdd20aSAndroid Build Coastguard Worker  async addAtomSlices(ctx: Trace): Promise<void> {
1309*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1310*6dbdd20aSAndroid Build Coastguard Worker
1311*6dbdd20aSAndroid Build Coastguard Worker    try {
1312*6dbdd20aSAndroid Build Coastguard Worker      await e.query(
1313*6dbdd20aSAndroid Build Coastguard Worker        `INCLUDE PERFETTO MODULE
1314*6dbdd20aSAndroid Build Coastguard Worker            google3.wireless.android.telemetry.trace_extractor.modules.atom_counters_slices`,
1315*6dbdd20aSAndroid Build Coastguard Worker      );
1316*6dbdd20aSAndroid Build Coastguard Worker    } catch (e) {
1317*6dbdd20aSAndroid Build Coastguard Worker      return;
1318*6dbdd20aSAndroid Build Coastguard Worker    }
1319*6dbdd20aSAndroid Build Coastguard Worker
1320*6dbdd20aSAndroid Build Coastguard Worker    const sliceTracks = await e.query(
1321*6dbdd20aSAndroid Build Coastguard Worker      `select distinct ui_group, ui_name, atom, field
1322*6dbdd20aSAndroid Build Coastguard Worker       from atom_slices
1323*6dbdd20aSAndroid Build Coastguard Worker       where ui_name is not null
1324*6dbdd20aSAndroid Build Coastguard Worker       order by 1, 2, 3, 4`,
1325*6dbdd20aSAndroid Build Coastguard Worker    );
1326*6dbdd20aSAndroid Build Coastguard Worker    const slicesIt = sliceTracks.iter({
1327*6dbdd20aSAndroid Build Coastguard Worker      atom: 'str',
1328*6dbdd20aSAndroid Build Coastguard Worker      ui_group: 'str',
1329*6dbdd20aSAndroid Build Coastguard Worker      ui_name: 'str',
1330*6dbdd20aSAndroid Build Coastguard Worker      field: 'str',
1331*6dbdd20aSAndroid Build Coastguard Worker    });
1332*6dbdd20aSAndroid Build Coastguard Worker
1333*6dbdd20aSAndroid Build Coastguard Worker    const tracks = new Map<
1334*6dbdd20aSAndroid Build Coastguard Worker      string,
1335*6dbdd20aSAndroid Build Coastguard Worker      {
1336*6dbdd20aSAndroid Build Coastguard Worker        ui_group: string;
1337*6dbdd20aSAndroid Build Coastguard Worker        ui_name: string;
1338*6dbdd20aSAndroid Build Coastguard Worker      }
1339*6dbdd20aSAndroid Build Coastguard Worker    >();
1340*6dbdd20aSAndroid Build Coastguard Worker    const fields = new Map<string, string[]>();
1341*6dbdd20aSAndroid Build Coastguard Worker    for (; slicesIt.valid(); slicesIt.next()) {
1342*6dbdd20aSAndroid Build Coastguard Worker      const atom = slicesIt.atom;
1343*6dbdd20aSAndroid Build Coastguard Worker      let args = fields.get(atom);
1344*6dbdd20aSAndroid Build Coastguard Worker      if (args === undefined) {
1345*6dbdd20aSAndroid Build Coastguard Worker        args = [];
1346*6dbdd20aSAndroid Build Coastguard Worker        fields.set(atom, args);
1347*6dbdd20aSAndroid Build Coastguard Worker      }
1348*6dbdd20aSAndroid Build Coastguard Worker      args.push(slicesIt.field);
1349*6dbdd20aSAndroid Build Coastguard Worker      tracks.set(atom, {
1350*6dbdd20aSAndroid Build Coastguard Worker        ui_group: slicesIt.ui_group,
1351*6dbdd20aSAndroid Build Coastguard Worker        ui_name: slicesIt.ui_name,
1352*6dbdd20aSAndroid Build Coastguard Worker      });
1353*6dbdd20aSAndroid Build Coastguard Worker    }
1354*6dbdd20aSAndroid Build Coastguard Worker
1355*6dbdd20aSAndroid Build Coastguard Worker    for (const [atom, args] of fields) {
1356*6dbdd20aSAndroid Build Coastguard Worker      function safeArg(arg: string) {
1357*6dbdd20aSAndroid Build Coastguard Worker        return arg.replaceAll(/[[\]]/g, '').replaceAll(/\./g, '_');
1358*6dbdd20aSAndroid Build Coastguard Worker      }
1359*6dbdd20aSAndroid Build Coastguard Worker
1360*6dbdd20aSAndroid Build Coastguard Worker      // We need to make arg names compatible with SQL here because they pass through several
1361*6dbdd20aSAndroid Build Coastguard Worker      // layers of SQL without being quoted in "".
1362*6dbdd20aSAndroid Build Coastguard Worker      function argSql(arg: string) {
1363*6dbdd20aSAndroid Build Coastguard Worker        return `max(case when field = '${arg}' then ifnull(string_value, int_value) end)
1364*6dbdd20aSAndroid Build Coastguard Worker                as ${safeArg(arg)}`;
1365*6dbdd20aSAndroid Build Coastguard Worker      }
1366*6dbdd20aSAndroid Build Coastguard Worker
1367*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1368*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1369*6dbdd20aSAndroid Build Coastguard Worker        tracks.get(atom)!.ui_name,
1370*6dbdd20aSAndroid Build Coastguard Worker        `select ts, dur, slice_name as name, ${args.map((a) => argSql(a)).join(', ')}
1371*6dbdd20aSAndroid Build Coastguard Worker         from atom_slices
1372*6dbdd20aSAndroid Build Coastguard Worker         where atom = '${atom}'
1373*6dbdd20aSAndroid Build Coastguard Worker         group by ts, dur, name`,
1374*6dbdd20aSAndroid Build Coastguard Worker        tracks.get(atom)!.ui_group,
1375*6dbdd20aSAndroid Build Coastguard Worker        args.map((a) => safeArg(a)),
1376*6dbdd20aSAndroid Build Coastguard Worker      );
1377*6dbdd20aSAndroid Build Coastguard Worker    }
1378*6dbdd20aSAndroid Build Coastguard Worker  }
1379*6dbdd20aSAndroid Build Coastguard Worker
1380*6dbdd20aSAndroid Build Coastguard Worker  async addNetworkSummary(ctx: Trace, features: Set<string>): Promise<void> {
1381*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has('net.modem') && !features.has('net.wifi')) {
1382*6dbdd20aSAndroid Build Coastguard Worker      return;
1383*6dbdd20aSAndroid Build Coastguard Worker    }
1384*6dbdd20aSAndroid Build Coastguard Worker
1385*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'Network Summary';
1386*6dbdd20aSAndroid Build Coastguard Worker
1387*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1388*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.battery_stats;`);
1389*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.network_packets;`);
1390*6dbdd20aSAndroid Build Coastguard Worker    await e.query(NETWORK_SUMMARY);
1391*6dbdd20aSAndroid Build Coastguard Worker    await e.query(RADIO_TRANSPORT_TYPE);
1392*6dbdd20aSAndroid Build Coastguard Worker
1393*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1394*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1395*6dbdd20aSAndroid Build Coastguard Worker      'Default network',
1396*6dbdd20aSAndroid Build Coastguard Worker      DEFAULT_NETWORK,
1397*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1398*6dbdd20aSAndroid Build Coastguard Worker    );
1399*6dbdd20aSAndroid Build Coastguard Worker
1400*6dbdd20aSAndroid Build Coastguard Worker    if (features.has('atom.network_tethering_reported')) {
1401*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(ctx, 'Tethering', TETHERING, groupName);
1402*6dbdd20aSAndroid Build Coastguard Worker    }
1403*6dbdd20aSAndroid Build Coastguard Worker    if (features.has('net.wifi')) {
1404*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1405*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1406*6dbdd20aSAndroid Build Coastguard Worker        'Wifi total bytes',
1407*6dbdd20aSAndroid Build Coastguard Worker        `select ts, sum(value) as value from network_summary where dev_type = 'wifi' group by 1`,
1408*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1409*6dbdd20aSAndroid Build Coastguard Worker        {yDisplay: 'log', yRangeSharingKey: 'net_bytes', unit: 'byte'},
1410*6dbdd20aSAndroid Build Coastguard Worker      );
1411*6dbdd20aSAndroid Build Coastguard Worker      const result = await e.query(
1412*6dbdd20aSAndroid Build Coastguard Worker        `select pkg, sum(value) from network_summary where dev_type='wifi' group by 1 order by 2 desc limit 10`,
1413*6dbdd20aSAndroid Build Coastguard Worker      );
1414*6dbdd20aSAndroid Build Coastguard Worker      const it = result.iter({pkg: 'str'});
1415*6dbdd20aSAndroid Build Coastguard Worker      for (; it.valid(); it.next()) {
1416*6dbdd20aSAndroid Build Coastguard Worker        await this.addCounterTrack(
1417*6dbdd20aSAndroid Build Coastguard Worker          ctx,
1418*6dbdd20aSAndroid Build Coastguard Worker          `Top wifi: ${it.pkg}`,
1419*6dbdd20aSAndroid Build Coastguard Worker          `select ts, value from network_summary where dev_type = 'wifi' and pkg = '${it.pkg}'`,
1420*6dbdd20aSAndroid Build Coastguard Worker          groupName,
1421*6dbdd20aSAndroid Build Coastguard Worker          {yDisplay: 'log', yRangeSharingKey: 'net_bytes', unit: 'byte'},
1422*6dbdd20aSAndroid Build Coastguard Worker        );
1423*6dbdd20aSAndroid Build Coastguard Worker      }
1424*6dbdd20aSAndroid Build Coastguard Worker    }
1425*6dbdd20aSAndroid Build Coastguard Worker    this.addBatteryStatsState(
1426*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1427*6dbdd20aSAndroid Build Coastguard Worker      'Wifi interface',
1428*6dbdd20aSAndroid Build Coastguard Worker      'battery_stats.wifi_radio',
1429*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1430*6dbdd20aSAndroid Build Coastguard Worker      features,
1431*6dbdd20aSAndroid Build Coastguard Worker    );
1432*6dbdd20aSAndroid Build Coastguard Worker    this.addBatteryStatsState(
1433*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1434*6dbdd20aSAndroid Build Coastguard Worker      'Wifi supplicant state',
1435*6dbdd20aSAndroid Build Coastguard Worker      'battery_stats.wifi_suppl',
1436*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1437*6dbdd20aSAndroid Build Coastguard Worker      features,
1438*6dbdd20aSAndroid Build Coastguard Worker    );
1439*6dbdd20aSAndroid Build Coastguard Worker    this.addBatteryStatsState(
1440*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1441*6dbdd20aSAndroid Build Coastguard Worker      'Wifi strength',
1442*6dbdd20aSAndroid Build Coastguard Worker      'battery_stats.wifi_signal_strength',
1443*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1444*6dbdd20aSAndroid Build Coastguard Worker      features,
1445*6dbdd20aSAndroid Build Coastguard Worker    );
1446*6dbdd20aSAndroid Build Coastguard Worker    if (features.has('net.modem')) {
1447*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1448*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1449*6dbdd20aSAndroid Build Coastguard Worker        'Modem total bytes',
1450*6dbdd20aSAndroid Build Coastguard Worker        `select ts, sum(value) as value from network_summary where dev_type = 'modem' group by 1`,
1451*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1452*6dbdd20aSAndroid Build Coastguard Worker        {yDisplay: 'log', yRangeSharingKey: 'net_bytes', unit: 'byte'},
1453*6dbdd20aSAndroid Build Coastguard Worker      );
1454*6dbdd20aSAndroid Build Coastguard Worker      const result = await e.query(
1455*6dbdd20aSAndroid Build Coastguard Worker        `select pkg, sum(value) from network_summary where dev_type='modem' group by 1 order by 2 desc limit 10`,
1456*6dbdd20aSAndroid Build Coastguard Worker      );
1457*6dbdd20aSAndroid Build Coastguard Worker      const it = result.iter({pkg: 'str'});
1458*6dbdd20aSAndroid Build Coastguard Worker      for (; it.valid(); it.next()) {
1459*6dbdd20aSAndroid Build Coastguard Worker        await this.addCounterTrack(
1460*6dbdd20aSAndroid Build Coastguard Worker          ctx,
1461*6dbdd20aSAndroid Build Coastguard Worker          `Top modem: ${it.pkg}`,
1462*6dbdd20aSAndroid Build Coastguard Worker          `select ts, value from network_summary where dev_type = 'modem' and pkg = '${it.pkg}'`,
1463*6dbdd20aSAndroid Build Coastguard Worker          groupName,
1464*6dbdd20aSAndroid Build Coastguard Worker          {yDisplay: 'log', yRangeSharingKey: 'net_bytes', unit: 'byte'},
1465*6dbdd20aSAndroid Build Coastguard Worker        );
1466*6dbdd20aSAndroid Build Coastguard Worker      }
1467*6dbdd20aSAndroid Build Coastguard Worker    }
1468*6dbdd20aSAndroid Build Coastguard Worker    this.addBatteryStatsState(
1469*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1470*6dbdd20aSAndroid Build Coastguard Worker      'Cellular interface',
1471*6dbdd20aSAndroid Build Coastguard Worker      'battery_stats.mobile_radio',
1472*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1473*6dbdd20aSAndroid Build Coastguard Worker      features,
1474*6dbdd20aSAndroid Build Coastguard Worker    );
1475*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1476*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1477*6dbdd20aSAndroid Build Coastguard Worker      'Cellular connection',
1478*6dbdd20aSAndroid Build Coastguard Worker      `select ts, dur, name from radio_transport`,
1479*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1480*6dbdd20aSAndroid Build Coastguard Worker    );
1481*6dbdd20aSAndroid Build Coastguard Worker    this.addBatteryStatsState(
1482*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1483*6dbdd20aSAndroid Build Coastguard Worker      'Cellular strength',
1484*6dbdd20aSAndroid Build Coastguard Worker      'battery_stats.phone_signal_strength',
1485*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1486*6dbdd20aSAndroid Build Coastguard Worker      features,
1487*6dbdd20aSAndroid Build Coastguard Worker    );
1488*6dbdd20aSAndroid Build Coastguard Worker  }
1489*6dbdd20aSAndroid Build Coastguard Worker
1490*6dbdd20aSAndroid Build Coastguard Worker  async addModemDetail(ctx: Trace, features: Set<string>): Promise<void> {
1491*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'Modem Detail';
1492*6dbdd20aSAndroid Build Coastguard Worker    if (features.has('track.ril')) {
1493*6dbdd20aSAndroid Build Coastguard Worker      await this.addModemRil(ctx, groupName);
1494*6dbdd20aSAndroid Build Coastguard Worker    }
1495*6dbdd20aSAndroid Build Coastguard Worker    await this.addModemTeaData(ctx, groupName);
1496*6dbdd20aSAndroid Build Coastguard Worker  }
1497*6dbdd20aSAndroid Build Coastguard Worker
1498*6dbdd20aSAndroid Build Coastguard Worker  async addModemRil(ctx: Trace, groupName: string): Promise<void> {
1499*6dbdd20aSAndroid Build Coastguard Worker    const rilStrength = async (band: string, value: string) =>
1500*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1501*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1502*6dbdd20aSAndroid Build Coastguard Worker        `Modem signal strength ${band} ${value}`,
1503*6dbdd20aSAndroid Build Coastguard Worker        `SELECT ts, dur, name FROM RilScreenOn WHERE band_name = '${band}' AND value_name = '${value}'`,
1504*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1505*6dbdd20aSAndroid Build Coastguard Worker      );
1506*6dbdd20aSAndroid Build Coastguard Worker
1507*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1508*6dbdd20aSAndroid Build Coastguard Worker
1509*6dbdd20aSAndroid Build Coastguard Worker    await e.query(MODEM_RIL_STRENGTH);
1510*6dbdd20aSAndroid Build Coastguard Worker    await e.query(MODEM_RIL_CHANNELS_PREAMBLE);
1511*6dbdd20aSAndroid Build Coastguard Worker
1512*6dbdd20aSAndroid Build Coastguard Worker    await rilStrength('LTE', 'rsrp');
1513*6dbdd20aSAndroid Build Coastguard Worker    await rilStrength('LTE', 'rssi');
1514*6dbdd20aSAndroid Build Coastguard Worker    await rilStrength('NR', 'rsrp');
1515*6dbdd20aSAndroid Build Coastguard Worker    await rilStrength('NR', 'rssi');
1516*6dbdd20aSAndroid Build Coastguard Worker
1517*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1518*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1519*6dbdd20aSAndroid Build Coastguard Worker      'Modem channel config',
1520*6dbdd20aSAndroid Build Coastguard Worker      MODEM_RIL_CHANNELS,
1521*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1522*6dbdd20aSAndroid Build Coastguard Worker    );
1523*6dbdd20aSAndroid Build Coastguard Worker
1524*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1525*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1526*6dbdd20aSAndroid Build Coastguard Worker      'Modem cell reselection',
1527*6dbdd20aSAndroid Build Coastguard Worker      MODEM_CELL_RESELECTION,
1528*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1529*6dbdd20aSAndroid Build Coastguard Worker      ['raw_ril'],
1530*6dbdd20aSAndroid Build Coastguard Worker    );
1531*6dbdd20aSAndroid Build Coastguard Worker  }
1532*6dbdd20aSAndroid Build Coastguard Worker
1533*6dbdd20aSAndroid Build Coastguard Worker  async addModemTeaData(ctx: Trace, groupName: string): Promise<void> {
1534*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1535*6dbdd20aSAndroid Build Coastguard Worker
1536*6dbdd20aSAndroid Build Coastguard Worker    try {
1537*6dbdd20aSAndroid Build Coastguard Worker      await e.query(
1538*6dbdd20aSAndroid Build Coastguard Worker        `INCLUDE PERFETTO MODULE
1539*6dbdd20aSAndroid Build Coastguard Worker            google3.wireless.android.telemetry.trace_extractor.modules.modem_tea_metrics`,
1540*6dbdd20aSAndroid Build Coastguard Worker      );
1541*6dbdd20aSAndroid Build Coastguard Worker    } catch {
1542*6dbdd20aSAndroid Build Coastguard Worker      return;
1543*6dbdd20aSAndroid Build Coastguard Worker    }
1544*6dbdd20aSAndroid Build Coastguard Worker
1545*6dbdd20aSAndroid Build Coastguard Worker    const counters = await e.query(
1546*6dbdd20aSAndroid Build Coastguard Worker      `select distinct name from pixel_modem_counters`,
1547*6dbdd20aSAndroid Build Coastguard Worker    );
1548*6dbdd20aSAndroid Build Coastguard Worker    const countersIt = counters.iter({name: 'str'});
1549*6dbdd20aSAndroid Build Coastguard Worker    for (; countersIt.valid(); countersIt.next()) {
1550*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1551*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1552*6dbdd20aSAndroid Build Coastguard Worker        countersIt.name,
1553*6dbdd20aSAndroid Build Coastguard Worker        `select ts, value from pixel_modem_counters where name = '${countersIt.name}'`,
1554*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1555*6dbdd20aSAndroid Build Coastguard Worker      );
1556*6dbdd20aSAndroid Build Coastguard Worker    }
1557*6dbdd20aSAndroid Build Coastguard Worker    const slices = await e.query(
1558*6dbdd20aSAndroid Build Coastguard Worker      `select distinct track_name from pixel_modem_slices`,
1559*6dbdd20aSAndroid Build Coastguard Worker    );
1560*6dbdd20aSAndroid Build Coastguard Worker    const slicesIt = slices.iter({track_name: 'str'});
1561*6dbdd20aSAndroid Build Coastguard Worker    for (; slicesIt.valid(); slicesIt.next()) {
1562*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1563*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1564*6dbdd20aSAndroid Build Coastguard Worker        slicesIt.track_name,
1565*6dbdd20aSAndroid Build Coastguard Worker        `select ts, dur, slice_name as name from pixel_modem_slices
1566*6dbdd20aSAndroid Build Coastguard Worker            where track_name = '${slicesIt.track_name}'`,
1567*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1568*6dbdd20aSAndroid Build Coastguard Worker      );
1569*6dbdd20aSAndroid Build Coastguard Worker    }
1570*6dbdd20aSAndroid Build Coastguard Worker  }
1571*6dbdd20aSAndroid Build Coastguard Worker
1572*6dbdd20aSAndroid Build Coastguard Worker  async addKernelWakelocks(ctx: Trace, features: Set<string>): Promise<void> {
1573*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has('atom.kernel_wakelock')) {
1574*6dbdd20aSAndroid Build Coastguard Worker      return;
1575*6dbdd20aSAndroid Build Coastguard Worker    }
1576*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'Kernel Wakelock Summary';
1577*6dbdd20aSAndroid Build Coastguard Worker
1578*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1579*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.suspend;`);
1580*6dbdd20aSAndroid Build Coastguard Worker    await e.query(KERNEL_WAKELOCKS);
1581*6dbdd20aSAndroid Build Coastguard Worker    const result = await e.query(KERNEL_WAKELOCKS_SUMMARY);
1582*6dbdd20aSAndroid Build Coastguard Worker    const it = result.iter({wakelock_name: 'str'});
1583*6dbdd20aSAndroid Build Coastguard Worker    for (; it.valid(); it.next()) {
1584*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1585*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1586*6dbdd20aSAndroid Build Coastguard Worker        it.wakelock_name,
1587*6dbdd20aSAndroid Build Coastguard Worker        `select ts, dur, value from kernel_wakelocks where wakelock_name = "${it.wakelock_name}"`,
1588*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1589*6dbdd20aSAndroid Build Coastguard Worker        {yRangeSharingKey: 'kernel_wakelock', unit: '%'},
1590*6dbdd20aSAndroid Build Coastguard Worker      );
1591*6dbdd20aSAndroid Build Coastguard Worker    }
1592*6dbdd20aSAndroid Build Coastguard Worker  }
1593*6dbdd20aSAndroid Build Coastguard Worker
1594*6dbdd20aSAndroid Build Coastguard Worker  async addWakeups(ctx: Trace, features: Set<string>): Promise<void> {
1595*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has('track.suspend_backoff')) {
1596*6dbdd20aSAndroid Build Coastguard Worker      return;
1597*6dbdd20aSAndroid Build Coastguard Worker    }
1598*6dbdd20aSAndroid Build Coastguard Worker
1599*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1600*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'Wakeups';
1601*6dbdd20aSAndroid Build Coastguard Worker    await e.query(`INCLUDE PERFETTO MODULE android.suspend;`);
1602*6dbdd20aSAndroid Build Coastguard Worker    await e.query(WAKEUPS);
1603*6dbdd20aSAndroid Build Coastguard Worker    const result = await e.query(`select
1604*6dbdd20aSAndroid Build Coastguard Worker          item,
1605*6dbdd20aSAndroid Build Coastguard Worker          sum(dur) as sum_dur
1606*6dbdd20aSAndroid Build Coastguard Worker      from wakeups
1607*6dbdd20aSAndroid Build Coastguard Worker      group by 1
1608*6dbdd20aSAndroid Build Coastguard Worker      having sum_dur > 600e9`);
1609*6dbdd20aSAndroid Build Coastguard Worker    const it = result.iter({item: 'str'});
1610*6dbdd20aSAndroid Build Coastguard Worker    const sqlPrefix = `select
1611*6dbdd20aSAndroid Build Coastguard Worker                ts,
1612*6dbdd20aSAndroid Build Coastguard Worker                dur,
1613*6dbdd20aSAndroid Build Coastguard Worker                item || case backoff_reason
1614*6dbdd20aSAndroid Build Coastguard Worker                  when 'short' then ' (Short suspend backoff)'
1615*6dbdd20aSAndroid Build Coastguard Worker                  when 'failed' then ' (Failed suspend backoff)'
1616*6dbdd20aSAndroid Build Coastguard Worker                  else ''
1617*6dbdd20aSAndroid Build Coastguard Worker                end as name,
1618*6dbdd20aSAndroid Build Coastguard Worker                item,
1619*6dbdd20aSAndroid Build Coastguard Worker                type,
1620*6dbdd20aSAndroid Build Coastguard Worker                raw_wakeup,
1621*6dbdd20aSAndroid Build Coastguard Worker                attribution,
1622*6dbdd20aSAndroid Build Coastguard Worker                suspend_quality,
1623*6dbdd20aSAndroid Build Coastguard Worker                backoff_state,
1624*6dbdd20aSAndroid Build Coastguard Worker                backoff_reason,
1625*6dbdd20aSAndroid Build Coastguard Worker                backoff_count,
1626*6dbdd20aSAndroid Build Coastguard Worker                backoff_millis
1627*6dbdd20aSAndroid Build Coastguard Worker            from wakeups`;
1628*6dbdd20aSAndroid Build Coastguard Worker    const items = [];
1629*6dbdd20aSAndroid Build Coastguard Worker    let labelOther = false;
1630*6dbdd20aSAndroid Build Coastguard Worker    for (; it.valid(); it.next()) {
1631*6dbdd20aSAndroid Build Coastguard Worker      labelOther = true;
1632*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1633*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1634*6dbdd20aSAndroid Build Coastguard Worker        `Wakeup ${it.item}`,
1635*6dbdd20aSAndroid Build Coastguard Worker        `${sqlPrefix} where item="${it.item}"`,
1636*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1637*6dbdd20aSAndroid Build Coastguard Worker        WAKEUPS_COLUMNS,
1638*6dbdd20aSAndroid Build Coastguard Worker      );
1639*6dbdd20aSAndroid Build Coastguard Worker      items.push(it.item);
1640*6dbdd20aSAndroid Build Coastguard Worker    }
1641*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1642*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1643*6dbdd20aSAndroid Build Coastguard Worker      labelOther ? 'Other wakeups' : 'Wakeups',
1644*6dbdd20aSAndroid Build Coastguard Worker      `${sqlPrefix} where item not in ('${items.join("','")}')`,
1645*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1646*6dbdd20aSAndroid Build Coastguard Worker      WAKEUPS_COLUMNS,
1647*6dbdd20aSAndroid Build Coastguard Worker    );
1648*6dbdd20aSAndroid Build Coastguard Worker  }
1649*6dbdd20aSAndroid Build Coastguard Worker
1650*6dbdd20aSAndroid Build Coastguard Worker  async addHighCpu(ctx: Trace, features: Set<string>): Promise<void> {
1651*6dbdd20aSAndroid Build Coastguard Worker    if (!features.has('atom.cpu_cycles_per_uid_cluster')) {
1652*6dbdd20aSAndroid Build Coastguard Worker      return;
1653*6dbdd20aSAndroid Build Coastguard Worker    }
1654*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'CPU per UID (major users)';
1655*6dbdd20aSAndroid Build Coastguard Worker
1656*6dbdd20aSAndroid Build Coastguard Worker    const e = ctx.engine;
1657*6dbdd20aSAndroid Build Coastguard Worker
1658*6dbdd20aSAndroid Build Coastguard Worker    await e.query(HIGH_CPU);
1659*6dbdd20aSAndroid Build Coastguard Worker    const result = await e.query(
1660*6dbdd20aSAndroid Build Coastguard Worker      `select distinct pkg, cluster from high_cpu where value > 10 order by 1, 2`,
1661*6dbdd20aSAndroid Build Coastguard Worker    );
1662*6dbdd20aSAndroid Build Coastguard Worker    const it = result.iter({pkg: 'str', cluster: 'str'});
1663*6dbdd20aSAndroid Build Coastguard Worker    for (; it.valid(); it.next()) {
1664*6dbdd20aSAndroid Build Coastguard Worker      await this.addCounterTrack(
1665*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1666*6dbdd20aSAndroid Build Coastguard Worker        `CPU (${it.cluster}): ${it.pkg}`,
1667*6dbdd20aSAndroid Build Coastguard Worker        `select ts, value from high_cpu where pkg = "${it.pkg}" and cluster="${it.cluster}"`,
1668*6dbdd20aSAndroid Build Coastguard Worker        groupName,
1669*6dbdd20aSAndroid Build Coastguard Worker        {yOverrideMaximum: 100, unit: '%'},
1670*6dbdd20aSAndroid Build Coastguard Worker      );
1671*6dbdd20aSAndroid Build Coastguard Worker    }
1672*6dbdd20aSAndroid Build Coastguard Worker  }
1673*6dbdd20aSAndroid Build Coastguard Worker
1674*6dbdd20aSAndroid Build Coastguard Worker  async addBluetooth(ctx: Trace, features: Set<string>): Promise<void> {
1675*6dbdd20aSAndroid Build Coastguard Worker    if (
1676*6dbdd20aSAndroid Build Coastguard Worker      !Array.from(features.values()).some(
1677*6dbdd20aSAndroid Build Coastguard Worker        (f) => f.startsWith('atom.bluetooth_') || f.startsWith('atom.ble_'),
1678*6dbdd20aSAndroid Build Coastguard Worker      )
1679*6dbdd20aSAndroid Build Coastguard Worker    ) {
1680*6dbdd20aSAndroid Build Coastguard Worker      return;
1681*6dbdd20aSAndroid Build Coastguard Worker    }
1682*6dbdd20aSAndroid Build Coastguard Worker    const groupName = 'Bluetooth';
1683*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1684*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1685*6dbdd20aSAndroid Build Coastguard Worker      'BLE Scans (opportunistic)',
1686*6dbdd20aSAndroid Build Coastguard Worker      bleScanQuery('opportunistic'),
1687*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1688*6dbdd20aSAndroid Build Coastguard Worker    );
1689*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1690*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1691*6dbdd20aSAndroid Build Coastguard Worker      'BLE Scans (filtered)',
1692*6dbdd20aSAndroid Build Coastguard Worker      bleScanQuery('filtered'),
1693*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1694*6dbdd20aSAndroid Build Coastguard Worker    );
1695*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1696*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1697*6dbdd20aSAndroid Build Coastguard Worker      'BLE Scans (unfiltered)',
1698*6dbdd20aSAndroid Build Coastguard Worker      bleScanQuery('not filtered'),
1699*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1700*6dbdd20aSAndroid Build Coastguard Worker    );
1701*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'BLE Scan Results', BLE_RESULTS, groupName);
1702*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Connections (ACL)', BT_CONNS_ACL, groupName);
1703*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'Connections (SCO)', BT_CONNS_SCO, groupName);
1704*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1705*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1706*6dbdd20aSAndroid Build Coastguard Worker      'Link-level Events',
1707*6dbdd20aSAndroid Build Coastguard Worker      BT_LINK_LEVEL_EVENTS,
1708*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1709*6dbdd20aSAndroid Build Coastguard Worker      BT_LINK_LEVEL_EVENTS_COLUMNS,
1710*6dbdd20aSAndroid Build Coastguard Worker    );
1711*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(ctx, 'A2DP Audio', BT_A2DP_AUDIO, groupName);
1712*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1713*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1714*6dbdd20aSAndroid Build Coastguard Worker      'Bytes Transferred (L2CAP/RFCOMM)',
1715*6dbdd20aSAndroid Build Coastguard Worker      BT_BYTES,
1716*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1717*6dbdd20aSAndroid Build Coastguard Worker    );
1718*6dbdd20aSAndroid Build Coastguard Worker    await ctx.engine.query(BT_ACTIVITY);
1719*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1720*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1721*6dbdd20aSAndroid Build Coastguard Worker      'ACL Classic Active Count',
1722*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, acl_active_count as value from bt_activity',
1723*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1724*6dbdd20aSAndroid Build Coastguard Worker    );
1725*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1726*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1727*6dbdd20aSAndroid Build Coastguard Worker      'ACL Classic Sniff Count',
1728*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, acl_sniff_count as value from bt_activity',
1729*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1730*6dbdd20aSAndroid Build Coastguard Worker    );
1731*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1732*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1733*6dbdd20aSAndroid Build Coastguard Worker      'ACL BLE Count',
1734*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, acl_ble_count as value from bt_activity',
1735*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1736*6dbdd20aSAndroid Build Coastguard Worker    );
1737*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1738*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1739*6dbdd20aSAndroid Build Coastguard Worker      'Advertising Instance Count',
1740*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, advertising_count as value from bt_activity',
1741*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1742*6dbdd20aSAndroid Build Coastguard Worker    );
1743*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1744*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1745*6dbdd20aSAndroid Build Coastguard Worker      'LE Scan Duty Cycle Maximum',
1746*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, le_scan_duty_cycle as value from bt_activity',
1747*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1748*6dbdd20aSAndroid Build Coastguard Worker      {unit: '%'},
1749*6dbdd20aSAndroid Build Coastguard Worker    );
1750*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1751*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1752*6dbdd20aSAndroid Build Coastguard Worker      'Inquiry Active',
1753*6dbdd20aSAndroid Build Coastguard Worker      "select ts, dur, 'Active' as name from bt_activity where inquiry_active",
1754*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1755*6dbdd20aSAndroid Build Coastguard Worker    );
1756*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1757*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1758*6dbdd20aSAndroid Build Coastguard Worker      'SCO Active',
1759*6dbdd20aSAndroid Build Coastguard Worker      "select ts, dur, 'Active' as name from bt_activity where sco_active",
1760*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1761*6dbdd20aSAndroid Build Coastguard Worker    );
1762*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1763*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1764*6dbdd20aSAndroid Build Coastguard Worker      'A2DP Active',
1765*6dbdd20aSAndroid Build Coastguard Worker      "select ts, dur, 'Active' as name from bt_activity where a2dp_active",
1766*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1767*6dbdd20aSAndroid Build Coastguard Worker    );
1768*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1769*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1770*6dbdd20aSAndroid Build Coastguard Worker      'LE Audio Active',
1771*6dbdd20aSAndroid Build Coastguard Worker      "select ts, dur, 'Active' as name from bt_activity where le_audio_active",
1772*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1773*6dbdd20aSAndroid Build Coastguard Worker    );
1774*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1775*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1776*6dbdd20aSAndroid Build Coastguard Worker      'Controller Idle Time',
1777*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, controller_idle_pct as value from bt_activity',
1778*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1779*6dbdd20aSAndroid Build Coastguard Worker      {yRangeSharingKey: 'bt_controller_time', unit: '%'},
1780*6dbdd20aSAndroid Build Coastguard Worker    );
1781*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1782*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1783*6dbdd20aSAndroid Build Coastguard Worker      'Controller TX Time',
1784*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, controller_tx_pct as value from bt_activity',
1785*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1786*6dbdd20aSAndroid Build Coastguard Worker      {yRangeSharingKey: 'bt_controller_time', unit: '%'},
1787*6dbdd20aSAndroid Build Coastguard Worker    );
1788*6dbdd20aSAndroid Build Coastguard Worker    await this.addCounterTrack(
1789*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1790*6dbdd20aSAndroid Build Coastguard Worker      'Controller RX Time',
1791*6dbdd20aSAndroid Build Coastguard Worker      'select ts, dur, controller_rx_pct as value from bt_activity',
1792*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1793*6dbdd20aSAndroid Build Coastguard Worker      {yRangeSharingKey: 'bt_controller_time', unit: '%'},
1794*6dbdd20aSAndroid Build Coastguard Worker    );
1795*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1796*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1797*6dbdd20aSAndroid Build Coastguard Worker      'Quality reports',
1798*6dbdd20aSAndroid Build Coastguard Worker      BT_QUALITY_REPORTS,
1799*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1800*6dbdd20aSAndroid Build Coastguard Worker      BT_QUALITY_REPORTS_COLUMNS,
1801*6dbdd20aSAndroid Build Coastguard Worker    );
1802*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1803*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1804*6dbdd20aSAndroid Build Coastguard Worker      'RSSI Reports',
1805*6dbdd20aSAndroid Build Coastguard Worker      BT_RSSI_REPORTS,
1806*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1807*6dbdd20aSAndroid Build Coastguard Worker      BT_RSSI_REPORTS_COLUMNS,
1808*6dbdd20aSAndroid Build Coastguard Worker    );
1809*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1810*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1811*6dbdd20aSAndroid Build Coastguard Worker      'HAL Crashes',
1812*6dbdd20aSAndroid Build Coastguard Worker      BT_HAL_CRASHES,
1813*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1814*6dbdd20aSAndroid Build Coastguard Worker      BT_HAL_CRASHES_COLUMNS,
1815*6dbdd20aSAndroid Build Coastguard Worker    );
1816*6dbdd20aSAndroid Build Coastguard Worker    await this.addSliceTrack(
1817*6dbdd20aSAndroid Build Coastguard Worker      ctx,
1818*6dbdd20aSAndroid Build Coastguard Worker      'Code Path Counter',
1819*6dbdd20aSAndroid Build Coastguard Worker      BT_CODE_PATH_COUNTER,
1820*6dbdd20aSAndroid Build Coastguard Worker      groupName,
1821*6dbdd20aSAndroid Build Coastguard Worker      BT_CODE_PATH_COUNTER_COLUMNS,
1822*6dbdd20aSAndroid Build Coastguard Worker    );
1823*6dbdd20aSAndroid Build Coastguard Worker  }
1824*6dbdd20aSAndroid Build Coastguard Worker
1825*6dbdd20aSAndroid Build Coastguard Worker  async addContainedTraces(
1826*6dbdd20aSAndroid Build Coastguard Worker    ctx: Trace,
1827*6dbdd20aSAndroid Build Coastguard Worker    containedTraces: ContainedTrace[],
1828*6dbdd20aSAndroid Build Coastguard Worker  ): Promise<void> {
1829*6dbdd20aSAndroid Build Coastguard Worker    const bySubscription = new Map<string, ContainedTrace[]>();
1830*6dbdd20aSAndroid Build Coastguard Worker    for (const trace of containedTraces) {
1831*6dbdd20aSAndroid Build Coastguard Worker      if (!bySubscription.has(trace.subscription)) {
1832*6dbdd20aSAndroid Build Coastguard Worker        bySubscription.set(trace.subscription, []);
1833*6dbdd20aSAndroid Build Coastguard Worker      }
1834*6dbdd20aSAndroid Build Coastguard Worker      bySubscription.get(trace.subscription)!.push(trace);
1835*6dbdd20aSAndroid Build Coastguard Worker    }
1836*6dbdd20aSAndroid Build Coastguard Worker
1837*6dbdd20aSAndroid Build Coastguard Worker    for (const [subscription, traces] of bySubscription) {
1838*6dbdd20aSAndroid Build Coastguard Worker      await this.addSliceTrack(
1839*6dbdd20aSAndroid Build Coastguard Worker        ctx,
1840*6dbdd20aSAndroid Build Coastguard Worker        subscription,
1841*6dbdd20aSAndroid Build Coastguard Worker        traces
1842*6dbdd20aSAndroid Build Coastguard Worker          .map(
1843*6dbdd20aSAndroid Build Coastguard Worker            (t) => `SELECT
1844*6dbdd20aSAndroid Build Coastguard Worker          CAST(${t.ts} * 1e6 AS int) AS ts,
1845*6dbdd20aSAndroid Build Coastguard Worker          CAST(${t.dur} * 1e6 AS int) AS dur,
1846*6dbdd20aSAndroid Build Coastguard Worker          '${t.trigger === '' ? 'Trace' : t.trigger}' AS name,
1847*6dbdd20aSAndroid Build Coastguard Worker          'http://go/trace-uuid/${t.uuid}' AS link
1848*6dbdd20aSAndroid Build Coastguard Worker        `,
1849*6dbdd20aSAndroid Build Coastguard Worker          )
1850*6dbdd20aSAndroid Build Coastguard Worker          .join(' UNION ALL '),
1851*6dbdd20aSAndroid Build Coastguard Worker        'Other traces',
1852*6dbdd20aSAndroid Build Coastguard Worker        ['link'],
1853*6dbdd20aSAndroid Build Coastguard Worker      );
1854*6dbdd20aSAndroid Build Coastguard Worker    }
1855*6dbdd20aSAndroid Build Coastguard Worker  }
1856*6dbdd20aSAndroid Build Coastguard Worker
1857*6dbdd20aSAndroid Build Coastguard Worker  async findFeatures(e: Engine): Promise<Set<string>> {
1858*6dbdd20aSAndroid Build Coastguard Worker    const features = new Set<string>();
1859*6dbdd20aSAndroid Build Coastguard Worker
1860*6dbdd20aSAndroid Build Coastguard Worker    const addFeatures = async (q: string) => {
1861*6dbdd20aSAndroid Build Coastguard Worker      const result = await e.query(q);
1862*6dbdd20aSAndroid Build Coastguard Worker      const it = result.iter({feature: 'str'});
1863*6dbdd20aSAndroid Build Coastguard Worker      for (; it.valid(); it.next()) {
1864*6dbdd20aSAndroid Build Coastguard Worker        features.add(it.feature);
1865*6dbdd20aSAndroid Build Coastguard Worker      }
1866*6dbdd20aSAndroid Build Coastguard Worker    };
1867*6dbdd20aSAndroid Build Coastguard Worker
1868*6dbdd20aSAndroid Build Coastguard Worker    await addFeatures(`
1869*6dbdd20aSAndroid Build Coastguard Worker      select distinct 'atom.' || s.name as feature
1870*6dbdd20aSAndroid Build Coastguard Worker      from track t join slice s on t.id = s.track_id
1871*6dbdd20aSAndroid Build Coastguard Worker      where t.name = 'Statsd Atoms'`);
1872*6dbdd20aSAndroid Build Coastguard Worker
1873*6dbdd20aSAndroid Build Coastguard Worker    await addFeatures(`
1874*6dbdd20aSAndroid Build Coastguard Worker      select distinct
1875*6dbdd20aSAndroid Build Coastguard Worker        case when name like '%wlan%' then 'net.wifi'
1876*6dbdd20aSAndroid Build Coastguard Worker            when name like '%rmnet%' then 'net.modem'
1877*6dbdd20aSAndroid Build Coastguard Worker            else 'net.other'
1878*6dbdd20aSAndroid Build Coastguard Worker        end as feature
1879*6dbdd20aSAndroid Build Coastguard Worker      from track
1880*6dbdd20aSAndroid Build Coastguard Worker      where name like '%Transmitted' or name like '%Received'`);
1881*6dbdd20aSAndroid Build Coastguard Worker
1882*6dbdd20aSAndroid Build Coastguard Worker    await addFeatures(`
1883*6dbdd20aSAndroid Build Coastguard Worker      select distinct 'track.' || lower(name) as feature
1884*6dbdd20aSAndroid Build Coastguard Worker      from track where name in ('RIL', 'suspend_backoff') or name like 'battery_stats.%'`);
1885*6dbdd20aSAndroid Build Coastguard Worker
1886*6dbdd20aSAndroid Build Coastguard Worker    await addFeatures(`
1887*6dbdd20aSAndroid Build Coastguard Worker      select distinct 'track.battery_stats.*' as feature
1888*6dbdd20aSAndroid Build Coastguard Worker      from track where name like 'battery_stats.%'`);
1889*6dbdd20aSAndroid Build Coastguard Worker
1890*6dbdd20aSAndroid Build Coastguard Worker    return features;
1891*6dbdd20aSAndroid Build Coastguard Worker  }
1892*6dbdd20aSAndroid Build Coastguard Worker
1893*6dbdd20aSAndroid Build Coastguard Worker  async addTracks(ctx: Trace): Promise<void> {
1894*6dbdd20aSAndroid Build Coastguard Worker    const features: Set<string> = await this.findFeatures(ctx.engine);
1895*6dbdd20aSAndroid Build Coastguard Worker
1896*6dbdd20aSAndroid Build Coastguard Worker    const containedTraces = (ctx.openerPluginArgs?.containedTraces ??
1897*6dbdd20aSAndroid Build Coastguard Worker      []) as ContainedTrace[];
1898*6dbdd20aSAndroid Build Coastguard Worker
1899*6dbdd20aSAndroid Build Coastguard Worker    await ctx.engine.query(PACKAGE_LOOKUP);
1900*6dbdd20aSAndroid Build Coastguard Worker    await this.addNetworkSummary(ctx, features);
1901*6dbdd20aSAndroid Build Coastguard Worker    await this.addBluetooth(ctx, features);
1902*6dbdd20aSAndroid Build Coastguard Worker    await this.addAtomCounters(ctx);
1903*6dbdd20aSAndroid Build Coastguard Worker    await this.addAtomSlices(ctx);
1904*6dbdd20aSAndroid Build Coastguard Worker    await this.addModemDetail(ctx, features);
1905*6dbdd20aSAndroid Build Coastguard Worker    await this.addKernelWakelocks(ctx, features);
1906*6dbdd20aSAndroid Build Coastguard Worker    await this.addWakeups(ctx, features);
1907*6dbdd20aSAndroid Build Coastguard Worker    await this.addDeviceState(ctx, features);
1908*6dbdd20aSAndroid Build Coastguard Worker    await this.addHighCpu(ctx, features);
1909*6dbdd20aSAndroid Build Coastguard Worker    await this.addContainedTraces(ctx, containedTraces);
1910*6dbdd20aSAndroid Build Coastguard Worker  }
1911*6dbdd20aSAndroid Build Coastguard Worker
1912*6dbdd20aSAndroid Build Coastguard Worker  async onTraceLoad(ctx: Trace): Promise<void> {
1913*6dbdd20aSAndroid Build Coastguard Worker    await this.addTracks(ctx);
1914*6dbdd20aSAndroid Build Coastguard Worker  }
1915*6dbdd20aSAndroid Build Coastguard Worker}
1916