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 '../../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( 74 descriptor: unknown, 75): descriptor is DataSourceDescriptor { 76 if (descriptor instanceof Object) { 77 return (descriptor as DataSourceDescriptor).name !== undefined; 78 } 79 return false; 80} 81 82class AtraceAppsList implements m.ClassComponent { 83 view() { 84 if (globals.state.recordConfig.allAtraceApps) { 85 return m('div'); 86 } 87 88 return m(Textarea, { 89 placeholder: 90 'Apps to profile, one per line, e.g.:\n' + 91 'com.android.phone\n' + 92 'lmkd\n' + 93 'com.android.nfc', 94 cssClass: '.record-apps-list', 95 set: (cfg, val) => (cfg.atraceApps = val), 96 get: (cfg) => cfg.atraceApps, 97 } as TextareaAttrs); 98 } 99} 100 101export class AndroidSettings 102 implements m.ClassComponent<RecordingSectionAttrs> 103{ 104 view({attrs}: m.CVnode<RecordingSectionAttrs>) { 105 let atraceCategories = DEFAULT_ATRACE_CATEGORIES; 106 for (const dataSource of attrs.dataSources) { 107 if ( 108 dataSource.name !== 'linux.ftrace' || 109 !isDataSourceDescriptor(dataSource.descriptor) 110 ) { 111 continue; 112 } 113 const atraces = dataSource.descriptor.ftraceDescriptor?.atraceCategories; 114 if (!atraces || atraces.length === 0) { 115 break; 116 } 117 118 atraceCategories = new Map<string, string>(); 119 for (const atrace of atraces) { 120 if (atrace.name) { 121 atraceCategories.set(atrace.name, atrace.description || ''); 122 } 123 } 124 } 125 126 return m( 127 `.record-section${attrs.cssClass}`, 128 m( 129 Probe, 130 { 131 title: 'Atrace userspace annotations', 132 img: 'rec_atrace.png', 133 descr: `Enables C++ / Java codebase annotations (ATRACE_BEGIN() / 134 os.Trace())`, 135 setEnabled: (cfg, val) => (cfg.atrace = val), 136 isEnabled: (cfg) => cfg.atrace, 137 } as ProbeAttrs, 138 m(Dropdown, { 139 title: 'Categories', 140 cssClass: '.multicolumn.atrace-categories', 141 options: atraceCategories, 142 set: (cfg, val) => (cfg.atraceCats = val), 143 get: (cfg) => cfg.atraceCats, 144 } as DropdownAttrs), 145 m(Toggle, { 146 title: 'Record events from all Android apps and services', 147 descr: '', 148 setEnabled: (cfg, val) => (cfg.allAtraceApps = val), 149 isEnabled: (cfg) => cfg.allAtraceApps, 150 } as ToggleAttrs), 151 m(AtraceAppsList), 152 ), 153 m( 154 Probe, 155 { 156 title: 'Event log (logcat)', 157 img: 'rec_logcat.png', 158 descr: `Streams the event log into the trace. If no buffer filter is 159 specified, all buffers are selected.`, 160 setEnabled: (cfg, val) => (cfg.androidLogs = val), 161 isEnabled: (cfg) => cfg.androidLogs, 162 } as ProbeAttrs, 163 m(Dropdown, { 164 title: 'Buffers', 165 cssClass: '.multicolumn', 166 options: LOG_BUFFERS, 167 set: (cfg, val) => (cfg.androidLogBuffers = val), 168 get: (cfg) => cfg.androidLogBuffers, 169 } as DropdownAttrs), 170 ), 171 m(Probe, { 172 title: 'Frame timeline', 173 img: 'rec_frame_timeline.png', 174 descr: `Records expected/actual frame timings from surface_flinger. 175 Requires Android 12 (S) or above.`, 176 setEnabled: (cfg, val) => (cfg.androidFrameTimeline = val), 177 isEnabled: (cfg) => cfg.androidFrameTimeline, 178 } as ProbeAttrs), 179 m(Probe, { 180 title: 'Game intervention list', 181 img: '', 182 descr: `List game modes and interventions. 183 Requires Android 13 (T) or above.`, 184 setEnabled: (cfg, val) => (cfg.androidGameInterventionList = val), 185 isEnabled: (cfg) => cfg.androidGameInterventionList, 186 } as ProbeAttrs), 187 m( 188 Probe, 189 { 190 title: 'Network Tracing', 191 img: '', 192 descr: `Records detailed information on network packets. 193 Requires Android 14 (U) or above.`, 194 setEnabled: (cfg, val) => (cfg.androidNetworkTracing = val), 195 isEnabled: (cfg) => cfg.androidNetworkTracing, 196 } as ProbeAttrs, 197 m(Slider, { 198 title: 'Poll interval', 199 cssClass: '.thin', 200 values: [100, 250, 500, 1000, 2500], 201 unit: 'ms', 202 set: (cfg, val) => (cfg.androidNetworkTracingPollMs = val), 203 get: (cfg) => cfg.androidNetworkTracingPollMs, 204 } as SliderAttrs), 205 ), 206 ); 207 } 208} 209