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 16SELECT IMPORT('common.timestamps'); 17 18-- Converts a battery_stats counter value to human readable string. 19-- 20-- @arg track STRING The counter track name (e.g. 'battery_stats.audio'). 21-- @arg value LONG The counter value. 22-- @ret STRING The human-readable name for the counter value. 23SELECT CREATE_FUNCTION( 24 'BATTERY_STATS_COUNTER_TO_STRING(track STRING, value FLOAT)', 25 'STRING', 26 ' 27 SELECT 28 CASE 29 WHEN ($track = "battery_stats.wifi_scan" OR 30 $track = "battery_stats.wifi_radio" OR 31 $track = "battery_stats.mobile_radio" OR 32 $track = "battery_stats.audio" OR 33 $track = "battery_stats.video" OR 34 $track = "battery_stats.camera" OR 35 $track = "battery_stats.power_save" OR 36 $track = "battery_stats.phone_in_call") 37 THEN 38 CASE $value 39 WHEN 0 THEN "inactive" 40 WHEN 1 THEN "active" 41 ELSE "unknown" 42 END 43 WHEN $track = "battery_stats.wifi" 44 THEN 45 CASE $value 46 WHEN 0 THEN "off" 47 WHEN 1 THEN "on" 48 ELSE "unknown" 49 END 50 WHEN $track = "battery_stats.phone_state" 51 THEN 52 CASE $value 53 WHEN 0 THEN "in" 54 WHEN 1 THEN "out" 55 WHEN 2 THEN "emergency" 56 WHEN 3 THEN "off" 57 ELSE "unknown" 58 END 59 WHEN ($track = "battery_stats.phone_signal_strength" OR 60 $track = "battery_stats.wifi_signal_strength") 61 THEN 62 CASE $value 63 WHEN 0 THEN "none" 64 WHEN 1 THEN "poor" 65 WHEN 2 THEN "moderate" 66 WHEN 3 THEN "good" 67 WHEN 4 THEN "great" 68 ELSE "unknown" 69 END 70 WHEN $track = "battery_stats.wifi_suppl" 71 THEN 72 CASE $value 73 WHEN 0 THEN "invalid" 74 WHEN 1 THEN "disconn" 75 WHEN 2 THEN "disabled" 76 WHEN 3 THEN "inactive" 77 WHEN 4 THEN "scanning" 78 WHEN 5 THEN "authenticating" 79 WHEN 6 THEN "associating" 80 WHEN 7 THEN "associated" 81 WHEN 8 THEN "4-way-handshake" 82 WHEN 9 THEN "group-handshake" 83 WHEN 10 THEN "completed" 84 WHEN 11 THEN "dormant" 85 WHEN 12 THEN "uninit" 86 ELSE "unknown" 87 END 88 WHEN $track = "battery_stats.data_conn" 89 THEN 90 CASE $value 91 WHEN 0 THEN "oos" 92 WHEN 1 THEN "gprs" 93 WHEN 2 THEN "edge" 94 WHEN 3 THEN "umts" 95 WHEN 4 THEN "cdma" 96 WHEN 5 THEN "evdo_0" 97 WHEN 6 THEN "evdo_A" 98 WHEN 7 THEN "1xrtt" 99 WHEN 8 THEN "hsdpa" 100 WHEN 9 THEN "hsupa" 101 WHEN 10 THEN "hspa" 102 WHEN 11 THEN "iden" 103 WHEN 12 THEN "evdo_b" 104 WHEN 13 THEN "lte" 105 WHEN 14 THEN "ehrpd" 106 WHEN 15 THEN "hspap" 107 WHEN 16 THEN "gsm" 108 WHEN 17 THEN "td_scdma" 109 WHEN 18 THEN "iwlan" 110 WHEN 19 THEN "lte_ca" 111 WHEN 20 THEN "nr" 112 WHEN 21 THEN "emngcy" 113 WHEN 22 THEN "other" 114 ELSE "unknown" 115 END 116 ELSE CAST($value AS text) 117 END 118 ' 119); 120 121 122-- View of human readable battery stats counter-based states. These are recorded 123-- by BatteryStats as a bitmap where each 'category' has a unique value at any 124-- given time. 125-- 126-- @column ts Timestamp in nanoseconds. 127-- @column dur The duration the state was active. 128-- @column track_name The name of the counter track. 129-- @column value The counter value as a number. 130-- @column value_name The counter value as a human-readable string. 131CREATE VIEW android_battery_stats_state AS 132SELECT 133 ts, 134 name AS track_name, 135 CAST(value AS INT64) AS value, 136 BATTERY_STATS_COUNTER_TO_STRING(name, value) AS value_name, 137 IFNULL(LEAD(ts) OVER (PARTITION BY track_id ORDER BY ts) - ts, -1) AS dur 138FROM counter 139JOIN counter_track 140 ON counter.track_id = counter_track.id 141WHERE counter_track.name GLOB 'battery_stats.*'; 142 143 144-- View of slices derived from battery_stats events. Battery stats records all 145-- events as instants, however some may indicate whether something started or 146-- stopped with a '+' or '-' prefix. Events such as jobs, top apps, foreground 147-- apps or long wakes include these details and allow drawing slices between 148-- instant events found in a trace. 149-- 150-- For example, we may see an event like the following on 'battery_stats.top': 151-- 152-- -top=10215:"com.google.android.apps.nexuslauncher" 153-- 154-- This view will find the associated start ('+top') with the matching suffix 155-- (everything after the '=') to construct a slice. It computes the timestamp 156-- and duration from the events and extract the details as follows: 157-- 158-- track_name='battery_stats.top' 159-- str_value='com.google.android.apps.nexuslauncher' 160-- int_value=10215 161-- 162-- @column track_name The battery stats track name. 163-- @column ts Timestamp in nanoseconds. 164-- @column dur The duration of the event. 165-- @column str_value The string part of the event identifier. 166-- @column int_value The integer part of the event identifier. 167CREATE VIEW android_battery_stats_event_slices AS 168WITH 169 event_markers AS ( 170 SELECT 171 ts, 172 track.name AS track_name, 173 str_split(slice.name, '=', 1) AS key, 174 substr(slice.name, 1, 1) = '+' AS start 175 FROM slice 176 JOIN track 177 ON slice.track_id = track.id 178 WHERE 179 track_name GLOB 'battery_stats.*' 180 AND substr(slice.name, 1, 1) IN ('+', '-') 181 ), 182 with_neighbors AS ( 183 SELECT 184 *, 185 LAG(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS last_ts, 186 LEAD(ts) OVER (PARTITION BY track_name, key ORDER BY ts) AS next_ts 187 FROM event_markers 188 ), 189 -- Note: query performance depends on the ability to push down filters on 190 -- the track_name. It would be more clear below to have two queries and union 191 -- them, but doing so prevents push down through the above window functions. 192 event_spans AS ( 193 SELECT 194 track_name, key, 195 IIF(start, ts, TRACE_START()) AS ts, 196 IIF(start, next_ts, ts) AS end_ts 197 FROM with_neighbors 198 -- For the majority of events, we take the `start` event and compute the dur 199 -- based on next_ts. In the off chance we get an end event with no prior 200 -- start (matched by the second half of this where), we can create an event 201 -- starting from the beginning of the trace ending at the current event. 202 WHERE (start OR last_ts IS NULL) 203 ) 204SELECT 205 ts, 206 IFNULL(end_ts-ts, -1) AS dur, 207 track_name, 208 str_split(key, '"', 1) AS str_value, 209 CAST(str_split(key, ':', 0) AS INT64) AS int_value 210FROM event_spans; 211