• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2023 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
16-- Converts a battery_stats counter value to human readable string.
17CREATE PERFETTO FUNCTION android_battery_stats_counter_to_string(
18    -- The counter track name (e.g. 'battery_stats.audio').
19    track STRING,
20    -- The counter value.
21    value DOUBLE
22)
23-- The human-readable name for the counter value.
24RETURNS STRING AS
25SELECT
26  CASE
27    WHEN (
28      $track = "battery_stats.wifi_scan"
29      OR $track = "battery_stats.wifi_radio"
30      OR $track = "battery_stats.mobile_radio"
31      OR $track = "battery_stats.audio"
32      OR $track = "battery_stats.video"
33      OR $track = "battery_stats.camera"
34      OR $track = "battery_stats.power_save"
35      OR $track = "battery_stats.phone_in_call"
36    )
37    THEN CASE $value WHEN 0 THEN "inactive" WHEN 1 THEN "active" ELSE "unknown" END
38    WHEN $track = "battery_stats.wifi"
39    THEN CASE $value WHEN 0 THEN "off" WHEN 1 THEN "on" ELSE "unknown" END
40    WHEN $track = "battery_stats.phone_state"
41    THEN CASE $value
42      WHEN 0
43      THEN "in"
44      WHEN 1
45      THEN "out"
46      WHEN 2
47      THEN "emergency"
48      WHEN 3
49      THEN "off"
50      ELSE "unknown"
51    END
52    WHEN (
53      $track = "battery_stats.phone_signal_strength"
54      OR $track = "battery_stats.wifi_signal_strength"
55    )
56    THEN CASE $value
57      WHEN 0
58      THEN "0/4"
59      WHEN 1
60      THEN "1/4"
61      WHEN 2
62      THEN "2/4"
63      WHEN 3
64      THEN "3/4"
65      WHEN 4
66      THEN "4/4"
67      ELSE "unknown"
68    END
69    WHEN $track = "battery_stats.wifi_suppl"
70    THEN CASE $value
71      WHEN 0
72      THEN "invalid"
73      WHEN 1
74      THEN "disconnected"
75      WHEN 2
76      THEN "disabled"
77      WHEN 3
78      THEN "inactive"
79      WHEN 4
80      THEN "scanning"
81      WHEN 5
82      THEN "authenticating"
83      WHEN 6
84      THEN "associating"
85      WHEN 7
86      THEN "associated"
87      WHEN 8
88      THEN "4-way-handshake"
89      WHEN 9
90      THEN "group-handshake"
91      WHEN 10
92      THEN "completed"
93      WHEN 11
94      THEN "dormant"
95      WHEN 12
96      THEN "uninitialized"
97      ELSE "unknown"
98    END
99    WHEN $track = "battery_stats.data_conn"
100    THEN CASE $value
101      WHEN 0
102      THEN "Out of service"
103      WHEN 1
104      THEN "2.5G (GPRS)"
105      WHEN 2
106      THEN "2.7G (EDGE)"
107      WHEN 3
108      THEN "3G (UMTS)"
109      WHEN 4
110      THEN "3G (CDMA)"
111      WHEN 5
112      THEN "3G (EVDO Rel 0)"
113      WHEN 6
114      THEN "3G (EVDO Rev A)"
115      WHEN 7
116      THEN "3G (LXRTT)"
117      WHEN 8
118      THEN "3.5G (HSDPA)"
119      WHEN 9
120      THEN "3.5G (HSUPA)"
121      WHEN 10
122      THEN "3.5G (HSPA)"
123      WHEN 11
124      THEN "2G (IDEN)"
125      WHEN 12
126      THEN "3G (EVDO Rev B)"
127      WHEN 13
128      THEN "4G (LTE)"
129      WHEN 14
130      THEN "3.5G (eHRPD)"
131      WHEN 15
132      THEN "3.7G (HSPA+)"
133      WHEN 16
134      THEN "2G (GSM)"
135      WHEN 17
136      THEN "3G (TD SCDMA)"
137      WHEN 18
138      THEN "Wifi calling (IWLAN)"
139      WHEN 19
140      THEN "4.5G (LTE CA)"
141      WHEN 20
142      THEN "5G (NR)"
143      WHEN 21
144      THEN "Emergency calls only"
145      WHEN 22
146      THEN "Other"
147      ELSE "unknown"
148    END
149    ELSE cast_string!($value)
150  END;
151
152-- View of human readable battery stats counter-based states. These are recorded
153-- by BatteryStats as a bitmap where each 'category' has a unique value at any
154-- given time.
155CREATE PERFETTO VIEW android_battery_stats_state (
156  -- Start of the new barrary state.
157  ts TIMESTAMP,
158  -- The duration the state was active, -1 for incomplete slices.
159  dur DURATION,
160  -- The same as `dur`, but extends to trace end for incomplete slices.
161  safe_dur DURATION,
162  -- The name of the counter track.
163  track_name STRING,
164  -- The counter value as a number.
165  value LONG,
166  -- The counter value as a human-readable string.
167  value_name STRING
168) AS
169SELECT
170  ts,
171  coalesce(lead(ts) OVER (PARTITION BY name ORDER BY ts) - ts, -1) AS dur,
172  lead(ts, 1, trace_end()) OVER (PARTITION BY name ORDER BY ts) - ts AS safe_dur,
173  name AS track_name,
174  cast_int!(value) AS value,
175  android_battery_stats_counter_to_string(name, value) AS value_name
176FROM counter
177JOIN counter_track
178  ON counter.track_id = counter_track.id
179WHERE
180  counter_track.name GLOB 'battery_stats.*';
181
182-- View of slices derived from battery_stats events. Battery stats records all
183-- events as instants, however some may indicate whether something started or
184-- stopped with a '+' or '-' prefix. Events such as jobs, top apps, foreground
185-- apps or long wakes include these details and allow drawing slices between
186-- instant events found in a trace.
187--
188-- For example, we may see an event like the following on 'battery_stats.top':
189--
190--     -top=10215:"com.google.android.apps.nexuslauncher"
191--
192-- This view will find the associated start ('+top') with the matching suffix
193-- (everything after the '=') to construct a slice. It computes the timestamp
194-- and duration from the events and extract the details as follows:
195--
196--     track_name='battery_stats.top'
197--     str_value='com.google.android.apps.nexuslauncher'
198--     int_value=10215
199CREATE PERFETTO VIEW android_battery_stats_event_slices (
200  -- Start of a new battery state.
201  ts TIMESTAMP,
202  -- The duration the state was active, -1 for incomplete slices.
203  dur DURATION,
204  -- The same as `dur`, but extends to trace end for incomplete slices.
205  safe_dur DURATION,
206  -- The name of the counter track.
207  track_name STRING,
208  -- String value.
209  str_value STRING,
210  -- Int value.
211  int_value LONG
212) AS
213WITH
214  event_markers AS (
215    SELECT
216      ts,
217      track.name AS track_name,
218      str_split(slice.name, '=', 1) AS key,
219      substr(slice.name, 1, 1) = '+' AS start
220    FROM slice
221    JOIN track
222      ON slice.track_id = track.id
223    WHERE
224      track_name GLOB 'battery_stats.*' AND substr(slice.name, 1, 1) IN ('+', '-')
225  ),
226  with_neighbors AS (
227    SELECT
228      *,
229      lag(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS last_ts,
230      lead(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS next_ts
231    FROM event_markers
232  ),
233  -- Note: query performance depends on the ability to push down filters on
234  -- the track_name. It would be more clear below to have two queries and union
235  -- them, but doing so prevents push down through the above window functions.
236  event_spans AS (
237    SELECT
238      track_name,
239      key,
240      iif(start, ts, trace_start()) AS ts,
241      iif(start, next_ts, ts) AS end_ts
242    FROM with_neighbors
243    -- For the majority of events, we take the `start` event and compute the dur
244    -- based on next_ts. In the off chance we get an end event with no prior
245    -- start (matched by the second half of this where), we can create an event
246    -- starting from the beginning of the trace ending at the current event.
247    WHERE
248      (
249        start OR last_ts IS NULL
250      )
251  )
252SELECT
253  ts,
254  coalesce(end_ts - ts, -1) AS dur,
255  coalesce(end_ts, trace_end()) - ts AS safe_dur,
256  track_name,
257  str_split(key, '"', 1) AS str_value,
258  cast_int!(str_split(key, ':', 0)) AS int_value
259FROM event_spans;
260