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-- Create the base tables and views containing the launch spans.
18SELECT RUN_METRIC('android/android_startup_launches.sql');
19SELECT RUN_METRIC('android/android_task_state.sql');
20SELECT RUN_METRIC('android/process_metadata.sql');
21
22-- Slices for forked processes. Never present in hot starts.
23-- Prefer this over process start_ts, since the process might have
24-- been preforked.
25CREATE VIEW zygote_fork_slice AS
26SELECT slice.ts, slice.dur, STR_SPLIT(slice.name, ": ", 1) AS process_name
27FROM slice WHERE name LIKE 'Start proc: %';
28
29CREATE TABLE zygote_forks_by_id AS
30SELECT
31  launches.id,
32  zygote_fork_slice.ts,
33  zygote_fork_slice.dur
34FROM zygote_fork_slice
35JOIN launches
36ON (launches.ts < zygote_fork_slice.ts
37    AND zygote_fork_slice.ts + zygote_fork_slice.dur < launches.ts_end
38    AND zygote_fork_slice.process_name = launches.package
39);
40
41CREATE VIEW launch_main_threads AS
42SELECT
43  launches.ts AS ts,
44  launches.dur AS dur,
45  launches.id AS launch_id,
46  thread.utid AS utid
47FROM launches
48JOIN launch_processes ON launches.id = launch_processes.launch_id
49JOIN process USING(upid)
50JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
51ORDER BY ts;
52
53CREATE VIRTUAL TABLE main_thread_state
54USING SPAN_JOIN(
55  launch_main_threads PARTITIONED utid,
56  task_state PARTITIONED utid);
57
58CREATE VIEW launch_by_thread_state AS
59SELECT launch_id, state, SUM(dur) AS dur
60FROM main_thread_state
61GROUP BY 1, 2;
62
63-- Tracks all slices for the main process threads
64CREATE TABLE main_process_slice AS
65SELECT
66  launches.id AS launch_id,
67  slice.name AS name,
68  AndroidStartupMetric_Slice(
69    'dur_ns', SUM(slice.dur),
70    'dur_ms', SUM(slice.dur) / 1e6
71  ) AS slice_proto
72FROM launches
73JOIN launch_processes ON (launches.id = launch_processes.launch_id)
74JOIN thread ON (launch_processes.upid = thread.upid)
75JOIN thread_track USING (utid)
76JOIN slice ON (
77  slice.track_id = thread_track.id
78  AND slice.ts BETWEEN launches.ts AND launches.ts + launches.dur)
79WHERE slice.name IN (
80  'PostFork',
81  'ActivityThreadMain',
82  'bindApplication',
83  'activityStart',
84  'activityResume',
85  'Choreographer#doFrame',
86  'inflate')
87GROUP BY 1, 2;
88
89CREATE VIEW to_event_protos AS
90SELECT
91  slice.name as slice_name,
92  launch_id,
93  AndroidStartupMetric_Slice(
94    'dur_ns', slice.ts - l.ts,
95    'dur_ms', (slice.ts - l.ts) / 1e6
96  ) as slice_proto
97FROM launch_main_threads l
98JOIN thread_track USING (utid)
99JOIN slice ON (
100  slice.track_id = thread_track.id
101  AND slice.ts BETWEEN l.ts AND l.ts + l.dur);
102
103CREATE VIEW startup_view AS
104SELECT
105  AndroidStartupMetric_Startup(
106    'startup_id', launches.id,
107    'package_name', launches.package,
108    'process_name', (
109      SELECT name FROM process
110      WHERE upid IN (
111        SELECT upid FROM launch_processes
112        WHERE launch_id = launches.id
113        LIMIT 1
114      )
115    ),
116    'process', (
117      SELECT metadata FROM process_metadata
118      WHERE upid IN (
119        SELECT upid FROM launch_processes
120        WHERE launch_id = launches.id
121        LIMIT 1
122      )
123    ),
124    'zygote_new_process', EXISTS(SELECT TRUE FROM zygote_forks_by_id WHERE id = launches.id),
125    'activity_hosting_process_count', (
126      SELECT COUNT(1) FROM launch_processes WHERE launch_id = launches.id
127    ),
128    'to_first_frame', AndroidStartupMetric_ToFirstFrame(
129      'dur_ns', launches.dur,
130      'dur_ms', launches.dur / 1e6,
131      'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown(
132        'running_dur_ns', IFNULL(
133            (
134            SELECT dur FROM launch_by_thread_state
135            WHERE launch_id = launches.id AND state = 'running'
136            ), 0),
137        'runnable_dur_ns', IFNULL(
138            (
139            SELECT dur FROM launch_by_thread_state
140            WHERE launch_id = launches.id AND state = 'runnable'
141            ), 0),
142        'uninterruptible_sleep_dur_ns', IFNULL(
143            (
144            SELECT dur FROM launch_by_thread_state
145            WHERE launch_id = launches.id AND state = 'uninterruptible'
146            ), 0),
147        'interruptible_sleep_dur_ns', IFNULL(
148            (
149            SELECT dur FROM launch_by_thread_state
150            WHERE launch_id = launches.id AND state = 'interruptible'
151            ), 0)
152      ),
153      'to_post_fork', (
154        SELECT slice_proto
155        FROM to_event_protos
156        WHERE launch_id = launches.id AND slice_name = 'PostFork'
157      ),
158      'to_activity_thread_main', (
159        SELECT slice_proto
160        FROM to_event_protos
161        WHERE launch_id = launches.id AND slice_name = 'ActivityThreadMain'
162      ),
163      'to_bind_application', (
164        SELECT slice_proto
165        FROM to_event_protos
166        WHERE launch_id = launches.id AND slice_name = 'bindApplication'
167      ),
168      'other_processes_spawned_count', (
169        SELECT COUNT(1) FROM process
170        WHERE (process.name IS NULL OR process.name != launches.package)
171        AND process.start_ts BETWEEN launches.ts AND launches.ts + launches.dur
172      ),
173      'time_activity_manager', (
174        SELECT AndroidStartupMetric_Slice(
175          'dur_ns', launching_events.ts - launches.ts,
176          'dur_ms', (launching_events.ts - launches.ts) / 1e6
177        )
178        FROM launching_events
179        WHERE launching_events.ts BETWEEN launches.ts AND launches.ts + launches.dur
180      ),
181      'time_post_fork', (
182        SELECT slice_proto FROM main_process_slice
183        WHERE launch_id = launches.id AND name = 'PostFork'
184      ),
185      'time_activity_thread_main', (
186        SELECT slice_proto FROM main_process_slice
187        WHERE launch_id = launches.id AND name = 'ActivityThreadMain'
188      ),
189      'time_bind_application', (
190        SELECT slice_proto FROM main_process_slice
191        WHERE launch_id = launches.id AND name = 'bindApplication'
192      ),
193      'time_activity_start', (
194        SELECT slice_proto FROM main_process_slice
195        WHERE launch_id = launches.id AND name = 'activityStart'
196      ),
197      'time_activity_resume', (
198        SELECT slice_proto FROM main_process_slice
199        WHERE launch_id = launches.id AND name = 'activityResume'
200      ),
201      'time_choreographer', (
202        SELECT slice_proto FROM main_process_slice
203        WHERE launch_id = launches.id AND name = 'Choreographer#doFrame'
204      ),
205      'time_before_start_process', (
206        SELECT AndroidStartupMetric_Slice(
207          'dur_ns', ts - launches.ts,
208          'dur_ms', (ts - launches.ts) / 1e6
209        )
210        FROM zygote_forks_by_id WHERE id = launches.id
211      ),
212      'time_during_start_process', (
213        SELECT AndroidStartupMetric_Slice(
214          'dur_ns', dur,
215          'dur_ms', dur / 1e6
216        )
217        FROM zygote_forks_by_id WHERE id = launches.id
218      )
219    )
220  ) as startup
221FROM launches;
222
223CREATE VIEW android_startup_output AS
224SELECT
225  AndroidStartupMetric(
226    'startup', (
227      SELECT RepeatedField(startup) FROM startup_view
228    )
229  );
230