1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {TimeSpan} from '../base/time'; 16import {exists} from '../base/utils'; 17import {maybeMachineLabel} from '../base/multi_machine_trace'; 18import {Trace} from './trace'; 19 20export function getTrackName( 21 args: Partial<{ 22 name: string | null; 23 utid: number | null; 24 processName: string | null; 25 pid: number | null; 26 threadName: string | null; 27 tid: number | null; 28 upid: number | null; 29 userName: string | null; 30 uid: number | null; 31 kind: string; 32 threadTrack: boolean; 33 uidTrack: boolean; 34 machine: number | null; 35 }>, 36) { 37 const { 38 name, 39 upid, 40 utid, 41 processName, 42 threadName, 43 pid, 44 tid, 45 userName, 46 uid, 47 kind, 48 threadTrack, 49 uidTrack, 50 machine, 51 } = args; 52 53 const hasName = name !== undefined && name !== null && name !== '[NULL]'; 54 const hasUpid = upid !== undefined && upid !== null; 55 const hasUtid = utid !== undefined && utid !== null; 56 const hasProcessName = processName !== undefined && processName !== null; 57 const hasThreadName = threadName !== undefined && threadName !== null; 58 const hasUserName = userName !== undefined && userName !== null; 59 const hasTid = tid !== undefined && tid !== null; 60 const hasPid = pid !== undefined && pid !== null; 61 const hasUid = uid !== undefined && uid !== null; 62 const hasKind = kind !== undefined; 63 const isThreadTrack = threadTrack !== undefined && threadTrack; 64 const isUidTrack = uidTrack !== undefined && uidTrack; 65 66 // If we don't have any useful information (better than 67 // upid/utid) we show the track kind to help with tracking 68 // down where this is coming from. 69 const kindSuffix = hasKind ? ` (${kind})` : ''; 70 const machineLabel = maybeMachineLabel(machine ?? undefined); 71 72 if (isThreadTrack && hasName && hasTid) { 73 return `${name} (${tid})`; 74 } else if (isUidTrack && hasName && hasUserName) { 75 return `${name} (${userName})`; 76 } else if (isUidTrack && hasName && hasUid) { 77 return `${name} ${uid}`; 78 } else if (hasName) { 79 return `${name}`; 80 } else if (hasThreadName && hasTid) { 81 return `${threadName} ${tid}`; 82 } else if (hasTid) { 83 return `Thread ${tid}`; 84 } else if (hasUpid && hasPid && hasProcessName) { 85 return `${processName} ${pid}${machineLabel}`; 86 } else if (hasUpid && hasPid) { 87 return `Process ${pid}${machineLabel}`; 88 } else if (hasUpid) { 89 return `upid: ${upid}${kindSuffix}`; 90 } else if (hasUtid) { 91 return `utid: ${utid}${kindSuffix}`; 92 } else if (hasUid) { 93 return `uid: ${uid}${kindSuffix}`; 94 } else if (hasKind) { 95 return `Unnamed ${kind}`; 96 } 97 return 'Unknown'; 98} 99 100export function getThreadOrProcUri( 101 upid: number | null, 102 utid: number | null, 103): string { 104 if (exists(upid)) { 105 return `/process_${upid}`; 106 } else if (exists(utid)) { 107 return `/thread_${utid}`; 108 } else { 109 throw new Error('No upid or utid defined...'); 110 } 111} 112 113export function getThreadUriPrefix(upid: number | null, utid: number): string { 114 if (exists(upid)) { 115 return `/process_${upid}/thread_${utid}`; 116 } else { 117 return `/thread_${utid}`; 118 } 119} 120 121// Returns the time span of the current selection, or the visible window if 122// there is no current selection. 123export async function getTimeSpanOfSelectionOrVisibleWindow( 124 trace: Trace, 125): Promise<TimeSpan> { 126 const range = await trace.selection.findTimeRangeOfSelection(); 127 if (exists(range)) { 128 return new TimeSpan(range.start, range.end); 129 } else { 130 return trace.timeline.visibleWindow.toTimeSpan(); 131 } 132} 133