1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2021 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport m from 'mithril'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {LogFilteringCriteria, LogPanel} from './logs_panel'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {ANDROID_LOGS_TRACK_KIND} from '../../public/track_kinds'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace'; 19*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 20*6dbdd20aSAndroid Build Coastguard Workerimport {NUM} from '../../trace_processor/query_result'; 21*6dbdd20aSAndroid Build Coastguard Workerimport {AndroidLogTrack} from './logs_track'; 22*6dbdd20aSAndroid Build Coastguard Workerimport {exists} from '../../base/utils'; 23*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace'; 24*6dbdd20aSAndroid Build Coastguard Worker 25*6dbdd20aSAndroid Build Coastguard Workerconst VERSION = 1; 26*6dbdd20aSAndroid Build Coastguard Worker 27*6dbdd20aSAndroid Build Coastguard Workerconst DEFAULT_STATE: AndroidLogPluginState = { 28*6dbdd20aSAndroid Build Coastguard Worker version: VERSION, 29*6dbdd20aSAndroid Build Coastguard Worker filter: { 30*6dbdd20aSAndroid Build Coastguard Worker // The first two log priorities are ignored. 31*6dbdd20aSAndroid Build Coastguard Worker minimumLevel: 2, 32*6dbdd20aSAndroid Build Coastguard Worker tags: [], 33*6dbdd20aSAndroid Build Coastguard Worker textEntry: '', 34*6dbdd20aSAndroid Build Coastguard Worker hideNonMatching: true, 35*6dbdd20aSAndroid Build Coastguard Worker }, 36*6dbdd20aSAndroid Build Coastguard Worker}; 37*6dbdd20aSAndroid Build Coastguard Worker 38*6dbdd20aSAndroid Build Coastguard Workerinterface AndroidLogPluginState { 39*6dbdd20aSAndroid Build Coastguard Worker version: number; 40*6dbdd20aSAndroid Build Coastguard Worker filter: LogFilteringCriteria; 41*6dbdd20aSAndroid Build Coastguard Worker} 42*6dbdd20aSAndroid Build Coastguard Worker 43*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 44*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.AndroidLog'; 45*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 46*6dbdd20aSAndroid Build Coastguard Worker const store = ctx.mountStore<AndroidLogPluginState>((init) => { 47*6dbdd20aSAndroid Build Coastguard Worker return exists(init) && (init as {version: unknown}).version === VERSION 48*6dbdd20aSAndroid Build Coastguard Worker ? (init as AndroidLogPluginState) 49*6dbdd20aSAndroid Build Coastguard Worker : DEFAULT_STATE; 50*6dbdd20aSAndroid Build Coastguard Worker }); 51*6dbdd20aSAndroid Build Coastguard Worker 52*6dbdd20aSAndroid Build Coastguard Worker const result = await ctx.engine.query( 53*6dbdd20aSAndroid Build Coastguard Worker `select count(1) as cnt from android_logs`, 54*6dbdd20aSAndroid Build Coastguard Worker ); 55*6dbdd20aSAndroid Build Coastguard Worker const logCount = result.firstRow({cnt: NUM}).cnt; 56*6dbdd20aSAndroid Build Coastguard Worker const uri = 'perfetto.AndroidLog'; 57*6dbdd20aSAndroid Build Coastguard Worker const title = 'Android logs'; 58*6dbdd20aSAndroid Build Coastguard Worker if (logCount > 0) { 59*6dbdd20aSAndroid Build Coastguard Worker ctx.tracks.registerTrack({ 60*6dbdd20aSAndroid Build Coastguard Worker uri, 61*6dbdd20aSAndroid Build Coastguard Worker title, 62*6dbdd20aSAndroid Build Coastguard Worker tags: {kind: ANDROID_LOGS_TRACK_KIND}, 63*6dbdd20aSAndroid Build Coastguard Worker track: new AndroidLogTrack(ctx.engine), 64*6dbdd20aSAndroid Build Coastguard Worker }); 65*6dbdd20aSAndroid Build Coastguard Worker const track = new TrackNode({title, uri}); 66*6dbdd20aSAndroid Build Coastguard Worker ctx.workspace.addChildInOrder(track); 67*6dbdd20aSAndroid Build Coastguard Worker } 68*6dbdd20aSAndroid Build Coastguard Worker 69*6dbdd20aSAndroid Build Coastguard Worker const androidLogsTabUri = 'perfetto.AndroidLog#tab'; 70*6dbdd20aSAndroid Build Coastguard Worker 71*6dbdd20aSAndroid Build Coastguard Worker // Eternal tabs should always be available even if there is nothing to show 72*6dbdd20aSAndroid Build Coastguard Worker const filterStore = store.createSubStore( 73*6dbdd20aSAndroid Build Coastguard Worker ['filter'], 74*6dbdd20aSAndroid Build Coastguard Worker (x) => x as LogFilteringCriteria, 75*6dbdd20aSAndroid Build Coastguard Worker ); 76*6dbdd20aSAndroid Build Coastguard Worker 77*6dbdd20aSAndroid Build Coastguard Worker ctx.tabs.registerTab({ 78*6dbdd20aSAndroid Build Coastguard Worker isEphemeral: false, 79*6dbdd20aSAndroid Build Coastguard Worker uri: androidLogsTabUri, 80*6dbdd20aSAndroid Build Coastguard Worker content: { 81*6dbdd20aSAndroid Build Coastguard Worker render: () => m(LogPanel, {filterStore: filterStore, trace: ctx}), 82*6dbdd20aSAndroid Build Coastguard Worker getTitle: () => 'Android Logs', 83*6dbdd20aSAndroid Build Coastguard Worker }, 84*6dbdd20aSAndroid Build Coastguard Worker }); 85*6dbdd20aSAndroid Build Coastguard Worker 86*6dbdd20aSAndroid Build Coastguard Worker if (logCount > 0) { 87*6dbdd20aSAndroid Build Coastguard Worker ctx.tabs.addDefaultTab(androidLogsTabUri); 88*6dbdd20aSAndroid Build Coastguard Worker } 89*6dbdd20aSAndroid Build Coastguard Worker 90*6dbdd20aSAndroid Build Coastguard Worker ctx.commands.registerCommand({ 91*6dbdd20aSAndroid Build Coastguard Worker id: 'perfetto.AndroidLog#ShowLogsTab', 92*6dbdd20aSAndroid Build Coastguard Worker name: 'Show android logs tab', 93*6dbdd20aSAndroid Build Coastguard Worker callback: () => { 94*6dbdd20aSAndroid Build Coastguard Worker ctx.tabs.showTab(androidLogsTabUri); 95*6dbdd20aSAndroid Build Coastguard Worker }, 96*6dbdd20aSAndroid Build Coastguard Worker }); 97*6dbdd20aSAndroid Build Coastguard Worker } 98*6dbdd20aSAndroid Build Coastguard Worker} 99