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-- 16 17-- The start of the launching event corresponds to the end of the AM handling 18-- the startActivity intent, whereas the end corresponds to the first frame drawn. 19-- Only successful app launches have a launching event. 20DROP TABLE IF EXISTS launching_events; 21CREATE TABLE launching_events AS 22SELECT 23 ts, 24 dur, 25 ts + dur AS ts_end, 26 STR_SPLIT(s.name, ": ", 1) AS package_name 27FROM slice s 28JOIN process_track t ON s.track_id = t.id 29JOIN process USING(upid) 30WHERE s.name LIKE 'launching: %' 31AND (process.name IS NULL OR process.name = 'system_server'); 32 33-- Marks the beginning of the trace and is equivalent to when the statsd launch 34-- logging begins. 35DROP VIEW IF EXISTS activity_intent_received; 36CREATE VIEW activity_intent_received AS 37SELECT ts FROM slice 38WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted'; 39 40-- Successful activity launch. The end of the 'launching' event is not related 41-- to whether it actually succeeded or not. 42DROP VIEW IF EXISTS activity_intent_launch_successful; 43CREATE VIEW activity_intent_launch_successful AS 44SELECT ts FROM slice 45WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished'; 46 47-- We partition the trace into spans based on posted activity intents. 48-- We will refine these progressively in the next steps to only encompass 49-- activity starts. 50DROP TABLE IF EXISTS activity_intent_recv_spans; 51CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT); 52 53INSERT INTO activity_intent_recv_spans 54SELECT 55 ROW_NUMBER() 56 OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id, 57 ts, 58 LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur 59FROM activity_intent_received 60ORDER BY ts; 61 62-- Filter activity_intent_recv_spans, keeping only the ones that triggered 63-- a launch. 64DROP VIEW IF EXISTS launch_partitions; 65CREATE VIEW launch_partitions AS 66SELECT * FROM activity_intent_recv_spans AS spans 67WHERE 1 = ( 68 SELECT COUNT(1) 69 FROM launching_events 70 WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur); 71 72-- All activity launches in the trace, keyed by ID. 73DROP TABLE IF EXISTS launches; 74CREATE TABLE launches( 75 ts BIG INT, 76 ts_end BIG INT, 77 dur BIG INT, 78 id INT, 79 package STRING); 80 81-- Use the starting event package name. The finish event package name 82-- is not reliable in the case of failed launches. 83INSERT INTO launches 84SELECT 85 lpart.ts AS ts, 86 launching_events.ts_end AS ts_end, 87 launching_events.ts_end - lpart.ts AS dur, 88 lpart.id AS id, 89 package_name AS package 90FROM launch_partitions AS lpart 91JOIN launching_events ON 92 (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND 93 (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur) 94WHERE ( 95 SELECT COUNT(1) 96 FROM activity_intent_launch_successful AS successful 97 WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur 98) > 0; 99 100-- Maps a launch to the corresponding set of processes that handled the 101-- activity start. The vast majority of cases should be a single process. 102-- However it is possible that the process dies during the activity launch 103-- and is respawned. 104DROP TABLE IF EXISTS launch_processes; 105CREATE TABLE launch_processes(launch_id INT, upid BIG INT); 106 107-- We make the (not always correct) simplification that process == package 108INSERT INTO launch_processes 109SELECT launches.id, process.upid 110FROM launches 111 JOIN process ON launches.package = process.name 112 JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid) 113WHERE (process.start_ts IS NULL OR process.start_ts < launches.ts_end) 114AND (thread.end_ts IS NULL OR thread.end_ts > launches.ts_end) 115ORDER BY process.start_ts DESC; 116