• 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 GLOB '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 GLOB 'WakeLock *' AND dur != -1
82    )
83)
84GROUP BY group_id;
85
86DROP TABLE IF EXISTS suspend_slice_;
87CREATE TABLE suspend_slice_ AS
88-- Traces from after b/70292203 was fixed have the action string so just look
89-- for it.
90SELECT
91    ts,
92    dur,
93    true as trustworthy
94FROM (
95    SELECT
96        ts,
97        LEAD(ts) OVER (ORDER BY ts, start DESC) - ts AS dur,
98        start
99    FROM (
100        SELECT
101               ts,
102               EXTRACT_ARG(arg_set_id, 'action') AS action,
103               EXTRACT_ARG(arg_set_id, 'start') AS start
104        FROM raw
105        WHERE name = 'suspend_resume'
106    )
107    -- Different device kernels log different actions when suspending.
108    -- Fortunately each action only appears in the kernel in which it's
109    -- relevant so we can simply look for any of them.
110    WHERE action IN ('timekeeping_freeze', 'syscore_resume')
111)
112WHERE start = 1
113UNION ALL
114-- Traces from before b/70292203 was fixed (approx Nov 2020) do not have the
115-- action string so we do some convoluted pattern matching that mostly works.
116-- TODO(simonmacm) remove this when we no longer need suspend-resume from R
117-- phones.
118SELECT
119    ts,
120    dur,
121    false as trustworthy
122FROM (
123    SELECT
124       ts,
125       ts - lag(ts) OVER w AS lag_dur,
126       lead(ts) OVER w - ts AS dur,
127       action,
128       start,
129       event,
130       lag(start) OVER w AS lag_start,
131       lag(event) OVER w AS lag_event,
132       lag(start, 2) OVER w AS lag_2_start,
133       lag(event, 2) OVER w AS lag_2_event,
134       lead(start) OVER w AS lead_start,
135       lead(event) OVER w AS lead_event,
136       lead(start, 2) OVER w AS lead_2_start,
137       lead(event, 2) OVER w AS lead_2_event
138    FROM (
139        SELECT
140               ts,
141               EXTRACT_ARG(arg_set_id, 'action') AS action,
142               EXTRACT_ARG(arg_set_id, 'start') AS start,
143               EXTRACT_ARG(arg_set_id, 'val') AS event
144        FROM raw
145        WHERE name = 'suspend_resume'
146    )
147    WINDOW w AS (ORDER BY ts)
148)
149WHERE action IS NULL AND (
150-- We want to find the start and end events with action='timekeeping_freeze'.
151-- In practice, these events often show up in a sequence like the following:
152-- start = 1, event = 1     [string would have been 'machine_suspend']
153-- start = 1, event = (any) [string would have been 'timekeeping_freeze'] *
154--
155--                             (sleep happens here)
156--
157-- start = 0, event = (any) [string would have been 'timekeeping_freeze']
158-- start = 0, event = 1     [string would have been 'machine_suspend']
159--
160-- So we look for this pattern of start and event, anchored on the event marked
161-- with "*".
162    (
163        lag_start = 1 AND lag_event = 1
164        AND start = 1
165        AND lead_start = 0
166        AND lead_2_start = 0 AND lead_2_event = 1
167    )
168-- Or in newer kernels we seem to have a very different pattern. We can take
169-- advantage of that fact that we get several events with identical timestamp
170-- just before sleeping (normally this never happens):
171-- gap = 0, start = 1, event = 3
172-- gap = 0, start = 0, event = 3
173-- gap = 0, start = 1, event = 0
174--
175--  (sleep happens here)
176--
177-- gap = (any), start = 0, event = 0
178    OR (
179        lag_dur = 0
180        AND lead_start = 0 AND lead_event = 0
181        AND start = 1 AND event = 0
182        AND lag_start = 0 AND lag_event = 3
183        AND lag_2_start = 1 AND lag_2_event = 3
184    )
185);
186
187SELECT RUN_METRIC('android/global_counter_span_view.sql',
188  'table_name', 'screen_state',
189  'counter_name', 'ScreenState');
190
191DROP TABLE IF EXISTS screen_state_span_with_suspend;
192CREATE VIRTUAL TABLE screen_state_span_with_suspend
193    USING span_join(screen_state_span, suspend_slice_);
194
195DROP VIEW IF EXISTS android_batt_event;
196CREATE VIEW android_batt_event AS
197SELECT
198       ts,
199       dur,
200       'Suspended' AS slice_name,
201       'Suspend / resume' AS track_name,
202       'slice' AS track_type
203FROM suspend_slice_;
204
205DROP VIEW IF EXISTS android_batt_output;
206CREATE VIEW android_batt_output AS
207SELECT AndroidBatteryMetric(
208  'battery_counters', (
209    SELECT RepeatedField(
210      AndroidBatteryMetric_BatteryCounters(
211        'timestamp_ns', ts,
212        'charge_counter_uah', charge_uah,
213        'capacity_percent', capacity_percent,
214        'current_ua', current_ua,
215        'current_avg_ua', current_avg_ua
216      )
217    )
218    FROM battery_view
219  ),
220  'battery_aggregates', (
221    SELECT NULL_IF_EMPTY(AndroidBatteryMetric_BatteryAggregates(
222      'total_screen_off_ns',
223      SUM(CASE WHEN state = 1.0 AND tbl = 'total' THEN dur ELSE 0 END),
224      'total_screen_on_ns',
225      SUM(CASE WHEN state = 2.0 AND tbl = 'total' THEN dur ELSE 0 END),
226      'total_screen_doze_ns',
227      SUM(CASE WHEN state = 3.0 AND tbl = 'total' THEN dur ELSE 0 END),
228      'sleep_ns',
229      (SELECT SUM(dur) FROM suspend_slice_),
230      'sleep_screen_off_ns',
231      SUM(CASE WHEN state = 1.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
232      'sleep_screen_on_ns',
233      SUM(CASE WHEN state = 2.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
234      'sleep_screen_doze_ns',
235      SUM(CASE WHEN state = 3.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
236      'total_wakelock_ns',
237      (SELECT SUM(ts_end - ts) FROM android_batt_wakelocks_merged)
238    ))
239    FROM (
240         SELECT dur, screen_state_val AS state, 'total' AS tbl
241         FROM screen_state_span
242         UNION ALL
243         SELECT dur, screen_state_val AS state, 'sleep' AS tbl
244         FROM screen_state_span_with_suspend
245    )
246  ),
247  'suspend_period', (
248    SELECT RepeatedField(
249      AndroidBatteryMetric_SuspendPeriod(
250        'timestamp_ns', ts,
251        'duration_ns', dur
252      )
253    )
254    FROM suspend_slice_
255    WHERE trustworthy
256  )
257);
258