blob: 282ecc8aaef2b6bf7f9e45ecf9d3ac08e866612e [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 m from 'mithril';
import {BigintMath} from '../base/bigint_math';
import {sqliteString} from '../base/string_utils';
import {duration, time} from '../base/time';
import {exists} from '../base/utils';
import {Anchor} from '../widgets/anchor';
import {MenuItem, PopupMenu2} from '../widgets/menu';
import {Section} from '../widgets/section';
import {SqlRef} from '../widgets/sql_ref';
import {Tree, TreeNode} from '../widgets/tree';
import {addTab} from './bottom_tab';
import {globals} from './globals';
import {SliceDetails} from './sql/slice';
import {
BreakdownByThreadState,
BreakdownByThreadStateTreeNode,
} from './sql/thread_state';
import {SqlTableTab} from './sql_table/tab';
import {SqlTables} from './sql_table/well_known_tables';
import {getProcessName, getThreadName} from './thread_and_process_info';
import {DurationWidget} from './widgets/duration';
import {Timestamp} from './widgets/timestamp';
function computeDuration(ts: time, dur: duration): m.Children {
if (dur === -1n) {
const minDuration = globals.state.traceTime.end - ts;
return [m(DurationWidget, {dur: minDuration}), ' (Did not end)'];
} else {
return m(DurationWidget, {dur});
}
}
// Renders a widget storing all of the generic details for a slice from the
// slice table.
export function renderDetails(
slice: SliceDetails, durationBreakdown?: BreakdownByThreadState) {
return m(
Section,
{title: 'Details'},
m(
Tree,
m(TreeNode, {
left: 'Name',
right: m(
PopupMenu2,
{
trigger: m(Anchor, slice.name),
},
m(MenuItem, {
label: 'Slices with the same name',
onclick: () => {
addTab({
kind: SqlTableTab.kind,
config: {
table: SqlTables.slice,
displayName: 'slice',
filters: [`name = ${sqliteString(slice.name)}`],
},
});
},
}),
),
}),
m(TreeNode, {
left: 'Category',
right: !slice.category || slice.category === '[NULL]' ?
'N/A' :
slice.category,
}),
m(TreeNode, {
left: 'Start time',
right: m(Timestamp, {ts: slice.ts}),
}),
exists(slice.absTime) &&
m(TreeNode, {left: 'Absolute Time', right: slice.absTime}),
m(
TreeNode,
{
left: 'Duration',
right: computeDuration(slice.ts, slice.dur),
},
exists(durationBreakdown) && slice.dur > 0 &&
m(BreakdownByThreadStateTreeNode, {
data: durationBreakdown,
dur: slice.dur,
}),
),
renderThreadDuration(slice),
slice.thread && m(TreeNode, {
left: 'Thread',
right: getThreadName(slice.thread),
}),
slice.process && m(TreeNode, {
left: 'Process',
right: getProcessName(slice.process),
}),
slice.process && exists(slice.process.uid) && m(TreeNode, {
left: 'User ID',
right: slice.process.uid,
}),
slice.process && slice.process.packageName && m(TreeNode, {
left: 'Package name',
right: slice.process.packageName,
}),
slice.process && exists(slice.process.versionCode) && m(TreeNode, {
left: 'Version code',
right: slice.process.versionCode,
}),
m(TreeNode, {
left: 'SQL ID',
right: m(SqlRef, {table: 'slice', id: slice.id}),
}),
));
}
function renderThreadDuration(sliceInfo: SliceDetails) {
if (exists(sliceInfo.threadTs) && exists(sliceInfo.threadDur)) {
// If we have valid thread duration, also display a percentage of
// |threadDur| compared to |dur|.
const ratio = BigintMath.ratio(sliceInfo.threadDur, sliceInfo.dur);
const threadDurFractionSuffix =
sliceInfo.threadDur === -1n ? '' : ` (${(ratio * 100).toFixed(2)}%)`;
return m(TreeNode, {
left: 'Thread duration',
right: [
computeDuration(sliceInfo.threadTs, sliceInfo.threadDur),
threadDurFractionSuffix,
],
});
} else {
return undefined;
}
}