1// Copyright (C) 2023 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 {TPTime} from 'src/common/time'; 16import {v4 as uuidv4} from 'uuid'; 17 18import {Actions} from '../../common/actions'; 19import {Engine} from '../../common/engine'; 20import { 21 generateSqlWithInternalLayout, 22} from '../../common/internal_layout_utils'; 23import { 24 PrimaryTrackSortKey, 25 SCROLLING_TRACK_GROUP, 26 Selection, 27} from '../../common/state'; 28import {OnSliceClickArgs} from '../../frontend/base_slice_track'; 29import {globals} from '../../frontend/globals'; 30import { 31 NamedSliceTrack, 32 NamedSliceTrackTypes, 33} from '../../frontend/named_slice_track'; 34import {NewTrackArgs, Track} from '../../frontend/track'; 35import {DecideTracksResult} from '../chrome_scroll_jank'; 36 37export const TOP_LEVEL_SCROLL_KIND = 'TOP_LEVEL_SCROLL'; 38 39export interface TopLevelScrollSelection { 40 kind: 'TOP_LEVEL_SCROLL'; 41 id: number; 42 sqlTableName: string; 43 start: TPTime; 44 duration: TPTime; 45} 46 47export {Data} from '../chrome_slices'; 48 49interface TopLevelScrollTrackTypes extends NamedSliceTrackTypes {} 50 51export class TopLevelScrollTrack extends 52 NamedSliceTrack<TopLevelScrollTrackTypes> { 53 static readonly kind = 'org.chromium.TopLevelScrolls.scrolls'; 54 createdModels = false; 55 56 static create(args: NewTrackArgs): Track { 57 return new TopLevelScrollTrack(args); 58 } 59 60 constructor(args: NewTrackArgs) { 61 super(args); 62 } 63 64 async initSqlTable(tableName: string) { 65 if (this.createdModels) { 66 return; 67 } 68 const sql = 69 `CREATE VIEW ${tableName} AS ` + generateSqlWithInternalLayout({ 70 columns: [`printf("Scroll %s", CAST(id AS STRING)) AS name`, '*'], 71 layoutParams: {ts: 'ts', dur: 'dur'}, 72 sourceTable: 'chrome_scrolls', 73 orderByClause: 'ts', 74 }); 75 await this.engine.query(sql); 76 this.createdModels = true; 77 } 78 79 isSelectionHandled(selection: Selection) { 80 if (selection.kind !== 'TOP_LEVEL_SCROLL') { 81 return false; 82 } 83 return selection.trackId === this.trackId; 84 } 85 86 onSliceClick(args: OnSliceClickArgs<TopLevelScrollTrackTypes['slice']>) { 87 globals.dispatch(Actions.selectTopLevelScrollSlice({ 88 id: args.slice.id, 89 sqlTableName: this.tableName, 90 start: args.slice.start, 91 duration: args.slice.duration, 92 trackId: this.trackId, 93 })); 94 } 95} 96 97export async function addTopLevelScrollTrack(engine: Engine): 98 Promise<DecideTracksResult> { 99 const result: DecideTracksResult = { 100 tracksToAdd: [], 101 }; 102 103 await engine.query(`SELECT IMPORT('chrome.chrome_scrolls');`); 104 105 result.tracksToAdd.push({ 106 id: uuidv4(), 107 engineId: engine.id, 108 kind: TopLevelScrollTrack.kind, 109 trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK, 110 name: 'Top Level Scrolls', 111 config: {}, 112 trackGroup: SCROLLING_TRACK_GROUP, 113 }); 114 115 return result; 116} 117