1-- 2-- Copyright 2020 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-- WebView is embedded in the hosting app's main process, which means it shares some threads 17-- with the host app's work. We approximate WebView-related power usage 18-- by selecting user slices that belong to WebView and estimating their power use 19-- through the CPU time they consume at different core frequencies. 20-- This file populates a summary table that can be used to produce metrics in different formats. 21 22SELECT RUN_METRIC('android/android_proxy_power.sql'); 23SELECT RUN_METRIC('android/cpu_info.sql'); 24 25DROP TABLE IF EXISTS top_level_slice; 26 27-- Select topmost slices from the 'toplevel' and 'Java' categories. 28-- Filter out Looper events since they are likely to belong to the host app. 29-- Slices are only used to calculate the contribution of the browser process, 30-- renderer contribution will be calculated as the sum of all renderer processes' usage. 31CREATE TABLE top_level_slice AS 32 SELECT * 33 FROM slice WHERE 34 depth = 0 AND 35 ((category GLOB '*toplevel*' OR category = 'Java') AND 36 name NOT GLOB '*looper*'); 37 38DROP TABLE IF EXISTS webview_browser_slices; 39 40-- Match top-level slices to threads and hosting apps. 41-- This excludes any renderer slices because renderer processes are counted 42-- as a whole separately. 43-- Slices from Chrome browser processes are also excluded. 44CREATE TABLE webview_browser_slices AS 45 SELECT 46 top_level_slice.ts, 47 top_level_slice.dur, 48 thread_track.utid, 49 process.upid AS upid, 50 extract_arg(process.arg_set_id, 'chrome.host_app_package_name') AS app_name 51 FROM top_level_slice 52 INNER JOIN thread_track 53 ON top_level_slice.track_id = thread_track.id 54 INNER JOIN process 55 ON thread.upid = process.upid 56 INNER JOIN thread 57 ON thread_track.utid = thread.utid 58 WHERE process.name NOT GLOB '*SandboxedProcessService*' 59 AND process.name NOT GLOB '*chrome*' 60 AND app_name IS NOT NULL; 61 62DROP TABLE IF EXISTS webview_browser_slices_power; 63 64-- Assign power usage to WebView browser slices. 65CREATE VIRTUAL TABLE webview_browser_slices_power 66USING SPAN_JOIN(power_per_thread PARTITIONED utid, 67 webview_browser_slices PARTITIONED utid); 68 69DROP TABLE IF EXISTS webview_browser_slices_power_summary; 70 71-- Calculate the power usage of all WebView browser slices for each app 72-- in milliampere-seconds. 73CREATE TABLE webview_browser_slices_power_summary AS 74SELECT 75 app_name, 76 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 77 FROM webview_browser_slices_power 78 GROUP BY app_name; 79 80DROP TABLE IF EXISTS webview_renderer_threads; 81 82-- All threads of all WebView renderer processes. 83CREATE TABLE webview_renderer_threads AS 84SELECT 85 thread.utid AS utid, 86 extract_arg(process.arg_set_id, 'chrome.host_app_package_name') as app_name 87 FROM process 88 INNER JOIN thread 89 ON thread.upid = process.upid 90 WHERE process.name GLOB '*webview*SandboxedProcessService*' 91 AND app_name IS NOT NULL; 92 93DROP TABLE IF EXISTS webview_renderer_power_summary; 94 95-- Calculate the power usage of all WebView renderer processes for each app 96-- in milliampere-seconds. 97CREATE TABLE webview_renderer_power_summary AS 98 SELECT 99 app_name, 100 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 101 FROM power_per_thread 102 INNER JOIN webview_renderer_threads 103 ON power_per_thread.utid = webview_renderer_threads.utid 104 GROUP BY app_name; 105 106DROP TABLE IF EXISTS webview_renderer_power_per_core_type; 107 108-- Calculate the power usage of all WebView renderer processes for each app 109-- in milliampere-seconds grouped by core type. 110CREATE TABLE webview_renderer_power_per_core_type AS 111SELECT 112 app_name, 113 core_type_per_cpu.core_type AS core_type, 114 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 115FROM power_per_thread 116INNER JOIN webview_renderer_threads 117 ON power_per_thread.utid = webview_renderer_threads.utid 118INNER JOIN core_type_per_cpu 119 ON power_per_thread.cpu = core_type_per_cpu.cpu 120GROUP BY app_name, core_type_per_cpu.core_type; 121 122DROP TABLE IF EXISTS host_app_threads; 123 124-- All threads of hosting apps (this is a superset of webview_browser_slices). 125-- 1) select all threads that had any WebView browser slices associated with them; 126-- 2) get all threads for processes matching threads from 1). 127-- For example, only some of app's threads wrote any slices, but we are selecting 128-- all threads for this app's process. 129-- Excludes all renderer processes and Chrome browser processes. 130CREATE TABLE host_app_threads AS 131SELECT 132 thread.utid AS utid, 133 thread.name AS name, 134 extract_arg(process.arg_set_id, 'chrome.host_app_package_name') as app_name 135 FROM thread 136 JOIN process ON thread.upid = process.upid 137 WHERE thread.upid IN 138 (SELECT DISTINCT(webview_browser_slices.upid) FROM webview_browser_slices) 139 AND process.name NOT GLOB '*SandboxedProcessService*' 140 AND process.name NOT GLOB '*chrome*' 141 AND app_name IS NOT NULL; 142 143DROP TABLE IF EXISTS host_app_power_summary; 144 145-- Calculate the power usage of all WebView (host app+browser) processes for each app 146-- in milliampere-seconds. 147CREATE TABLE host_app_power_summary AS 148 SELECT 149 app_name, 150 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 151 FROM power_per_thread 152 INNER JOIN host_app_threads 153 ON power_per_thread.utid = host_app_threads.utid 154 GROUP BY app_name; 155 156DROP TABLE IF EXISTS host_app_power_per_core_type; 157 158-- Calculate the power usage of all WebView (host app+browser) processes for each app 159-- in milliampere-seconds grouped by core type. 160CREATE TABLE host_app_power_per_core_type AS 161SELECT 162 app_name, 163 core_type_per_cpu.core_type AS core_type, 164 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 165FROM power_per_thread 166INNER JOIN host_app_threads 167 ON power_per_thread.utid = host_app_threads.utid 168INNER JOIN core_type_per_cpu 169 ON power_per_thread.cpu = core_type_per_cpu.cpu 170GROUP BY app_name, core_type_per_cpu.core_type; 171 172DROP TABLE IF EXISTS webview_only_threads; 173 174-- A subset of the host app threads that are WebView-specific. 175CREATE TABLE webview_only_threads AS 176SELECT * 177FROM host_app_threads 178 WHERE name GLOB 'Chrome*' OR name GLOB 'CookieMonster*' 179 OR name GLOB 'CompositorTileWorker*' OR name GLOB 'ThreadPool*ground*' 180 OR NAME GLOB 'ThreadPoolService*' OR name GLOB 'VizCompositorThread*' 181 OR name IN ('AudioThread', 'DedicatedWorker thread', 'GpuMemoryThread', 182 'JavaBridge', 'LevelDBEnv.IDB', 'MemoryInfra', 'NetworkService', 'VizWebView'); 183 184DROP TABLE IF EXISTS webview_only_power_summary; 185 186-- Calculate the power usage of all WebView-specific host app threads 187-- (browser + in-process renderers) for each app in milliampere-seconds. 188CREATE TABLE webview_only_power_summary AS 189 SELECT 190 app_name, 191 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 192 FROM power_per_thread 193 INNER JOIN webview_only_threads 194 ON power_per_thread.utid = webview_only_threads.utid 195 GROUP BY app_name; 196 197DROP TABLE IF EXISTS webview_only_power_per_core_type; 198 199-- Calculate the power usage of all WebView-specific host app threads 200-- for each app in milliampere-seconds grouped by core type. 201CREATE TABLE webview_only_power_per_core_type AS 202 SELECT app_name, 203 core_type_per_cpu.core_type AS core_type, 204 SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 205FROM power_per_thread 206INNER JOIN webview_only_threads 207 ON power_per_thread.utid = webview_only_threads.utid 208INNER JOIN core_type_per_cpu 209 ON power_per_thread.cpu = core_type_per_cpu.cpu 210GROUP BY app_name, core_type_per_cpu.core_type; 211 212-- Create views for output. 213 214DROP TABLE IF EXISTS total_app_power_output; 215 216CREATE TABLE total_app_power_output AS 217 SELECT 218 host_app_power_summary.app_name as app_name, 219 host_app_power_summary.power_mas AS total_mas, 220 host_app_power_little_cores_mas.power_mas AS little_cores_mas, 221 host_app_power_big_cores_mas.power_mas AS big_cores_mas, 222 host_app_power_bigger_cores_mas.power_mas AS bigger_cores_mas 223 FROM host_app_power_summary LEFT JOIN host_app_power_per_core_type AS host_app_power_little_cores_mas 224 ON host_app_power_summary.app_name = host_app_power_little_cores_mas.app_name 225 AND host_app_power_little_cores_mas.core_type = 'little' 226 LEFT JOIN host_app_power_per_core_type AS host_app_power_big_cores_mas 227 ON host_app_power_summary.app_name = host_app_power_big_cores_mas.app_name 228 AND host_app_power_big_cores_mas.core_type = 'big' 229 LEFT JOIN host_app_power_per_core_type AS host_app_power_bigger_cores_mas 230 ON host_app_power_summary.app_name = host_app_power_bigger_cores_mas.app_name 231 AND host_app_power_bigger_cores_mas.core_type = 'bigger'; 232 233DROP TABLE IF EXISTS webview_renderer_power_output; 234 235CREATE TABLE webview_renderer_power_output AS 236 SELECT 237 webview_renderer_power_summary.app_name AS app_name, 238 webview_renderer_power_summary.power_mas AS total_mas, 239 webview_renderer_little_power.power_mas AS little_cores_mas, 240 webview_renderer_big_power.power_mas AS big_cores_mas, 241 webview_renderer_bigger_power.power_mas AS bigger_cores_mas 242 FROM webview_renderer_power_summary LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_little_power 243 ON webview_renderer_power_summary.app_name = webview_renderer_little_power.app_name 244 AND webview_renderer_little_power.core_type = 'little' 245 LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_big_power 246 ON webview_renderer_power_summary.app_name = webview_renderer_big_power.app_name 247 AND webview_renderer_big_power.core_type = 'big' 248 LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_bigger_power 249 ON webview_renderer_power_summary.app_name = webview_renderer_bigger_power.app_name 250 AND webview_renderer_bigger_power.core_type = 'bigger'; 251 252DROP TABLE IF EXISTS webview_only_power_output; 253 254CREATE TABLE webview_only_power_output AS 255 SELECT 256 webview_only_power_summary.app_name AS app_name, 257 webview_only_power_summary.power_mas AS total_mas, 258 webview_only_power_little_cores_mas.power_mas AS little_cores_mas, 259 webview_only_power_big_cores_mas.power_mas AS big_cores_mas, 260 webview_only_power_bigger_cores_mas.power_mas AS bigger_cores_mas 261 FROM webview_only_power_summary LEFT JOIN webview_only_power_per_core_type AS webview_only_power_little_cores_mas 262 ON webview_only_power_summary.app_name = webview_only_power_little_cores_mas.app_name 263 AND webview_only_power_little_cores_mas.core_type = 'little' 264 LEFT JOIN webview_only_power_per_core_type AS webview_only_power_big_cores_mas 265 ON webview_only_power_summary.app_name = webview_only_power_big_cores_mas.app_name 266 AND webview_only_power_big_cores_mas.core_type = 'big' 267 LEFT JOIN webview_only_power_per_core_type AS webview_only_power_bigger_cores_mas 268 ON webview_only_power_summary.app_name = webview_only_power_bigger_cores_mas.app_name 269 AND webview_only_power_bigger_cores_mas.core_type = 'bigger'; 270 271DROP TABLE IF EXISTS total_device_power; 272 273-- Calculate the power usage of the device in milliampere-seconds. 274CREATE TABLE total_device_power AS 275 SELECT SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas 276 FROM power_per_thread; 277