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