blob: 1ae9ac6c4f04f3529a3f68f4067482d160f52d5d [file] [log] [blame]
// Copyright (C) 2024 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 {
expandProcessName,
BlockingCallMetricData,
MetricHandler,
} from './metricUtils';
import {Trace} from '../../../public/trace';
import {addJankCUJDebugTrack} from '../../dev.perfetto.AndroidCujs';
import {addDebugSliceTrack} from '../../../public/debug_tracks';
class BlockingCallMetricHandler implements MetricHandler {
/**
* Match metric key & return parsed data if successful.
*
* @param {string} metricKey The metric key to match.
* @returns {BlockingCallMetricData | undefined} Parsed data or undefined if no match.
*/
public match(metricKey: string): BlockingCallMetricData | undefined {
const matcher =
/perfetto_android_blocking_call-cuj-name-(?<process>.*)-name-(?<cujName>.*)-blocking_calls-name-(?<blockingCallName>([^\-]*))-(?<aggregation>.*)/;
const match = matcher.exec(metricKey);
if (!match?.groups) {
return undefined;
}
const metricData: BlockingCallMetricData = {
process: expandProcessName(match.groups.process),
cujName: match.groups.cujName,
blockingCallName: match.groups.blockingCallName,
aggregation: match.groups.aggregation,
};
return metricData;
}
/**
* Adds the debug tracks for Blocking Call metrics
*
* @param {BlockingCallMetricData} metricData Parsed metric data for the cuj scoped jank
* @param {Trace} ctx PluginContextTrace for trace related properties and methods
* @returns {void} Adds one track for Jank CUJ slice and one for Janky CUJ frames
*/
public addMetricTrack(metricData: BlockingCallMetricData, ctx: Trace): void {
this.pinSingleCuj(ctx, metricData);
const config = this.blockingCallTrackConfig(metricData);
addDebugSliceTrack({trace: ctx, ...config});
}
private pinSingleCuj(ctx: Trace, metricData: BlockingCallMetricData) {
const trackName = `Jank CUJ: ${metricData.cujName}`;
addJankCUJDebugTrack(ctx, trackName, metricData.cujName);
}
private blockingCallTrackConfig(metricData: BlockingCallMetricData) {
const cuj = metricData.cujName;
const processName = metricData.process;
const blockingCallName = metricData.blockingCallName;
// TODO: b/296349525 - Migrate jank tables from run metrics to stdlib
const blockingCallDuringCujQuery = `
SELECT name, ts, dur
FROM main_thread_slices_scoped_to_cujs
WHERE process_name = "${processName}"
AND cuj_name = "${cuj}"
AND name = "${blockingCallName}"
`;
const trackName = 'Blocking calls in ' + processName;
return {
data: {
sqlSource: blockingCallDuringCujQuery,
columns: ['name', 'ts', 'dur'],
},
columns: {ts: 'ts', dur: 'dur', name: 'name'},
argColumns: ['name', 'ts', 'dur'],
trackName,
};
}
}
export const pinBlockingCallHandlerInstance = new BlockingCallMetricHandler();