1// Copyright (C) 2024 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'; 16import {TargetPlatformId} from '../interfaces/target_platform'; 17import {TraceConfigBuilder} from './trace_config_builder'; 18import {RecordPluginSchema, RecordSessionSchema} from '../serialization_schema'; 19 20/** 21 * A sub-page of the Record page. 22 * Each section maps to an entry in the left sidebar of the recording page. 23 * There are three types of subpages. The last two are identical with exception 24 * of the serialization scope. 25 * 1. Probes pages: the ones that are a structured collection of probes that 26 * can be toggled. 27 * 2,3. Session and global pages: they care of their own rendering and 28 * de/serialization. 29 * 2. Session pages serialize their state in the per-session object (e.g. buffer 30 * sizes). This object can be shared with other people when using the share 31 * config feature. 32 * 3. Global pages instead hold onto the "global" state of the plugin, which is 33 * not tied to the specific config of the recording session (e.g. the target 34 * being recorded, the list of saved configs). This state is retained in 35 * localstorage but is NOT shared with others. 36 */ 37export type RecordSubpage = { 38 /** A unique string. This becomes the subpage in the fragment #!/record/xxx */ 39 readonly id: string; 40 41 /** The name of the material-design icon that is displayed on the sidebar. */ 42 readonly icon: string; 43 44 /** The main text displayed in the left sidebar. */ 45 readonly title: string; 46 47 /** The subtitle displayed when hovering over the entry of the sidebar. */ 48 readonly subtitle: string; 49} & ( 50 | { 51 kind: 'PROBES_PAGE'; 52 53 /** The list of probes (togglable entries) for this section. */ 54 readonly probes: ReadonlyArray<RecordProbe>; 55 } 56 | { 57 kind: 'SESSION_PAGE'; 58 render(): m.Children; 59 60 // Save-restore the page state into the JSON object that is saved in 61 // localstorage and shared when sharing a config. 62 serialize(state: RecordSessionSchema): void; 63 deserialize(state: RecordSessionSchema): void; 64 } 65 | { 66 kind: 'GLOBAL_PAGE'; 67 render(): m.Children; 68 69 // Save-restore the page state into the JSON object that is saved in 70 // localstorage. 71 serialize(state: RecordPluginSchema): void; 72 deserialize(state: RecordPluginSchema): void; 73 } 74); 75 76export interface RecordProbe { 77 /** 78 * lower_with_under id. Keep stable, is used for serialization. 79 * This id must be globally unique (not just per-section). 80 */ 81 readonly id: string; 82 83 /** Human readable name. */ 84 readonly title: string; 85 86 /** (optional) decription. */ 87 readonly description?: string; 88 89 /** (optional) file name of a .png file under assets/. */ 90 readonly image?: string; 91 92 /** (optional) Link to documentation (e.g. 'https://docs.perfetto.dev/...') */ 93 readonly docsLink?: string; 94 95 /** (optional). If specified restricts the probe to the given platorms. */ 96 readonly supportedPlatforms?: TargetPlatformId[]; 97 98 /** (optional): a list of settings for the probe (e.g. polling interval). */ 99 readonly settings?: Record<string, ProbeSetting>; 100 101 /** 102 * (optional): a list of probe IDs that will be force-enabled if this probe is 103 * also enabled. 104 */ 105 readonly dependencies?: string[]; 106 107 /** 108 * Generate the TraceConfig for the probe. This happens in vdom-style: every 109 * time we make a change to the probes the RecordingManager starts a blank 110 * TraceConfigBuilder and asks all probes to update its config invoking this 111 * method. 112 */ 113 genConfig(tc: TraceConfigBuilder): void; 114} 115 116/** 117 * The interface to create widgets that change the state of a probe. 118 * The widget is maintains its own state and must be able to de/serialize it. 119 * Realistically you don't want to implment this interface yourself but use one 120 * of the pre-made widgets under ../pages/widgets/, e.g., Slider(). 121 */ 122export interface ProbeSetting { 123 readonly render: () => m.Children; 124 125 // The two methods below are supposed to save/restore the state of the setting 126 // in a JSON-serializable entity (object | number | string | boolean). This is 127 // to support saving configs into localstorage and sharing them. 128 serialize(): unknown; 129 deserialize(state: unknown): void; 130} 131 132export function supportsPlatform( 133 probe: RecordProbe, 134 platform: TargetPlatformId, 135): boolean { 136 return ( 137 probe.supportedPlatforms === undefined || 138 probe.supportedPlatforms.includes(platform) 139 ); 140} 141