xref: /aosp_15_r20/external/perfetto/ui/src/plugins/dev.perfetto.RecordTrace/recordingV2/recording_utils.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2022 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
15export const RECORDING_MODAL_DIALOG_KEY = 'recording_target';
16
17// Begin Websocket ////////////////////////////////////////////////////////
18
19export const WEBSOCKET_UNABLE_TO_CONNECT =
20  'Unable to connect to device via websocket.';
21
22// https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1
23export const WEBSOCKET_CLOSED_ABNORMALLY_CODE = 1006;
24
25// The messages read by the adb server have their length prepended in hex.
26// This method adds the length at the beginning of the message.
27// Example: 'host:track-devices' -> '0012host:track-devices'
28// go/codesearch/aosp-android11/system/core/adb/SERVICES.TXT
29export function buildAbdWebsocketCommand(cmd: string) {
30  const hdr = cmd.length.toString(16).padStart(4, '0');
31  return hdr + cmd;
32}
33
34// Sample user agent for Chrome on Mac OS:
35// 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36
36// (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
37export function isMacOs(userAgent: string) {
38  return userAgent.toLowerCase().includes(' mac os ');
39}
40
41// Sample user agent for Chrome on Linux:
42// Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)
43// Chrome/105.0.0.0 Safari/537.36
44export function isLinux(userAgent: string) {
45  return userAgent.toLowerCase().includes(' linux ');
46}
47// Sample user agent for Chrome on Windows:
48// Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
49// like Gecko) Chrome/125.0.0.0 Safari/537.36
50export function isWindows(userAgent: string) {
51  return userAgent.toLowerCase().includes('windows ');
52}
53
54// Sample user agent for Chrome on Chrome OS:
55// "Mozilla/5.0 (X11; CrOS x86_64 14816.99.0) AppleWebKit/537.36
56// (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
57// This condition is wider, in the unlikely possibility of different casing,
58export function isCrOS(userAgent: string) {
59  return userAgent.toLowerCase().includes(' cros ');
60}
61
62// End Websocket //////////////////////////////////////////////////////////
63
64// Begin Adb //////////////////////////////////////////////////////////////
65
66export const BINARY_PUSH_FAILURE = 'BinaryPushFailure';
67export const BINARY_PUSH_UNKNOWN_RESPONSE = 'BinaryPushUnknownResponse';
68
69// In case the device doesn't have the tracebox, we upload the latest version
70// to this path.
71export const TRACEBOX_DEVICE_PATH = '/data/local/tmp/tracebox';
72
73// Experimentally, this takes 900ms on the first fetch and 20-30ms after
74// because of caching.
75export const TRACEBOX_FETCH_TIMEOUT = 30000;
76
77// Message shown to the user when they need to allow authentication on the
78// device in order to connect.
79export const ALLOW_USB_DEBUGGING =
80  'Please allow USB debugging on device and try again.';
81
82// If the Android device has the tracing service on it (from API version 29),
83// then we can connect to this consumer socket.
84export const DEFAULT_TRACED_CONSUMER_SOCKET_PATH =
85  'localfilesystem:/dev/socket/traced_consumer';
86
87// If the Android device does not have the tracing service on it (before API
88// version 29), we will have to push the tracebox on the device. Then, we
89// can connect to this consumer socket (using it does not require system admin
90// privileges).
91export const CUSTOM_TRACED_CONSUMER_SOCKET_PATH =
92  'localabstract:traced_consumer';
93
94// End Adb /////////////////////////////////////////////////////////////////
95
96// Begin Webusb ///////////////////////////////////////////////////////////
97
98export const NO_DEVICE_SELECTED = 'No device selected.';
99
100export interface UsbInterfaceAndEndpoint {
101  readonly configurationValue: number;
102  readonly usbInterfaceNumber: number;
103  readonly endpoints: USBEndpoint[];
104}
105
106export const ADB_DEVICE_FILTER = {
107  classCode: 255, // USB vendor specific code
108  subclassCode: 66, // Android vendor specific subclass
109  protocolCode: 1, // Adb protocol
110};
111
112export function findInterfaceAndEndpoint(
113  device: USBDevice,
114): UsbInterfaceAndEndpoint | undefined {
115  const adbDeviceFilter = ADB_DEVICE_FILTER;
116  for (const config of device.configurations) {
117    for (const interface_ of config.interfaces) {
118      for (const alt of interface_.alternates) {
119        if (
120          alt.interfaceClass === adbDeviceFilter.classCode &&
121          alt.interfaceSubclass === adbDeviceFilter.subclassCode &&
122          alt.interfaceProtocol === adbDeviceFilter.protocolCode
123        ) {
124          return {
125            configurationValue: config.configurationValue,
126            usbInterfaceNumber: interface_.interfaceNumber,
127            endpoints: alt.endpoints,
128          };
129        } // if (alternate)
130      } // for (interface.alternates)
131    } // for (configuration.interfaces)
132  } // for (configurations)
133
134  return undefined;
135}
136
137// End Webusb //////////////////////////////////////////////////////////////
138
139// Begin Chrome ///////////////////////////////////////////////////////////
140
141export const EXTENSION_ID = 'lfmkphfpdbjijhpomgecfikhfohaoine';
142export const EXTENSION_URL = `https://chrome.google.com/webstore/detail/perfetto-ui/${EXTENSION_ID}`;
143export const EXTENSION_NAME = 'Chrome extension';
144export const EXTENSION_NOT_INSTALLED = `To trace Chrome from the Perfetto UI, you need to install our
145    ${EXTENSION_URL} and then reload this page.`;
146
147export const MALFORMED_EXTENSION_MESSAGE = 'Malformed extension message.';
148export const BUFFER_USAGE_NOT_ACCESSIBLE = 'Buffer usage not accessible';
149export const BUFFER_USAGE_INCORRECT_FORMAT =
150  'The buffer usage data has am incorrect format';
151
152// End Chrome /////////////////////////////////////////////////////////////
153
154// Begin Traced //////////////////////////////////////////////////////////
155
156export const RECORDING_IN_PROGRESS = 'Recording in progress';
157export const PARSING_UNKNWON_REQUEST_ID = 'Unknown request id';
158export const PARSING_UNABLE_TO_DECODE_METHOD = 'Unable to decode method';
159export const PARSING_UNRECOGNIZED_PORT = 'Unrecognized consumer port response';
160export const PARSING_UNRECOGNIZED_MESSAGE = 'Unrecognized frame message';
161
162// End Traced ///////////////////////////////////////////////////////////
163