1// Copyright (C) 2018 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 * as m from 'mithril'; 16 17import {assertExists} from '../base/logging'; 18import {Actions} from '../common/actions'; 19import {HttpRpcEngine, RPC_URL} from '../common/http_rpc_engine'; 20import {StatusResult} from '../common/protos'; 21import * as version from '../gen/perfetto_version'; 22import {perfetto} from '../gen/protos'; 23 24import {globals} from './globals'; 25import {showModal} from './modal'; 26 27const CURRENT_API_VERSION = perfetto.protos.TraceProcessorApiVersion 28 .TRACE_PROCESSOR_CURRENT_API_VERSION; 29 30const PROMPT = `Trace Processor Native Accelerator detected on ${RPC_URL} with: 31$loadedTraceName 32 33YES, use loaded trace: 34Will load from the current state of Trace Processor. If you did run 35trace_processor_shell --httpd file.pftrace this is likely what you want. 36 37YES, but reset state: 38Use this if you want to open another trace but still use the 39accelerator. This is the equivalent of killing and restarting 40trace_processor_shell --httpd. 41 42NO, Use builtin WASM: 43Will not use the accelerator in this tab. 44 45Using the native accelerator has some minor caveats: 46- Only one tab can be using the accelerator. 47- Sharing, downloading and conversion-to-legacy aren't supported. 48- You may encounter UI errors if the Trace Processor version you are using is 49too old. Get the latest version from get.perfetto.dev/trace_processor. 50`; 51 52 53const MSG_TOO_OLD = `The Trace Processor instance on ${RPC_URL} is too old. 54 55This UI requires TraceProcessor features that are not present in the 56Trace Processor native accelerator you are currently running. 57If you continue, this is almost surely going to cause UI failures. 58 59Please update your local Trace Processor binary: 60 61curl -LO https://get.perfetto.dev/trace_processor 62chmod +x ./trace_processor 63./trace_processor --httpd 64 65UI version: ${version.VERSION} 66TraceProcessor RPC API required: ${CURRENT_API_VERSION} or higher 67 68TraceProcessor version: $tpVersion 69RPC API: $tpApi 70`; 71 72let forceUseOldVersion = false; 73 74// Try to connect to the external Trace Processor HTTP RPC accelerator (if 75// available, often it isn't). If connected it will populate the 76// |httpRpcState| in the frontend local state. In turn that will show the UI 77// chip in the sidebar. trace_controller.ts will repeat this check before 78// trying to load a new trace. We do this ahead of time just to have a 79// consistent UX (i.e. so that the user can tell if the RPC is working without 80// having to open a trace). 81export async function CheckHttpRpcConnection(): Promise<void> { 82 const state = await HttpRpcEngine.checkConnection(); 83 globals.frontendLocalState.setHttpRpcState(state); 84 if (!state.connected) return; 85 const tpStatus = assertExists(state.status); 86 87 if (tpStatus.apiVersion < CURRENT_API_VERSION) { 88 await showDialogTraceProcessorTooOld(tpStatus); 89 if (!forceUseOldVersion) return; 90 } 91 92 if (tpStatus.loadedTraceName) { 93 // If a trace is already loaded in the trace processor (e.g., the user 94 // launched trace_processor_shell -D trace_file.pftrace), prompt the user to 95 // initialize the UI with the already-loaded trace. 96 return showDialogToUsePreloadedTrace(tpStatus); 97 } 98} 99 100async function showDialogTraceProcessorTooOld(tpStatus: StatusResult) { 101 return showModal({ 102 title: 'Your Trace Processor binary is outdated', 103 content: 104 m('.modal-pre', 105 MSG_TOO_OLD.replace('$tpVersion', tpStatus.humanReadableVersion) 106 .replace('$tpApi', `${tpStatus.apiVersion}`)), 107 buttons: [ 108 { 109 text: 'Use builtin Wasm', 110 primary: true, 111 id: 'tp_old_wasm', 112 action: () => { 113 globals.dispatch( 114 Actions.setNewEngineMode({mode: 'FORCE_BUILTIN_WASM'})); 115 } 116 }, 117 { 118 text: 'Use old version regardless (might crash)', 119 primary: false, 120 id: 'tp_old_cont', 121 action: () => { 122 forceUseOldVersion = true; 123 } 124 }, 125 ], 126 }); 127} 128 129async function showDialogToUsePreloadedTrace(tpStatus: StatusResult) { 130 return showModal({ 131 title: 'Use Trace Processor Native Acceleration?', 132 content: 133 m('.modal-pre', 134 PROMPT.replace('$loadedTraceName', tpStatus.loadedTraceName)), 135 buttons: [ 136 { 137 text: 'YES, use loaded trace', 138 primary: true, 139 id: 'rpc_load', 140 action: () => { 141 globals.dispatch(Actions.openTraceFromHttpRpc({})); 142 } 143 }, 144 { 145 text: 'YES, but reset state', 146 primary: false, 147 id: 'rpc_reset', 148 action: () => {} 149 }, 150 { 151 text: 'NO, Use builtin Wasm', 152 primary: false, 153 id: 'rpc_force_wasm', 154 action: () => { 155 globals.dispatch( 156 Actions.setNewEngineMode({mode: 'FORCE_BUILTIN_WASM'})); 157 } 158 }, 159 ], 160 }); 161} 162