1/* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {PersistentStoreProxy} from 'common/persistent_store_proxy'; 18import {INVALID_TIME_NS} from 'common/time'; 19import {WinscopeEvent, WinscopeEventType} from 'messaging/winscope_event'; 20import {Trace} from 'trace/trace'; 21import {Traces} from 'trace/traces'; 22import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; 23import { 24 AbstractHierarchyViewerPresenter, 25 NotifyHierarchyViewCallbackType, 26} from 'viewers/common/abstract_hierarchy_viewer_presenter'; 27import {VISIBLE_CHIP} from 'viewers/common/chip'; 28import {DisplayIdentifier} from 'viewers/common/display_identifier'; 29import {HierarchyPresenter} from 'viewers/common/hierarchy_presenter'; 30import {PropertiesPresenter} from 'viewers/common/properties_presenter'; 31import {RectsPresenter} from 'viewers/common/rects_presenter'; 32import {UiHierarchyTreeNode} from 'viewers/common/ui_hierarchy_tree_node'; 33import {UI_RECT_FACTORY} from 'viewers/common/ui_rect_factory'; 34import {UserOptions} from 'viewers/common/user_options'; 35import {UiRect} from 'viewers/components/rects/types2d'; 36import {UpdateDisplayNames} from './operations/update_display_names'; 37import {UiData} from './ui_data'; 38 39export class Presenter extends AbstractHierarchyViewerPresenter { 40 static readonly DENYLIST_PROPERTY_NAMES = [ 41 'name', 42 'children', 43 'dpiX', 44 'dpiY', 45 ]; 46 47 protected override hierarchyPresenter = new HierarchyPresenter( 48 PersistentStoreProxy.new<UserOptions>( 49 'WmHierarchyOptions', 50 { 51 showDiff: { 52 name: 'Show diff', 53 enabled: false, 54 isUnavailable: false, 55 }, 56 showOnlyVisible: { 57 name: 'Show only', 58 chip: VISIBLE_CHIP, 59 enabled: false, 60 }, 61 simplifyNames: { 62 name: 'Simplify names', 63 enabled: true, 64 }, 65 flat: { 66 name: 'Flat', 67 enabled: false, 68 }, 69 }, 70 this.storage, 71 ), 72 Presenter.DENYLIST_PROPERTY_NAMES, 73 true, 74 false, 75 (entry) => { 76 if ( 77 entry.getFullTrace().lengthEntries === 1 && 78 entry.getTimestamp().getValueNs() === INVALID_TIME_NS 79 ) { 80 return 'Dump'; 81 } 82 return entry.getTimestamp().format(); 83 }, 84 [new UpdateDisplayNames()], 85 ); 86 protected override rectsPresenter = new RectsPresenter( 87 PersistentStoreProxy.new<UserOptions>( 88 'WmRectsOptions', 89 { 90 ignoreNonHidden: { 91 name: 'Ignore', 92 icon: 'visibility', 93 enabled: false, 94 }, 95 showOnlyVisible: { 96 name: 'Show only', 97 chip: VISIBLE_CHIP, 98 enabled: false, 99 }, 100 }, 101 this.storage, 102 ), 103 (tree: HierarchyTreeNode) => UI_RECT_FACTORY.makeUiRects(tree), 104 this.getDisplays, 105 ); 106 protected override propertiesPresenter = new PropertiesPresenter( 107 PersistentStoreProxy.new<UserOptions>( 108 'WmPropertyOptions', 109 { 110 showDiff: { 111 name: 'Show diff', 112 enabled: false, 113 isUnavailable: false, 114 }, 115 showDefaults: { 116 name: 'Show defaults', 117 enabled: false, 118 tooltip: ` 119 If checked, shows the value of all properties. 120 Otherwise, hides all properties whose value is 121 the default for its data type. 122 `, 123 }, 124 }, 125 this.storage, 126 ), 127 Presenter.DENYLIST_PROPERTY_NAMES, 128 ); 129 protected override multiTraceType = undefined; 130 131 constructor( 132 trace: Trace<HierarchyTreeNode>, 133 traces: Traces, 134 storage: Readonly<Storage>, 135 notifyViewCallback: NotifyHierarchyViewCallbackType, 136 ) { 137 super(trace, traces, storage, notifyViewCallback, new UiData()); 138 } 139 140 override async onAppEvent(event: WinscopeEvent) { 141 await event.visit( 142 WinscopeEventType.TRACE_POSITION_UPDATE, 143 async (event) => { 144 await this.applyTracePositionUpdate(event); 145 this.refreshUIData(); 146 }, 147 ); 148 } 149 150 override async onHighlightedNodeChange(item: UiHierarchyTreeNode) { 151 await this.applyHighlightedNodeChange(item); 152 this.refreshUIData(); 153 } 154 155 override async onHighlightedIdChange(newId: string) { 156 await this.applyHighlightedIdChange(newId); 157 this.refreshUIData(); 158 } 159 160 protected override getOverrideDisplayName( 161 selected: [Trace<HierarchyTreeNode>, HierarchyTreeNode], 162 ): string | undefined { 163 if (!selected[1].isRoot()) { 164 return undefined; 165 } 166 return this.hierarchyPresenter 167 .getCurrentHierarchyTreeNames(selected[0]) 168 ?.at(0); 169 } 170 171 protected override keepCalculated(tree: HierarchyTreeNode): boolean { 172 return tree.isRoot(); 173 } 174 175 private getDisplays(rects: UiRect[]): DisplayIdentifier[] { 176 const ids: DisplayIdentifier[] = []; 177 rects.forEach((rect: UiRect) => { 178 if (!rect.isDisplay) return; 179 const displayName = rect.label.slice(10, rect.label.length); 180 ids.push({displayId: rect.id, groupId: rect.groupId, name: displayName}); 181 }); 182 return ids.sort((a, b) => { 183 if (a.name < b.name) { 184 return -1; 185 } 186 if (a.name > b.name) { 187 return 1; 188 } 189 return 0; 190 }); 191 } 192 193 private refreshUIData() { 194 this.refreshHierarchyViewerUiData(new UiData()); 195 } 196} 197