blob: 894736437a941faef74f3c6f4caccfa240703b35 [file] [log] [blame]
// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
Plugin,
PluginContext,
PluginDescriptor,
} from '../../public';
class AndroidCujs implements Plugin {
onActivate(ctx: PluginContext): void {
ctx.addCommand({
id: 'dev.perfetto.AndroidCujs#ListJankCUJs',
name: 'Run query: Android Jank CUJs',
callback: () => ctx.viewer.tabs.openQuery(
`
SELECT RUN_METRIC('android/android_jank_cuj.sql');
SELECT RUN_METRIC('android/jank/internal/counters.sql');
SELECT
CASE
WHEN
EXISTS(
SELECT 1
FROM slice AS cuj_state_marker
JOIN track marker_track
ON marker_track.id = cuj_state_marker.track_id
WHERE
cuj_state_marker.ts >= cuj.ts
AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
AND
( /* e.g. J<CUJ_NAME>#FT#cancel#0 this for backward compatibility */
cuj_state_marker.name GLOB(cuj.name || '#FT#cancel*')
OR (marker_track.name = cuj.name AND cuj_state_marker.name GLOB 'FT#cancel*')
)
)
THEN '❌ CANCELED'
WHEN
EXISTS(
SELECT 1
FROM slice AS cuj_state_marker
JOIN track marker_track
ON marker_track.id = cuj_state_marker.track_id
WHERE
cuj_state_marker.ts >= cuj.ts
AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
AND
( /* e.g. J<CUJ_NAME>#FT#end#0 this for backward compatibility */
cuj_state_marker.name GLOB(cuj.name || '#FT#end*')
OR (marker_track.name = cuj.name AND cuj_state_marker.name GLOB 'FT#end*')
)
)
THEN '✅ completed'
ELSE NULL
END AS state,
cuj.name,
total_frames,
missed_app_frames,
missed_sf_frames,
sf_callback_missed_frames,
hwui_callback_missed_frames,
cuj_layer.layer_name,
cuj.ts,
cuj.dur,
cuj.track_id,
cuj.slice_id
FROM slice AS cuj
JOIN process_track AS pt
ON cuj.track_id = pt.id
LEFT JOIN android_jank_cuj jc
ON pt.upid = jc.upid AND cuj.name = jc.cuj_slice_name AND cuj.ts = jc.ts
LEFT JOIN android_jank_cuj_layer_name cuj_layer USING (cuj_id)
LEFT JOIN android_jank_cuj_counter_metrics USING (cuj_id)
WHERE cuj.name GLOB 'J<*>'
AND cuj.dur > 0
ORDER BY state asc, cuj.ts desc;
`,
'Android Jank CUJs'),
});
ctx.addCommand({
id: 'dev.perfetto.AndroidCujs#ListLatencyCUJs',
name: 'Run query: Android Latency CUJs',
callback: () => ctx.viewer.tabs.openQuery(
`
SELECT
CASE
WHEN
EXISTS(
SELECT 1
FROM slice AS cuj_state_marker
JOIN track marker_track
ON marker_track.id = cuj_state_marker.track_id
WHERE
cuj_state_marker.ts >= cuj.ts
AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
AND marker_track.name = cuj.name AND (
cuj_state_marker.name GLOB 'cancel'
OR cuj_state_marker.name GLOB 'timeout')
)
THEN '❌ CANCELED'
ELSE '✅ completed'
END AS state,
cuj.name,
cuj.dur / 1e6 as dur_ms,
cuj.ts,
cuj.dur,
cuj.track_id,
cuj.slice_id
FROM slice AS cuj
JOIN process_track AS pt
ON cuj.track_id = pt.id
WHERE cuj.name GLOB 'L<*>'
AND cuj.dur > 0
ORDER BY state asc, ts desc;
`,
'Android Latency CUJs'),
});
}
}
export const plugin: PluginDescriptor = {
pluginId: 'dev.perfetto.AndroidCujs',
plugin: AndroidCujs,
};