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 15import m from 'mithril'; 16 17import {DataSourceDescriptor} from '../../common/protos'; 18import {globals} from '../globals'; 19import { 20 Dropdown, 21 DropdownAttrs, 22 Probe, 23 ProbeAttrs, 24 Slider, 25 SliderAttrs, 26 Textarea, 27 TextareaAttrs, 28 Toggle, 29 ToggleAttrs, 30} from '../record_widgets'; 31 32import {RecordingSectionAttrs} from './recording_sections'; 33 34const LOG_BUFFERS = new Map<string, string>(); 35LOG_BUFFERS.set('LID_CRASH', 'Crash'); 36LOG_BUFFERS.set('LID_DEFAULT', 'Main'); 37LOG_BUFFERS.set('LID_EVENTS', 'Binary events'); 38LOG_BUFFERS.set('LID_KERNEL', 'Kernel'); 39LOG_BUFFERS.set('LID_RADIO', 'Radio'); 40LOG_BUFFERS.set('LID_SECURITY', 'Security'); 41LOG_BUFFERS.set('LID_STATS', 'Stats'); 42LOG_BUFFERS.set('LID_SYSTEM', 'System'); 43 44const DEFAULT_ATRACE_CATEGORIES = new Map<string, string>(); 45DEFAULT_ATRACE_CATEGORIES.set('adb', 'ADB'); 46DEFAULT_ATRACE_CATEGORIES.set('aidl', 'AIDL calls'); 47DEFAULT_ATRACE_CATEGORIES.set('am', 'Activity Manager'); 48DEFAULT_ATRACE_CATEGORIES.set('audio', 'Audio'); 49DEFAULT_ATRACE_CATEGORIES.set('binder_driver', 'Binder Kernel driver'); 50DEFAULT_ATRACE_CATEGORIES.set('binder_lock', 'Binder global lock trace'); 51DEFAULT_ATRACE_CATEGORIES.set('bionic', 'Bionic C library'); 52DEFAULT_ATRACE_CATEGORIES.set('camera', 'Camera'); 53DEFAULT_ATRACE_CATEGORIES.set('dalvik', 'ART & Dalvik'); 54DEFAULT_ATRACE_CATEGORIES.set('database', 'Database'); 55DEFAULT_ATRACE_CATEGORIES.set('gfx', 'Graphics'); 56DEFAULT_ATRACE_CATEGORIES.set('hal', 'Hardware Modules'); 57DEFAULT_ATRACE_CATEGORIES.set('input', 'Input'); 58DEFAULT_ATRACE_CATEGORIES.set('network', 'Network'); 59DEFAULT_ATRACE_CATEGORIES.set('nnapi', 'Neural Network API'); 60DEFAULT_ATRACE_CATEGORIES.set('pm', 'Package Manager'); 61DEFAULT_ATRACE_CATEGORIES.set('power', 'Power Management'); 62DEFAULT_ATRACE_CATEGORIES.set('res', 'Resource Loading'); 63DEFAULT_ATRACE_CATEGORIES.set('rro', 'Resource Overlay'); 64DEFAULT_ATRACE_CATEGORIES.set('rs', 'RenderScript'); 65DEFAULT_ATRACE_CATEGORIES.set('sm', 'Sync Manager'); 66DEFAULT_ATRACE_CATEGORIES.set('ss', 'System Server'); 67DEFAULT_ATRACE_CATEGORIES.set('vibrator', 'Vibrator'); 68DEFAULT_ATRACE_CATEGORIES.set('video', 'Video'); 69DEFAULT_ATRACE_CATEGORIES.set('view', 'View System'); 70DEFAULT_ATRACE_CATEGORIES.set('webview', 'WebView'); 71DEFAULT_ATRACE_CATEGORIES.set('wm', 'Window Manager'); 72 73function isDataSourceDescriptor(descriptor: unknown): 74 descriptor is DataSourceDescriptor { 75 if (descriptor instanceof Object) { 76 return (descriptor as DataSourceDescriptor).name !== undefined; 77 } 78 return false; 79} 80 81class AtraceAppsList implements m.ClassComponent { 82 view() { 83 if (globals.state.recordConfig.allAtraceApps) { 84 return m('div'); 85 } 86 87 return m(Textarea, { 88 placeholder: 'Apps to profile, one per line, e.g.:\n' + 89 'com.android.phone\n' + 90 'lmkd\n' + 91 'com.android.nfc', 92 cssClass: '.atrace-apps-list', 93 set: (cfg, val) => cfg.atraceApps = val, 94 get: (cfg) => cfg.atraceApps, 95 } as TextareaAttrs); 96 } 97} 98 99export class AndroidSettings implements 100 m.ClassComponent<RecordingSectionAttrs> { 101 view({attrs}: m.CVnode<RecordingSectionAttrs>) { 102 let atraceCategories = DEFAULT_ATRACE_CATEGORIES; 103 for (const dataSource of attrs.dataSources) { 104 if (dataSource.name !== 'linux.ftrace' || 105 !isDataSourceDescriptor(dataSource.descriptor)) { 106 continue; 107 } 108 const atraces = dataSource.descriptor.ftraceDescriptor?.atraceCategories; 109 if (!atraces || atraces.length === 0) { 110 break; 111 } 112 113 atraceCategories = new Map<string, string>(); 114 for (const atrace of atraces) { 115 if (atrace.name) { 116 atraceCategories.set(atrace.name, atrace.description || ''); 117 } 118 } 119 } 120 121 return m( 122 `.record-section${attrs.cssClass}`, 123 m(Probe, 124 { 125 title: 'Atrace userspace annotations', 126 img: 'rec_atrace.png', 127 descr: `Enables C++ / Java codebase annotations (ATRACE_BEGIN() / 128 os.Trace())`, 129 setEnabled: (cfg, val) => cfg.atrace = val, 130 isEnabled: (cfg) => cfg.atrace, 131 } as ProbeAttrs, 132 m(Dropdown, { 133 title: 'Categories', 134 cssClass: '.multicolumn.atrace-categories', 135 options: atraceCategories, 136 set: (cfg, val) => cfg.atraceCats = val, 137 get: (cfg) => cfg.atraceCats, 138 } as DropdownAttrs), 139 m(Toggle, { 140 title: 'Record events from all Android apps and services', 141 descr: '', 142 setEnabled: (cfg, val) => cfg.allAtraceApps = val, 143 isEnabled: (cfg) => cfg.allAtraceApps, 144 } as ToggleAttrs), 145 m(AtraceAppsList)), 146 m(Probe, 147 { 148 title: 'Event log (logcat)', 149 img: 'rec_logcat.png', 150 descr: `Streams the event log into the trace. If no buffer filter is 151 specified, all buffers are selected.`, 152 setEnabled: (cfg, val) => cfg.androidLogs = val, 153 isEnabled: (cfg) => cfg.androidLogs, 154 } as ProbeAttrs, 155 m(Dropdown, { 156 title: 'Buffers', 157 cssClass: '.multicolumn', 158 options: LOG_BUFFERS, 159 set: (cfg, val) => cfg.androidLogBuffers = val, 160 get: (cfg) => cfg.androidLogBuffers, 161 } as DropdownAttrs)), 162 m(Probe, { 163 title: 'Frame timeline', 164 img: 'rec_frame_timeline.png', 165 descr: `Records expected/actual frame timings from surface_flinger. 166 Requires Android 12 (S) or above.`, 167 setEnabled: (cfg, val) => cfg.androidFrameTimeline = val, 168 isEnabled: (cfg) => cfg.androidFrameTimeline, 169 } as ProbeAttrs), 170 m(Probe, { 171 title: 'Game intervention list', 172 img: '', 173 descr: `List game modes and interventions. 174 Requires Android 13 (T) or above.`, 175 setEnabled: (cfg, val) => cfg.androidGameInterventionList = val, 176 isEnabled: (cfg) => cfg.androidGameInterventionList, 177 } as ProbeAttrs), 178 m(Probe, 179 { 180 title: 'Network Tracing', 181 img: '', 182 descr: `Records detailed information on network packets. 183 Requires Android 14 (U) or above.`, 184 setEnabled: (cfg, val) => cfg.androidNetworkTracing = val, 185 isEnabled: (cfg) => cfg.androidNetworkTracing, 186 } as ProbeAttrs, 187 m(Slider, { 188 title: 'Poll interval', 189 cssClass: '.thin', 190 values: [100, 250, 500, 1000, 2500], 191 unit: 'ms', 192 set: (cfg, val) => cfg.androidNetworkTracingPollMs = val, 193 get: (cfg) => cfg.androidNetworkTracingPollMs, 194 } as SliderAttrs))); 195 } 196} 197