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 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 {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} 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 action: () => { 112 globals.dispatch( 113 Actions.setNewEngineMode({mode: 'FORCE_BUILTIN_WASM'})); 114 }, 115 }, 116 { 117 text: 'Use old version regardless (might crash)', 118 primary: false, 119 action: () => { 120 forceUseOldVersion = true; 121 }, 122 }, 123 ], 124 }); 125} 126 127async function showDialogToUsePreloadedTrace(tpStatus: StatusResult) { 128 return showModal({ 129 title: 'Use Trace Processor Native Acceleration?', 130 content: 131 m('.modal-pre', 132 PROMPT.replace('$loadedTraceName', tpStatus.loadedTraceName)), 133 buttons: [ 134 { 135 text: 'YES, use loaded trace', 136 primary: true, 137 action: () => { 138 globals.dispatch(Actions.openTraceFromHttpRpc({})); 139 }, 140 }, 141 { 142 text: 'YES, but reset state', 143 }, 144 { 145 text: 'NO, Use builtin Wasm', 146 action: () => { 147 globals.dispatch( 148 Actions.setNewEngineMode({mode: 'FORCE_BUILTIN_WASM'})); 149 }, 150 }, 151 ], 152 }); 153} 154