| // 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<string, string>(); |
| 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<string, string>(); |
| 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<RecordingSectionAttrs> { |
| view({attrs}: m.CVnode<RecordingSectionAttrs>) { |
| 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<string, string>(); |
| 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))); |
| } |
| } |