// Copyright (C) 2022 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import m from 'mithril'; import {DataSourceDescriptor} from '../../common/protos'; import {globals} from '../globals'; import { Dropdown, DropdownAttrs, Probe, ProbeAttrs, Slider, SliderAttrs, Textarea, TextareaAttrs, Toggle, ToggleAttrs, } from '../record_widgets'; import {RecordingSectionAttrs} from './recording_sections'; const LOG_BUFFERS = new Map(); LOG_BUFFERS.set('LID_CRASH', 'Crash'); LOG_BUFFERS.set('LID_DEFAULT', 'Main'); LOG_BUFFERS.set('LID_EVENTS', 'Binary events'); LOG_BUFFERS.set('LID_KERNEL', 'Kernel'); LOG_BUFFERS.set('LID_RADIO', 'Radio'); LOG_BUFFERS.set('LID_SECURITY', 'Security'); LOG_BUFFERS.set('LID_STATS', 'Stats'); LOG_BUFFERS.set('LID_SYSTEM', 'System'); const DEFAULT_ATRACE_CATEGORIES = new Map(); DEFAULT_ATRACE_CATEGORIES.set('adb', 'ADB'); DEFAULT_ATRACE_CATEGORIES.set('aidl', 'AIDL calls'); DEFAULT_ATRACE_CATEGORIES.set('am', 'Activity Manager'); DEFAULT_ATRACE_CATEGORIES.set('audio', 'Audio'); DEFAULT_ATRACE_CATEGORIES.set('binder_driver', 'Binder Kernel driver'); DEFAULT_ATRACE_CATEGORIES.set('binder_lock', 'Binder global lock trace'); DEFAULT_ATRACE_CATEGORIES.set('bionic', 'Bionic C library'); DEFAULT_ATRACE_CATEGORIES.set('camera', 'Camera'); DEFAULT_ATRACE_CATEGORIES.set('dalvik', 'ART & Dalvik'); DEFAULT_ATRACE_CATEGORIES.set('database', 'Database'); DEFAULT_ATRACE_CATEGORIES.set('gfx', 'Graphics'); DEFAULT_ATRACE_CATEGORIES.set('hal', 'Hardware Modules'); DEFAULT_ATRACE_CATEGORIES.set('input', 'Input'); DEFAULT_ATRACE_CATEGORIES.set('network', 'Network'); DEFAULT_ATRACE_CATEGORIES.set('nnapi', 'Neural Network API'); DEFAULT_ATRACE_CATEGORIES.set('pm', 'Package Manager'); DEFAULT_ATRACE_CATEGORIES.set('power', 'Power Management'); DEFAULT_ATRACE_CATEGORIES.set('res', 'Resource Loading'); DEFAULT_ATRACE_CATEGORIES.set('rro', 'Resource Overlay'); DEFAULT_ATRACE_CATEGORIES.set('rs', 'RenderScript'); DEFAULT_ATRACE_CATEGORIES.set('sm', 'Sync Manager'); DEFAULT_ATRACE_CATEGORIES.set('ss', 'System Server'); DEFAULT_ATRACE_CATEGORIES.set('vibrator', 'Vibrator'); DEFAULT_ATRACE_CATEGORIES.set('video', 'Video'); DEFAULT_ATRACE_CATEGORIES.set('view', 'View System'); DEFAULT_ATRACE_CATEGORIES.set('webview', 'WebView'); DEFAULT_ATRACE_CATEGORIES.set('wm', 'Window Manager'); function isDataSourceDescriptor(descriptor: unknown): descriptor is DataSourceDescriptor { if (descriptor instanceof Object) { return (descriptor as DataSourceDescriptor).name !== undefined; } return false; } class AtraceAppsList implements m.ClassComponent { view() { if (globals.state.recordConfig.allAtraceApps) { return m('div'); } return m(Textarea, { placeholder: 'Apps to profile, one per line, e.g.:\n' + 'com.android.phone\n' + 'lmkd\n' + 'com.android.nfc', cssClass: '.atrace-apps-list', set: (cfg, val) => cfg.atraceApps = val, get: (cfg) => cfg.atraceApps, } as TextareaAttrs); } } export class AndroidSettings implements m.ClassComponent { view({attrs}: m.CVnode) { let atraceCategories = DEFAULT_ATRACE_CATEGORIES; for (const dataSource of attrs.dataSources) { if (dataSource.name !== 'linux.ftrace' || !isDataSourceDescriptor(dataSource.descriptor)) { continue; } const atraces = dataSource.descriptor.ftraceDescriptor?.atraceCategories; if (!atraces || atraces.length === 0) { break; } atraceCategories = new Map(); for (const atrace of atraces) { if (atrace.name) { atraceCategories.set(atrace.name, atrace.description || ''); } } } return m( `.record-section${attrs.cssClass}`, m(Probe, { title: 'Atrace userspace annotations', img: 'rec_atrace.png', descr: `Enables C++ / Java codebase annotations (ATRACE_BEGIN() / os.Trace())`, setEnabled: (cfg, val) => cfg.atrace = val, isEnabled: (cfg) => cfg.atrace, } as ProbeAttrs, m(Dropdown, { title: 'Categories', cssClass: '.multicolumn.atrace-categories', options: atraceCategories, set: (cfg, val) => cfg.atraceCats = val, get: (cfg) => cfg.atraceCats, } as DropdownAttrs), m(Toggle, { title: 'Record events from all Android apps and services', descr: '', setEnabled: (cfg, val) => cfg.allAtraceApps = val, isEnabled: (cfg) => cfg.allAtraceApps, } as ToggleAttrs), m(AtraceAppsList)), m(Probe, { title: 'Event log (logcat)', img: 'rec_logcat.png', descr: `Streams the event log into the trace. If no buffer filter is specified, all buffers are selected.`, setEnabled: (cfg, val) => cfg.androidLogs = val, isEnabled: (cfg) => cfg.androidLogs, } as ProbeAttrs, m(Dropdown, { title: 'Buffers', cssClass: '.multicolumn', options: LOG_BUFFERS, set: (cfg, val) => cfg.androidLogBuffers = val, get: (cfg) => cfg.androidLogBuffers, } as DropdownAttrs)), m(Probe, { title: 'Frame timeline', img: 'rec_frame_timeline.png', descr: `Records expected/actual frame timings from surface_flinger. Requires Android 12 (S) or above.`, setEnabled: (cfg, val) => cfg.androidFrameTimeline = val, isEnabled: (cfg) => cfg.androidFrameTimeline, } as ProbeAttrs), m(Probe, { title: 'Game intervention list', img: '', descr: `List game modes and interventions. Requires Android 13 (T) or above.`, setEnabled: (cfg, val) => cfg.androidGameInterventionList = val, isEnabled: (cfg) => cfg.androidGameInterventionList, } as ProbeAttrs), m(Probe, { title: 'Network Tracing', img: '', descr: `Records detailed information on network packets. Requires Android 14 (U) or above.`, setEnabled: (cfg, val) => cfg.androidNetworkTracing = val, isEnabled: (cfg) => cfg.androidNetworkTracing, } as ProbeAttrs, m(Slider, { title: 'Poll interval', cssClass: '.thin', values: [100, 250, 500, 1000, 2500], unit: 'ms', set: (cfg, val) => cfg.androidNetworkTracingPollMs = val, get: (cfg) => cfg.androidNetworkTracingPollMs, } as SliderAttrs))); } }