1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2024 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport m from 'mithril'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {copyToClipboard} from '../../base/clipboard'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {Icons} from '../../base/semantic_icons'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {exists} from '../../base/utils'; 19*6dbdd20aSAndroid Build Coastguard Workerimport {addEphemeralTab} from '../details/add_ephemeral_tab'; 20*6dbdd20aSAndroid Build Coastguard Workerimport {getThreadInfo, getThreadName, ThreadInfo} from '../sql_utils/thread'; 21*6dbdd20aSAndroid Build Coastguard Workerimport {Anchor} from '../../widgets/anchor'; 22*6dbdd20aSAndroid Build Coastguard Workerimport {MenuItem, PopupMenu2} from '../../widgets/menu'; 23*6dbdd20aSAndroid Build Coastguard Workerimport {ThreadDetailsTab} from '../details/thread_details_tab'; 24*6dbdd20aSAndroid Build Coastguard Workerimport { 25*6dbdd20aSAndroid Build Coastguard Worker createSqlIdRefRenderer, 26*6dbdd20aSAndroid Build Coastguard Worker sqlIdRegistry, 27*6dbdd20aSAndroid Build Coastguard Worker} from './sql/details/sql_ref_renderer_registry'; 28*6dbdd20aSAndroid Build Coastguard Workerimport {asUtid} from '../sql_utils/core_types'; 29*6dbdd20aSAndroid Build Coastguard Workerimport {Utid} from '../sql_utils/core_types'; 30*6dbdd20aSAndroid Build Coastguard Workerimport {AppImpl} from '../../core/app_impl'; 31*6dbdd20aSAndroid Build Coastguard Worker 32*6dbdd20aSAndroid Build Coastguard Workerexport function showThreadDetailsMenuItem( 33*6dbdd20aSAndroid Build Coastguard Worker utid: Utid, 34*6dbdd20aSAndroid Build Coastguard Worker tid?: number, 35*6dbdd20aSAndroid Build Coastguard Worker): m.Children { 36*6dbdd20aSAndroid Build Coastguard Worker return m(MenuItem, { 37*6dbdd20aSAndroid Build Coastguard Worker icon: Icons.ExternalLink, 38*6dbdd20aSAndroid Build Coastguard Worker label: 'Show thread details', 39*6dbdd20aSAndroid Build Coastguard Worker onclick: () => { 40*6dbdd20aSAndroid Build Coastguard Worker // TODO(primiano): `trace` should be injected, but doing so would require 41*6dbdd20aSAndroid Build Coastguard Worker // an invasive refactoring of most classes in frontend/widgets/sql/*. 42*6dbdd20aSAndroid Build Coastguard Worker const trace = AppImpl.instance.trace; 43*6dbdd20aSAndroid Build Coastguard Worker if (trace === undefined) return; 44*6dbdd20aSAndroid Build Coastguard Worker addEphemeralTab( 45*6dbdd20aSAndroid Build Coastguard Worker 'threadDetails', 46*6dbdd20aSAndroid Build Coastguard Worker new ThreadDetailsTab({ 47*6dbdd20aSAndroid Build Coastguard Worker trace, 48*6dbdd20aSAndroid Build Coastguard Worker utid, 49*6dbdd20aSAndroid Build Coastguard Worker tid, 50*6dbdd20aSAndroid Build Coastguard Worker }), 51*6dbdd20aSAndroid Build Coastguard Worker ); 52*6dbdd20aSAndroid Build Coastguard Worker }, 53*6dbdd20aSAndroid Build Coastguard Worker }); 54*6dbdd20aSAndroid Build Coastguard Worker} 55*6dbdd20aSAndroid Build Coastguard Worker 56*6dbdd20aSAndroid Build Coastguard Workerexport function threadRefMenuItems(info: { 57*6dbdd20aSAndroid Build Coastguard Worker utid: Utid; 58*6dbdd20aSAndroid Build Coastguard Worker name?: string; 59*6dbdd20aSAndroid Build Coastguard Worker tid?: number; 60*6dbdd20aSAndroid Build Coastguard Worker}): m.Children { 61*6dbdd20aSAndroid Build Coastguard Worker // We capture a copy to be able to pass it across async boundary to `onclick`. 62*6dbdd20aSAndroid Build Coastguard Worker const name = info.name; 63*6dbdd20aSAndroid Build Coastguard Worker return [ 64*6dbdd20aSAndroid Build Coastguard Worker exists(name) && 65*6dbdd20aSAndroid Build Coastguard Worker m(MenuItem, { 66*6dbdd20aSAndroid Build Coastguard Worker icon: Icons.Copy, 67*6dbdd20aSAndroid Build Coastguard Worker label: 'Copy thread name', 68*6dbdd20aSAndroid Build Coastguard Worker onclick: () => copyToClipboard(name), 69*6dbdd20aSAndroid Build Coastguard Worker }), 70*6dbdd20aSAndroid Build Coastguard Worker exists(info.tid) && 71*6dbdd20aSAndroid Build Coastguard Worker m(MenuItem, { 72*6dbdd20aSAndroid Build Coastguard Worker icon: Icons.Copy, 73*6dbdd20aSAndroid Build Coastguard Worker label: 'Copy tid', 74*6dbdd20aSAndroid Build Coastguard Worker onclick: () => copyToClipboard(`${info.tid}`), 75*6dbdd20aSAndroid Build Coastguard Worker }), 76*6dbdd20aSAndroid Build Coastguard Worker m(MenuItem, { 77*6dbdd20aSAndroid Build Coastguard Worker icon: Icons.Copy, 78*6dbdd20aSAndroid Build Coastguard Worker label: 'Copy utid', 79*6dbdd20aSAndroid Build Coastguard Worker onclick: () => copyToClipboard(`${info.utid}`), 80*6dbdd20aSAndroid Build Coastguard Worker }), 81*6dbdd20aSAndroid Build Coastguard Worker showThreadDetailsMenuItem(info.utid, info.tid), 82*6dbdd20aSAndroid Build Coastguard Worker ]; 83*6dbdd20aSAndroid Build Coastguard Worker} 84*6dbdd20aSAndroid Build Coastguard Worker 85*6dbdd20aSAndroid Build Coastguard Workerexport function renderThreadRef(info: { 86*6dbdd20aSAndroid Build Coastguard Worker utid: Utid; 87*6dbdd20aSAndroid Build Coastguard Worker name?: string; 88*6dbdd20aSAndroid Build Coastguard Worker tid?: number; 89*6dbdd20aSAndroid Build Coastguard Worker}): m.Children { 90*6dbdd20aSAndroid Build Coastguard Worker return m( 91*6dbdd20aSAndroid Build Coastguard Worker PopupMenu2, 92*6dbdd20aSAndroid Build Coastguard Worker { 93*6dbdd20aSAndroid Build Coastguard Worker trigger: m(Anchor, getThreadName(info)), 94*6dbdd20aSAndroid Build Coastguard Worker }, 95*6dbdd20aSAndroid Build Coastguard Worker threadRefMenuItems(info), 96*6dbdd20aSAndroid Build Coastguard Worker ); 97*6dbdd20aSAndroid Build Coastguard Worker} 98*6dbdd20aSAndroid Build Coastguard Worker 99*6dbdd20aSAndroid Build Coastguard WorkersqlIdRegistry['thread'] = createSqlIdRefRenderer<ThreadInfo>( 100*6dbdd20aSAndroid Build Coastguard Worker async (engine, id) => await getThreadInfo(engine, asUtid(Number(id))), 101*6dbdd20aSAndroid Build Coastguard Worker (data: ThreadInfo) => ({ 102*6dbdd20aSAndroid Build Coastguard Worker value: renderThreadRef(data), 103*6dbdd20aSAndroid Build Coastguard Worker }), 104*6dbdd20aSAndroid Build Coastguard Worker); 105