• 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--
16INCLUDE PERFETTO MODULE android.battery;
17INCLUDE PERFETTO MODULE android.battery_stats;
18INCLUDE PERFETTO MODULE android.suspend;
19INCLUDE PERFETTO MODULE counters.intervals;
20
21DROP VIEW IF EXISTS battery_view;
22CREATE PERFETTO VIEW battery_view AS
23SELECT * FROM android_battery_charge;
24
25DROP TABLE IF EXISTS android_batt_wakelocks_merged;
26CREATE PERFETTO TABLE android_batt_wakelocks_merged AS
27SELECT
28  MIN(ts) AS ts,
29  MAX(ts_end) AS ts_end
30FROM (
31    SELECT
32      *,
33      SUM(new_group) OVER (ORDER BY ts) AS group_id
34    FROM (
35        SELECT
36          ts,
37          ts + dur AS ts_end,
38          -- There is a new group if there was a gap before this wakelock.
39          -- i.e. the max end timestamp of all preceding wakelocks is before
40          -- the start timestamp of this one.
41          -- The null check is for the first row which is always a new group.
42          IFNULL(
43            MAX(ts + dur) OVER (
44              ORDER BY ts
45              ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
46            ) < ts,
47            TRUE
48          ) AS new_group
49        FROM slice
50        WHERE slice.name GLOB 'WakeLock *' AND dur != -1
51    )
52)
53GROUP BY group_id;
54
55-- TODO(simonmacm) remove this shim once no longer used internally
56DROP TABLE IF EXISTS suspend_slice_;
57CREATE PERFETTO TABLE suspend_slice_ AS
58SELECT ts, dur FROM android_suspend_state where power_state = 'suspended';
59
60DROP TABLE IF EXISTS screen_state_span;
61CREATE PERFETTO TABLE screen_state_span AS
62WITH screen_state AS (
63  SELECT counter.id, ts, 0 AS track_id, value
64  FROM counter
65  JOIN counter_track ON counter_track.id = counter.track_id
66  WHERE name = 'ScreenState'
67)
68SELECT * FROM counter_leading_intervals!(screen_state);
69
70DROP TABLE IF EXISTS screen_state_span_with_suspend;
71CREATE VIRTUAL TABLE screen_state_span_with_suspend
72USING span_join(screen_state_span, suspend_slice_);
73
74DROP TABLE IF EXISTS power_mw_intervals;
75CREATE PERFETTO TABLE power_mw_intervals AS
76WITH power_mw_counter AS (
77  SELECT counter.id, ts, track_id, value
78  FROM counter
79  JOIN counter_track ON counter_track.id = counter.track_id
80  WHERE name = 'batt.power_mw'
81)
82SELECT * FROM counter_leading_intervals!(power_mw_counter);
83
84DROP TABLE IF EXISTS charge_diff_mw;
85CREATE PERFETTO TABLE charge_diff_mw AS
86with energy_counters as (
87select
88  ts,
89  CASE
90    WHEN energy_counter_uwh IS NOT NULL THEN energy_counter_uwh
91    ELSE charge_uah *  voltage_uv / 1e12 END as energy
92 from android_battery_charge
93), start_energy as (
94  select
95  min(ts) as ts,
96  energy
97  from energy_counters
98), end_energy as (
99  select
100  max(ts) as ts,
101  energy
102  from energy_counters
103)
104select
105  -- If the battery is discharging, the start energy value will be greater than
106  -- the end and the estimate will report a positive value.
107  -- Battery energy is in watt hours, so multiply by 3600 to convert to joules.
108  -- Convert perfetto timestamp from nanoseconds to seconds.
109  -- Divide energy by seconds and convert to milliwatts.
110  (s.energy - e.energy) * 3600 * 1e3 / ((e.ts - s.ts) / 1e9) as estimate
111from start_energy s, end_energy e;
112
113DROP VIEW IF EXISTS android_batt_output;
114CREATE PERFETTO VIEW android_batt_output AS
115SELECT AndroidBatteryMetric(
116  'battery_counters', (
117    SELECT RepeatedField(
118      AndroidBatteryMetric_BatteryCounters(
119        'timestamp_ns', ts,
120        'charge_counter_uah', charge_uah,
121        'capacity_percent', capacity_percent,
122        'current_ua', current_ua,
123        'current_avg_ua', current_avg_ua,
124        'voltage_uv', voltage_uv
125      )
126    )
127    FROM android_battery_charge
128  ),
129  'battery_aggregates', (
130    SELECT NULL_IF_EMPTY(AndroidBatteryMetric_BatteryAggregates(
131      'total_screen_off_ns',
132      SUM(CASE WHEN state = 1.0 AND tbl = 'total' THEN dur ELSE 0 END),
133      'total_screen_on_ns',
134      SUM(CASE WHEN state = 2.0 AND tbl = 'total' THEN dur ELSE 0 END),
135      'total_screen_doze_ns',
136      SUM(CASE WHEN state = 3.0 AND tbl = 'total' THEN dur ELSE 0 END),
137      'sleep_ns',
138      (SELECT SUM(dur) FROM suspend_slice_),
139      'sleep_screen_off_ns',
140      SUM(CASE WHEN state = 1.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
141      'sleep_screen_on_ns',
142      SUM(CASE WHEN state = 2.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
143      'sleep_screen_doze_ns',
144      SUM(CASE WHEN state = 3.0 AND tbl = 'sleep' THEN dur ELSE 0 END),
145      'total_wakelock_ns',
146      (SELECT SUM(ts_end - ts) FROM android_batt_wakelocks_merged),
147      'avg_power_mw',
148      (SELECT SUM(value * dur) / SUM(dur) FROM power_mw_intervals),
149      'avg_power_from_charge_diff_mw',
150      (select estimate FROM charge_diff_mw)
151      ))
152    FROM (
153      SELECT dur, value AS state, 'total' AS tbl
154      FROM screen_state_span
155      UNION ALL
156      SELECT dur, value AS state, 'sleep' AS tbl
157      FROM screen_state_span_with_suspend
158    )
159  ),
160  'suspend_period', (
161    SELECT RepeatedField(
162      AndroidBatteryMetric_SuspendPeriod(
163        'timestamp_ns', ts,
164        'duration_ns', dur
165      )
166    )
167    FROM suspend_slice_
168  )
169);
170