• 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
16SELECT IMPORT('common.slices');
17SELECT IMPORT('android.process_metadata');
18
19-- All activity startup events.
20CREATE TABLE internal_startup_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
30  s.name GLOB 'launching: *'
31  AND (process.name IS NULL OR process.name = 'system_server');
32
33-- Gather all startup data. Populate by different sdks.
34CREATE TABLE internal_all_startups(
35  sdk STRING,
36  startup_id INTEGER BIGINT,
37  ts BIGINT,
38  ts_end BIGINT,
39  dur BIGINT,
40  package STRING,
41  startup_type STRING
42);
43
44SELECT IMPORT('android.startup.internal_startups_maxsdk28');
45SELECT IMPORT('android.startup.internal_startups_minsdk29');
46SELECT IMPORT('android.startup.internal_startups_minsdk33');
47
48-- All activity startups in the trace by startup id.
49-- Populated by different scripts depending on the platform version/contents.
50--
51-- @column id           Startup id.
52-- @column ts           Timestamp of startup start.
53-- @column ts_end       Timestamp of startup end.
54-- @column dur          Startup duration.
55-- @column package      Package name.
56-- @column startup_type Startup type.
57CREATE TABLE android_startups AS
58SELECT startup_id, ts, ts_end, dur, package, startup_type FROM
59internal_all_startups WHERE ( CASE
60  WHEN SLICE_COUNT('launchingActivity#*:*') > 0
61    THEN sdk = "minsdk33"
62  WHEN SLICE_COUNT('MetricsLogger:*') > 0
63    THEN sdk = "minsdk29"
64  ELSE sdk = "maxsdk28"
65  END);
66
67--
68-- Create startup processes
69--
70
71-- Create a table containing only the slices which are necessary for determining
72-- whether a startup happened.
73CREATE TABLE internal_startup_indicator_slices AS
74SELECT ts, name, track_id
75FROM slice
76WHERE name IN ('bindApplication', 'activityStart', 'activityResume');
77
78SELECT CREATE_FUNCTION(
79  'INTERNAL_STARTUP_INDICATOR_SLICE_COUNT(start_ts LONG, end_ts LONG, utid INT, name STRING)',
80  'INT',
81  '
82    SELECT COUNT(1)
83    FROM thread_track t
84    JOIN internal_startup_indicator_slices s ON s.track_id = t.id
85    WHERE
86      t.utid = $utid AND
87      s.ts >= $start_ts AND
88      s.ts < $end_ts AND
89      s.name = $name
90  '
91);
92
93-- Maps a startup to the set of processes that handled the activity start.
94--
95-- The vast majority of cases should be a single process. However it is
96-- possible that the process dies during the activity startup and is respawned.
97--
98-- @column startup_id   Startup id.
99-- @column upid         Upid of process on which activity started.
100-- @column startup_type Type of the startup.
101CREATE TABLE android_startup_processes AS
102-- This is intentionally a materialized query. For some reason, if we don't
103-- materialize, we end up with a query which is an order of magnitude slower :(
104WITH startup_with_type AS MATERIALIZED (
105  SELECT
106    startup_id,
107    upid,
108    CASE
109      -- type parsed from platform event takes precedence if available
110      WHEN startup_type IS NOT NULL THEN startup_type
111      WHEN bind_app > 0 AND a_start > 0 AND a_resume > 0 THEN 'cold'
112      WHEN a_start > 0 AND a_resume > 0 THEN 'warm'
113      WHEN a_resume > 0 THEN 'hot'
114      ELSE NULL
115    END AS startup_type
116  FROM (
117    SELECT
118      l.startup_id,
119      l.startup_type,
120      p.upid,
121      INTERNAL_STARTUP_INDICATOR_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'bindApplication') AS bind_app,
122      INTERNAL_STARTUP_INDICATOR_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'activityStart') AS a_start,
123      INTERNAL_STARTUP_INDICATOR_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'activityResume') AS a_resume
124    FROM android_startups l
125    JOIN android_process_metadata p ON (
126      l.package = p.package_name
127      -- If the package list data source was not enabled in the trace, nothing
128      -- will match the above constraint so also match any process whose name
129      -- is a prefix of the package name.
130      OR (
131        (SELECT COUNT(1) = 0 FROM package_list)
132        AND p.process_name GLOB l.package || '*'
133      )
134      )
135    JOIN thread t ON (p.upid = t.upid AND t.is_main_thread)
136  )
137)
138SELECT *
139FROM startup_with_type
140WHERE startup_type IS NOT NULL;
141
142
143-- Maps a startup to the set of threads on processes that handled the
144-- activity start.
145--
146-- @column startup_id     Startup id.
147-- @column ts             Timestamp of start.
148-- @column dur            Duration of startup.
149-- @column upid           Upid of process involved in startup.
150-- @column utid           Utid of the thread.
151-- @column thread_name    Name of the thread.
152-- @column is_main_thread Thread is a main thread.
153CREATE VIEW android_startup_threads AS
154SELECT
155  startups.startup_id,
156  startups.ts,
157  startups.dur,
158  android_startup_processes.upid,
159  thread.utid,
160  thread.name AS thread_name,
161  thread.is_main_thread AS is_main_thread
162FROM android_startups startups
163JOIN android_startup_processes USING (startup_id)
164JOIN thread USING (upid);
165
166---
167--- Functions
168---
169
170-- All the slices for all startups in trace.
171--
172-- Generally, this view should not be used. Instead, use one of the view functions related
173-- to the startup slices which are created from this table.
174--
175-- @column startup_ts     Timestamp of startup.
176-- @column startup_ts_end Timestamp of startup end.
177-- @column startup_id     Startup id.
178-- @column utid           UTID of thread with slice.
179-- @column thread_name    Name of thread.
180-- @column is_main_thread Whether it is main thread.
181-- @column arg_set_id     Arg set id.
182-- @column slice_id       Slice id.
183-- @column slice_name     Name of slice.
184-- @column slice_ts       Timestamp of slice start.
185-- @column slice_dur      Slice duration.
186CREATE VIEW android_thread_slices_for_all_startups AS
187SELECT
188  st.ts AS startup_ts,
189  st.ts + st.dur AS startup_ts_end,
190  st.startup_id,
191  st.utid,
192  st.thread_name,
193  st.is_main_thread,
194  slice.arg_set_id,
195  slice.id as slice_id,
196  slice.name AS slice_name,
197  slice.ts AS slice_ts,
198  slice.dur AS slice_dur
199FROM android_startup_threads st
200JOIN thread_track USING (utid)
201JOIN slice ON (slice.track_id = thread_track.id)
202WHERE slice.ts BETWEEN st.ts AND st.ts + st.dur;
203
204-- Given a startup id and GLOB for a slice name, returns matching slices with data.
205--
206-- @arg startup_id INT    Startup id.
207-- @arg slice_name STRING Glob of the slice.
208-- @column slice_name     Name of the slice.
209-- @column slice_ts       Timestamp of start of the slice.
210-- @column slice_dur      Duration of the slice.
211-- @column thread_name    Name of the thread with the slice.
212-- @column arg_set_id     Arg set id.
213SELECT CREATE_VIEW_FUNCTION(
214  'ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(startup_id INT, slice_name STRING)',
215  'slice_name STRING, slice_ts INT, slice_dur INT, thread_name STRING, arg_set_id INT',
216  '
217    SELECT slice_name, slice_ts, slice_dur, thread_name, arg_set_id
218    FROM android_thread_slices_for_all_startups
219    WHERE startup_id = $startup_id AND slice_name GLOB $slice_name
220  '
221);
222
223-- Returns binder transaction slices for a given startup id with duration over threshold.
224--
225-- @arg startup_id INT    Startup id.
226-- @arg threshold DOUBLE  Only return slices with duration over threshold.
227-- @column id             Slice id.
228-- @column slice_dur      Slice duration.
229-- @column thread_name    Name of the thread with slice.
230-- @column process        Name of the process with slice.
231-- @column arg_set_id     Arg set id.
232-- @column is_main_thread Whether is main thread.
233SELECT CREATE_VIEW_FUNCTION(
234  'ANDROID_BINDER_TRANSACTION_SLICES_FOR_STARTUP(startup_id INT, threshold DOUBLE)',
235  'id INT, slice_dur INT, thread_name STRING, process STRING, arg_set_id INT, is_main_thread BOOL',
236  '
237    SELECT slice_id as id, slice_dur, thread_name, process.name as process, s.arg_set_id, is_main_thread
238    FROM android_thread_slices_for_all_startups s
239    JOIN process ON (
240      EXTRACT_ARG(s.arg_set_id, "destination process") = process.pid
241    )
242    WHERE startup_id = $startup_id AND slice_name GLOB "binder transaction" AND slice_dur > $threshold
243  '
244);
245
246-- Returns duration of startup for slice name.
247--
248-- Sums duration of all slices of startup with provided name.
249--
250-- @arg startup_id LONG   Startup id.
251-- @arg slice_name STRING Slice name.
252-- @ret INT               Sum of duration.
253SELECT CREATE_FUNCTION(
254  'ANDROID_SUM_DUR_FOR_STARTUP_AND_SLICE(startup_id LONG, slice_name STRING)',
255  'INT',
256  '
257    SELECT SUM(slice_dur)
258    FROM android_thread_slices_for_all_startups
259    WHERE startup_id = $startup_id AND slice_name GLOB $slice_name
260  '
261);
262
263-- Returns duration of startup for slice name on main thread.
264--
265-- Sums duration of all slices of startup with provided name only on main thread.
266--
267-- @arg startup_id LONG   Startup id.
268-- @arg slice_name STRING Slice name.
269-- @ret INT               Sum of duration.
270SELECT CREATE_FUNCTION(
271  'ANDROID_SUM_DUR_ON_MAIN_THREAD_FOR_STARTUP_AND_SLICE(startup_id LONG, slice_name STRING)',
272  'INT',
273  '
274    SELECT SUM(slice_dur)
275    FROM android_thread_slices_for_all_startups
276    WHERE startup_id = $startup_id AND slice_name GLOB $slice_name AND is_main_thread
277  '
278);