• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2019 The Android Open Source Project
3--
4-- Licensed under the Apache License, Version 2.0 (the "License");
5-- you may not use this file except in compliance with the License.
6-- You may obtain a copy of the License at
7--
8--     https://www.apache.org/licenses/LICENSE-2.0
9--
10-- Unless required by applicable law or agreed to in writing, software
11-- distributed under the License is distributed on an "AS IS" BASIS,
12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-- See the License for the specific language governing permissions and
14-- limitations under the License.
15--
16DROP VIEW IF EXISTS battery_view;
17CREATE VIEW battery_view AS
18SELECT
19  all_ts.ts as ts,
20  current_avg_ua,
21  capacity_percent,
22  charge_uah,
23  current_ua
24FROM (
25  SELECT distinct(ts) AS ts
26  FROM counter c
27  JOIN counter_track t on c.track_id = t.id
28  WHERE name LIKE 'batt.%'
29) AS all_ts
30LEFT JOIN (
31  SELECT ts, value AS current_avg_ua
32  FROM counter c
33  JOIN counter_track t on c.track_id = t.id
34  WHERE name='batt.current.avg_ua'
35) USING(ts)
36LEFT JOIN (
37  SELECT ts, value AS capacity_percent
38  FROM counter c
39  JOIN counter_track t on c.track_id = t.id
40  WHERE name='batt.capacity_pct'
41) USING(ts)
42LEFT JOIN (
43  SELECT ts, value AS charge_uah
44  FROM counter c
45  JOIN counter_track t on c.track_id = t.id
46  WHERE name='batt.charge_uah'
47) USING(ts)
48LEFT JOIN (
49  SELECT ts, value AS current_ua
50  FROM counter c
51  JOIN counter_track t on c.track_id = t.id
52  WHERE name='batt.current_ua'
53) USING(ts)
54ORDER BY ts;
55
56DROP TABLE IF EXISTS android_batt_wakelocks_merged;
57CREATE TABLE android_batt_wakelocks_merged AS
58SELECT
59  MIN(ts) AS ts,
60  MAX(ts_end) AS ts_end
61FROM (
62    SELECT
63        *,
64        SUM(new_group) OVER (ORDER BY ts) AS group_id
65    FROM (
66        SELECT
67            ts,
68            ts + dur AS ts_end,
69            -- There is a new group if there was a gap before this wakelock.
70            -- i.e. the max end timestamp of all preceding wakelocks is before
71            -- the start timestamp of this one.
72            -- The null check is for the first row which is always a new group.
73            IFNULL(
74                MAX(ts + dur) OVER (
75                    ORDER BY ts
76                    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
77                ) < ts,
78                true
79            ) AS new_group
80        FROM slice
81        WHERE slice.name LIKE 'WakeLock %' AND dur != -1
82    )
83)
84GROUP BY group_id;
85
86-- Different device kernels log different actions when suspending. This table
87-- tells us the action that straddles the actual suspend period.
88DROP TABLE IF EXISTS device_action_mapping;
89CREATE TABLE device_action_mapping (device TEXT, action TEXT);
90INSERT INTO device_action_mapping VALUES
91('blueline', 'timekeeping_freeze'),
92('crosshatch', 'timekeeping_freeze'),
93('bonito', 'timekeeping_freeze'),
94('sargo', 'timekeeping_freeze'),
95('coral', 'timekeeping_freeze'),
96('flame', 'timekeeping_freeze'),
97('sunfish', 'timekeeping_freeze'),
98('redfin', 'syscore_resume'),
99('bramble', 'syscore_resume');
100
101DROP TABLE IF EXISTS device_action;
102CREATE TABLE device_action AS
103SELECT action
104FROM device_action_mapping dam
105WHERE EXISTS (
106  SELECT 1 FROM metadata
107  WHERE name = 'android_build_fingerprint' AND str_value LIKE '%' || dam.device || '%');
108
109DROP TABLE IF EXISTS suspend_slice_;
110CREATE TABLE suspend_slice_ AS
111-- Traces from after b/70292203 was fixed have the action string so just look
112-- for it.
113SELECT
114    ts,
115    dur,
116    true as trustworthy
117FROM (
118    SELECT
119        ts,
120        LEAD(ts) OVER (ORDER BY ts, start DESC) - ts AS dur,
121        start
122    FROM (
123        SELECT
124               ts,
125               EXTRACT_ARG(arg_set_id, 'action') AS action,
126               EXTRACT_ARG(arg_set_id, 'start') AS start
127        FROM raw
128        WHERE name = 'suspend_resume'
129    ) JOIN device_action USING(action)
130)
131WHERE start = 1
132UNION ALL
133-- Traces from before b/70292203 was fixed (approx Nov 2020) do not have the
134-- action string so we do some convoluted pattern matching that mostly works.
135-- TODO(simonmacm) remove this when enough time has passed (mid 2021?)
136SELECT
137    ts,
138    dur,
139    false as trustworthy
140FROM (
141    SELECT
142       ts,
143       ts - lag(ts) OVER w AS lag_dur,
144       lead(ts) OVER w - ts AS dur,
145       action,
146       start,
147       event,
148       lag(start) OVER w AS lag_start,
149       lag(event) OVER w AS lag_event,
150       lag(start, 2) OVER w AS lag_2_start,
151       lag(event, 2) OVER w AS lag_2_event,
152       lead(start) OVER w AS lead_start,
153       lead(event) OVER w AS lead_event,
154       lead(start, 2) OVER w AS lead_2_start,
155       lead(event, 2) OVER w AS lead_2_event
156    FROM (
157        SELECT
158               ts,
159               EXTRACT_ARG(arg_set_id, 'action') AS action,
160               EXTRACT_ARG(arg_set_id, 'start') AS start,
161               EXTRACT_ARG(arg_set_id, 'val') AS event
162        FROM raw
163        WHERE name = 'suspend_resume'
164    )
165    WINDOW w AS (ORDER BY ts)
166)
167WHERE action IS NULL AND (
168-- We want to find the start and end events with action='timekeeping_freeze'.
169-- In practice, these events often show up in a sequence like the following:
170-- start = 1, event = 1     [string would have been 'machine_suspend']
171-- start = 1, event = (any) [string would have been 'timekeeping_freeze'] *
172--
173--                             (sleep happens here)
174--
175-- start = 0, event = (any) [string would have been 'timekeeping_freeze']
176-- start = 0, event = 1     [string would have been 'machine_suspend']
177--
178-- So we look for this pattern of start and event, anchored on the event marked
179-- with "*".
180    (
181        lag_start = 1 AND lag_event = 1
182        AND start = 1
183        AND lead_start = 0
184        AND lead_2_start = 0 AND lead_2_event = 1
185    )
186-- Or in newer kernels we seem to have a very different pattern. We can take
187-- advantage of that fact that we get several events with identical timestamp
188-- just before sleeping (normally this never happens):
189-- gap = 0, start = 1, event = 3
190-- gap = 0, start = 0, event = 3
191-- gap = 0, start = 1, event = 0
192--
193--  (sleep happens here)
194--
195-- gap = (any), start = 0, event = 0
196    OR (
197        lag_dur = 0
198        AND lead_start = 0 AND lead_event = 0
199        AND start = 1 AND event = 0
200        AND lag_start = 0 AND lag_event = 3
201        AND lag_2_start = 1 AND lag_2_event = 3
202    )
203);
204
205DROP TABLE device_action_mapping;
206DROP TABLE device_action;
207
208SELECT RUN_METRIC('android/global_counter_span_view.sql',
209  'table_name', 'screen_state',
210  'counter_name', 'ScreenState');
211
212DROP TABLE IF EXISTS screen_state_span_with_suspend;
213CREATE VIRTUAL TABLE screen_state_span_with_suspend
214    USING span_join(screen_state_span, suspend_slice_);
215
216DROP VIEW IF EXISTS android_batt_event;
217CREATE VIEW android_batt_event AS
218SELECT
219       ts,
220       dur,
221       'Suspended' AS slice_name,
222       'Suspend / resume' AS track_name,
223       'slice' AS track_type
224FROM suspend_slice_;
225
226DROP VIEW IF EXISTS android_batt_output;
227CREATE VIEW android_batt_output AS
228SELECT AndroidBatteryMetric(
229  'battery_counters', (
230    SELECT RepeatedField(
231      AndroidBatteryMetric_BatteryCounters(
232        'timestamp_ns', ts,
233        'charge_counter_uah', charge_uah,
234        'capacity_percent', capacity_percent,
235        'current_ua', current_ua,
236        'current_avg_ua', current_avg_ua
237      )
238    )
239    FROM battery_view
240  ),
241  'battery_aggregates', (
242    SELECT NULL_IF_EMPTY(AndroidBatteryMetric_BatteryAggregates(
243      'total_screen_off_ns',
244      SUM(CASE WHEN state = 1.0 AND tbl = 'total' THEN dur ELSE 0 END),
245      'total_screen_on_ns',
246      SUM(CASE WHEN state = 2.0 AND tbl = 'total' THEN dur ELSE 0 END),
247      'total_screen_doze_ns',
248      SUM(CASE WHEN state = 3.0 AND tbl = 'total' THEN dur ELSE 0 END),
249      'sleep_ns',
250      (SELECT SUM(dur) FROM suspend_slice_),
251      'sleep_screen_off_ns',
252      SUM(CASE WHEN state = 1.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
253      'sleep_screen_on_ns',
254      SUM(CASE WHEN state = 2.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
255      'sleep_screen_doze_ns',
256      SUM(CASE WHEN state = 3.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
257      'total_wakelock_ns',
258      (SELECT SUM(ts_end - ts) FROM android_batt_wakelocks_merged)
259    ))
260    FROM (
261         SELECT dur, screen_state_val AS state, 'total' AS tbl
262         FROM screen_state_span
263         UNION ALL
264         SELECT dur, screen_state_val AS state, 'sleep' AS tbl
265         FROM screen_state_span_with_suspend
266    )
267  ),
268  'suspend_period', (
269    SELECT RepeatedField(
270      AndroidBatteryMetric_SuspendPeriod(
271        'timestamp_ns', ts,
272        'duration_ns', dur
273      )
274    )
275    FROM suspend_slice_
276    WHERE trustworthy
277  )
278);
279