1// Copyright (C) 2019 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use size 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 * as m from 'mithril'; 16 17import {drawDoubleHeadedArrow} from '../common/canvas_utils'; 18import {translateState} from '../common/thread_state'; 19import {timeToCode} from '../common/time'; 20 21import {globals} from './globals'; 22import {Panel, PanelSize} from './panel'; 23 24interface SliceDetailsPanelAttrs { 25 utid: number; 26} 27 28export class SliceDetailsPanel extends Panel<SliceDetailsPanelAttrs> { 29 view({attrs}: m.CVnode<SliceDetailsPanelAttrs>) { 30 const threadInfo = globals.threads.get(attrs.utid); 31 const sliceInfo = globals.sliceDetails; 32 if (threadInfo && sliceInfo.ts && sliceInfo.dur) { 33 return m( 34 '.details-panel', 35 m('.details-panel-heading', `Slice Details:`), 36 m('.details-table', [m('table', [ 37 m('tr', m('th', `PID`), m('td', `${threadInfo.pid}`)), 38 m('tr', 39 m('th', `Process name`), 40 m('td', `${threadInfo.procName}`)), 41 m('tr', m('th', `TID`), m('td', `${threadInfo.tid}`)), 42 m('tr', 43 m('th', `Thread name`), 44 m('td', `${threadInfo.threadName}`)), 45 m('tr', 46 m('th', `Start time`), 47 m('td', `${timeToCode(sliceInfo.ts)}`)), 48 m('tr', 49 m('th', `Duration`), 50 m('td', `${timeToCode(sliceInfo.dur)}`)), 51 m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)), 52 m('tr', 53 m('th', `End State`), 54 m('td', `${translateState(sliceInfo.endState)}`)) 55 ])], )); 56 } 57 else { 58 return m( 59 '.details-panel', m('.details-panel-heading', `Slice Details:`, )); 60 } 61} 62renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { 63 const details = globals.sliceDetails; 64 // Show expanded details on the scheduling of the currently selected slice. 65 if (details.wakeupTs && details.wakerUtid !== undefined) { 66 const threadInfo = globals.threads.get(details.wakerUtid); 67 // Draw separation line. 68 ctx.fillStyle = '#3c4b5d'; 69 ctx.fillRect(size.width / 2, 10, 1, size.height - 10); 70 ctx.font = '16px Google Sans'; 71 ctx.fillText('Scheduling Latency:', size.width / 2 + 30, 30); 72 // Draw diamond and vertical line. 73 const startDraw = {x: size.width / 2 + 30, y: 52}; 74 ctx.beginPath(); 75 ctx.moveTo(startDraw.x, startDraw.y + 28); 76 ctx.fillStyle = 'black'; 77 ctx.lineTo(startDraw.x + 6, startDraw.y + 20); 78 ctx.lineTo(startDraw.x, startDraw.y + 12); 79 ctx.lineTo(startDraw.x - 6, startDraw.y + 20); 80 ctx.fill(); 81 ctx.closePath(); 82 ctx.fillRect(startDraw.x - 1, startDraw.y, 2, 100); 83 84 // Wakeup explanation text. 85 ctx.font = '13px Google Sans'; 86 ctx.fillStyle = '#3c4b5d'; 87 if (threadInfo) { 88 const displayText = 89 `Wakeup @ ${ 90 timeToCode( 91 details.wakeupTs - globals.state.traceTime.startSec) 92 } on CPU ${details.wakerCpu} by`; 93 const processText = `P: ${threadInfo.procName} [${threadInfo.pid}]`; 94 const threadText = `T: ${threadInfo.threadName} [${threadInfo.tid}]`; 95 ctx.fillText(displayText, startDraw.x + 20, startDraw.y + 20); 96 ctx.fillText(processText, startDraw.x + 20, startDraw.y + 37); 97 ctx.fillText(threadText, startDraw.x + 20, startDraw.y + 55); 98 } 99 100 // Draw latency arrow and explanation text. 101 drawDoubleHeadedArrow(ctx, startDraw.x, startDraw.y + 80, 60, true); 102 if (details.ts) { 103 const displayLatency = 104 `Scheduling latency: ${ 105 timeToCode( 106 details.ts - 107 (details.wakeupTs - 108 globals.state.traceTime.startSec)) 109 }`; 110 ctx.fillText(displayLatency, startDraw.x + 70, startDraw.y + 86); 111 const explain1 = 112 'This is the interval from when the task became eligible to run'; 113 const explain2 = 114 '(e.g. because of notifying a wait queue it was suspended on) to'; 115 const explain3 = 'when it started running.'; 116 ctx.font = '10px Google Sans'; 117 ctx.fillText(explain1, startDraw.x + 70, startDraw.y + 86 + 16); 118 ctx.fillText(explain2, startDraw.x + 70, startDraw.y + 86 + 16 + 12); 119 ctx.fillText(explain3, startDraw.x + 70, startDraw.y + 86 + 16 + 24); 120 } 121 } 122} 123} 124