• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/store/persistent_store_proxy';
18import {Store} from 'common/store/store';
19import {Trace} from 'trace/trace';
20import {Traces} from 'trace/traces';
21import {TRACE_INFO} from 'trace/trace_info';
22import {TraceType} from 'trace/trace_type';
23import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node';
24import {
25  AbstractHierarchyViewerPresenter,
26  NotifyHierarchyViewCallbackType,
27} from 'viewers/common/abstract_hierarchy_viewer_presenter';
28import {VISIBLE_CHIP} from 'viewers/common/chip';
29import {DisplayIdentifier} from 'viewers/common/display_identifier';
30import {
31  HierarchyPresenter,
32  SelectedTree,
33} from 'viewers/common/hierarchy_presenter';
34import {PropertiesPresenter} from 'viewers/common/properties_presenter';
35import {RectsPresenter} from 'viewers/common/rects_presenter';
36import {TextFilter} from 'viewers/common/text_filter';
37import {UiHierarchyTreeNode} from 'viewers/common/ui_hierarchy_tree_node';
38import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node';
39import {UI_RECT_FACTORY} from 'viewers/common/ui_rect_factory';
40import {UserOptions} from 'viewers/common/user_options';
41import {ViewerEvents} from 'viewers/common/viewer_events';
42import {
43  RectLegendFactory,
44  TraceRectType,
45} from 'viewers/components/rects/rect_spec';
46import {UiRect} from 'viewers/components/rects/ui_rect';
47import {PropagateHashCodes} from './operations/propagate_hash_codes';
48import {UpdateDisplayNames} from './operations/update_display_names';
49import {UiData} from './ui_data';
50
51export class Presenter extends AbstractHierarchyViewerPresenter<UiData> {
52  static readonly DENYLIST_PROPERTY_NAMES = [
53    'name',
54    'children',
55    'dpiX',
56    'dpiY',
57  ];
58
59  protected override hierarchyPresenter = new HierarchyPresenter(
60    PersistentStoreProxy.new<UserOptions>(
61      'WmHierarchyOptions',
62      {
63        showDiff: {
64          name: 'Show diff',
65          enabled: false,
66          isUnavailable: false,
67        },
68        showOnlyVisible: {
69          name: 'Show only',
70          chip: VISIBLE_CHIP,
71          enabled: false,
72        },
73        simplifyNames: {
74          name: 'Simplify names',
75          enabled: true,
76        },
77        flat: {
78          name: 'Flat',
79          enabled: false,
80        },
81      },
82      this.storage,
83    ),
84    new TextFilter(),
85    Presenter.DENYLIST_PROPERTY_NAMES,
86    true,
87    false,
88    this.getEntryFormattedTimestamp,
89    [[TraceType.WINDOW_MANAGER, [new UpdateDisplayNames()]]],
90  );
91  protected override rectsPresenter = new RectsPresenter(
92    PersistentStoreProxy.new<UserOptions>(
93      'WmRectsOptions',
94      {
95        ignoreRectShowState: {
96          name: 'Ignore',
97          icon: 'visibility',
98          enabled: false,
99        },
100        showOnlyVisible: {
101          name: 'Show only',
102          chip: VISIBLE_CHIP,
103          enabled: false,
104        },
105      },
106      this.storage,
107    ),
108    (tree: HierarchyTreeNode) => UI_RECT_FACTORY.makeUiRects(tree),
109    this.getDisplays,
110    this.convertRectIdtoContainerName,
111  );
112  protected override propertiesPresenter = new PropertiesPresenter(
113    PersistentStoreProxy.new<UserOptions>(
114      'WmPropertyOptions',
115      {
116        showDiff: {
117          name: 'Show diff',
118          enabled: false,
119          isUnavailable: false,
120        },
121        showDefaults: {
122          name: 'Show defaults',
123          enabled: false,
124          tooltip: `If checked, shows the value of all properties.
125Otherwise, hides all properties whose value is
126the default for its data type.`,
127        },
128      },
129      this.storage,
130    ),
131    new TextFilter(),
132    Presenter.DENYLIST_PROPERTY_NAMES,
133    [new PropagateHashCodes()],
134  );
135  protected override multiTraceType = undefined;
136
137  constructor(
138    trace: Trace<HierarchyTreeNode>,
139    traces: Traces,
140    storage: Readonly<Store>,
141    notifyViewCallback: NotifyHierarchyViewCallbackType<UiData>,
142  ) {
143    const uiData = new UiData();
144    uiData.rectSpec = {
145      type: TraceRectType.WINDOW_STATES,
146      icon: TRACE_INFO[TraceType.WINDOW_MANAGER].icon,
147      legend: RectLegendFactory.makeLegendForWindowStateRects(),
148    };
149    super(trace, traces, storage, notifyViewCallback, uiData);
150  }
151
152  async onPropagatePropertyClick(node: UiPropertyTreeNode) {
153    if (node.name !== 'hashCode') {
154      return;
155    }
156    const token = (node.getValue() ?? 0).toString(16);
157    const target = this.uiData.hierarchyTrees
158      ?.at(0)
159      ?.findDfs((node) => node.id.includes(token));
160    if (target) {
161      await this.onHighlightedNodeChange(target);
162    }
163  }
164
165  protected override addViewerSpecificListeners(htmlElement: HTMLElement) {
166    htmlElement.addEventListener(
167      ViewerEvents.PropagatePropertyClick,
168      async (event) => {
169        const node = (event as CustomEvent).detail;
170        await this.onPropagatePropertyClick(node);
171      },
172    );
173  }
174
175  override async onHighlightedNodeChange(item: UiHierarchyTreeNode) {
176    await this.applyHighlightedNodeChange(item);
177    this.refreshUIData();
178  }
179
180  override async onHighlightedIdChange(newId: string) {
181    await this.applyHighlightedIdChange(newId);
182    this.refreshUIData();
183  }
184
185  protected override getOverrideDisplayName(
186    selected: SelectedTree,
187  ): string | undefined {
188    if (!selected.tree.isRoot()) {
189      return undefined;
190    }
191    return this.hierarchyPresenter
192      .getCurrentHierarchyTreeNames(selected.trace)
193      ?.at(0);
194  }
195
196  protected override keepCalculated(tree: HierarchyTreeNode): boolean {
197    return false;
198  }
199
200  protected override refreshUIData() {
201    this.refreshHierarchyViewerUiData();
202  }
203
204  private getDisplays(rects: UiRect[]): DisplayIdentifier[] {
205    const ids: DisplayIdentifier[] = [];
206    rects.forEach((rect: UiRect) => {
207      if (!rect.isDisplay) return;
208      const displayName = rect.label.slice(10, rect.label.length);
209      ids.push({
210        displayId: rect.id,
211        groupId: rect.groupId,
212        name: displayName,
213        isActive: rect.isActiveDisplay,
214      });
215    });
216    return ids.sort();
217  }
218
219  private convertRectIdtoContainerName(id: string) {
220    const parts = id.split(' ');
221    return parts.slice(2).join(' ');
222  }
223}
224