Remove legacy data and properties view from layer trace root

- Use OnPush Angular change detection strategy in SF viewer (better perf and avoids change loop errors)
- Hide PropertyGroupsComponent when root layer is selected
- Add formatting for "raw" long numbers

Fix: b/254044321
Test: npm run build:all && npm run test:all
Change-Id: I56274973a8d42c28e49e4a4a92fd6ae09a6693db
This commit is contained in:
Kean Mariotti
2022-12-23 08:40:23 +00:00
parent 43b5f364d7
commit 357b30e6bd
10 changed files with 71 additions and 43 deletions

View File

@@ -18,6 +18,7 @@ import {
toSize, toActiveBuffer, toColor, toColor3, toPoint, toPointF, toRect,
toRectF, toRegion, toMatrix22, toTransform, toInsets
} from './common';
import {ArrayUtils} from "common/utils/array_utils";
import { PropertiesDump } from "viewers/common/ui_tree_utils";
import intDefMapping from
'../../../../../../../prebuilts/misc/common/winscope/intDefMapping.json';
@@ -176,6 +177,16 @@ export default class ObjectFormatter {
}
}
// Raw long number (no type name, no constructor name, no useful toString() method)
if (ArrayUtils.equal(Object.keys(obj).sort(), ["high_", "low_"])) {
const high = BigInt(obj.high_) << 32n;
let low = BigInt(obj.low_);
if (low < 0) {
low = -low;
}
return (high | low).toString();
}
return null;
}

View File

@@ -21,8 +21,8 @@ import { TimeUtils } from "common/utils/time_utils";
import { ElapsedTimestamp, RealTimestamp } from "common/trace/timestamp";
LayerTraceEntry.fromProto = function (
protos: any[],
displayProtos: any[],
protos: object[],
displayProtos: object[],
elapsedTimestamp: bigint,
vSyncId: number,
hwcBlob: string,
@@ -49,7 +49,7 @@ LayerTraceEntry.fromProto = function (
return entry;
}
function addAttributes(entry: LayerTraceEntry, protos: any, useElapsedTime = false) {
function addAttributes(entry: LayerTraceEntry, protos: object[], useElapsedTime = false) {
entry.kind = "entry";
// Avoid parsing the entry root because it is an array of layers
// containing all trace information, this slows down the property tree.

View File

@@ -39,7 +39,3 @@ app-root {
flex-direction: row;
overflow: auto;
}
viewer-surface-flinger .properties-view .view-header {
flex: 3;
}

View File

@@ -22,7 +22,8 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
@Component({
selector: "properties-view",
template: `
<div class="view-header">
<div class="view-header"
[class.view-header-with-property-groups]="displayPropertyGroups">
<div class="title-filter">
<h2 class="properties-title mat-title">Properties</h2>
@@ -49,7 +50,7 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
</div>
<property-groups
*ngIf="itemIsSelected() && propertyGroups"
*ngIf="itemIsSelected() && displayPropertyGroups"
class="property-groups"
[item]="selectedFlickerItem"
></property-groups>
@@ -58,7 +59,8 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
<mat-divider></mat-divider>
<div class="properties-content">
<h3 *ngIf="objectKeys(propertiesTree).length > 0 && isProtoDump" class="properties-title mat-subheading-2">Properties - Proto Dump</h3>
<h3 *ngIf="objectKeys(propertiesTree).length > 0 && isProtoDump"
class="properties-title mat-subheading-2">Properties - Proto Dump</h3>
<div class="tree-wrapper">
<tree-view
@@ -80,6 +82,10 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
margin-bottom: 12px;
}
.view-header-with-property-groups {
flex: 3;
}
.title-filter {
display: flex;
flex-direction: row;
@@ -121,7 +127,7 @@ export class PropertiesComponent {
@Input() userOptions: UserOptions = {};
@Input() propertiesTree: PropertiesTreeNode = {};
@Input() selectedFlickerItem: TraceTreeNode | null = null;
@Input() propertyGroups = false;
@Input() displayPropertyGroups = false;
@Input() isProtoDump = false;
constructor(

View File

@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, Inject, Input, Output, ElementRef, EventEmitter, ChangeDetectionStrategy } from "@angular/core";
import {Component, Inject, Input, Output, ElementRef, EventEmitter, ChangeDetectionStrategy} from "@angular/core";
import { PersistentStore } from "common/utils/persistent_store";
import { nodeStyles, treeNodeDataViewStyles } from "viewers/components/styles/node.styles";
import { UiTreeUtils, UiTreeNode, HierarchyTreeNode, PropertiesTreeNode } from "viewers/common/ui_tree_utils";
import { UiTreeUtils, UiTreeNode, HierarchyTreeNode } from "viewers/common/ui_tree_utils";
import { TraceType } from "common/trace/trace_type";
@Component({
@@ -76,8 +76,12 @@ export class TreeComponent {
diffClass = UiTreeUtils.diffClass;
isHighlighted = UiTreeUtils.isHighlighted;
@Input() item?: UiTreeNode;
// TODO (b/263779536): this array is passed down from viewers/presenters and is used to generate
// an identifier supposed to be unique for each viewer. Let's just use a proper identifier
// instead. Each viewer/presenter could pass down a random magic number, an UUID, ...
@Input() dependencies: Array<TraceType> = [];
@Input() item?: UiTreeNode;
@Input() store!: PersistentStore;
@Input() isFlattened? = false;
@Input() initialDepth = 0;
@@ -117,7 +121,7 @@ export class TreeComponent {
}
constructor(
@Inject(ElementRef) public elementRef: ElementRef,
@Inject(ElementRef) public elementRef: ElementRef
) {
this.nodeElement = elementRef.nativeElement.querySelector(".node");
this.nodeElement?.addEventListener("mousedown", this.nodeMouseDownEventListener);
@@ -168,18 +172,14 @@ export class TreeComponent {
}
private updateHighlightedItems() {
if (this.item instanceof HierarchyTreeNode) {
if (this.item.stableId) {
this.highlightedItemChange.emit(`${this.item.stableId}`);
} else if (!this.item.stableId) {
//this.selectedTreeChange.emit(this.item);
}
if (this.item?.stableId) {
this.highlightedItemChange.emit(`${this.item.stableId}`);
}
}
public isPinned() {
if (this.item instanceof HierarchyTreeNode) {
return this.pinnedItems?.map(item => `${item.id}`).includes(`${this.item.id}`);
return this.pinnedItems?.map(item => `${item.stableId}`).includes(`${this.item.stableId}`);
}
return false;
}

View File

@@ -1,4 +1,3 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
@@ -31,7 +30,7 @@ export class Presenter {
constructor(notifyViewCallback: NotifyViewCallbackType, private storage: Storage) {
this.notifyViewCallback = notifyViewCallback;
this.uiData = new UiData([TraceType.SURFACE_FLINGER]);
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
public updatePinnedItems(pinnedItem: HierarchyTreeNode) {
@@ -43,7 +42,7 @@ export class Presenter {
}
this.updatePinnedIds(pinnedId);
this.uiData.pinnedItems = this.pinnedItems;
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
public updateHighlightedItems(id: string) {
@@ -54,20 +53,20 @@ export class Presenter {
this.highlightedItems.push(id);
}
this.uiData.highlightedItems = this.highlightedItems;
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
public updateHierarchyTree(userOptions: UserOptions) {
this.hierarchyUserOptions = userOptions;
this.uiData.hierarchyUserOptions = this.hierarchyUserOptions;
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
public filterHierarchyTree(filterString: string) {
this.hierarchyFilter = TreeUtils.makeNodeFilter(filterString);
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
public updatePropertiesTree(userOptions: UserOptions) {
@@ -101,7 +100,7 @@ export class Presenter {
this.uiData.tree = this.generateTree();
}
}
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
private generateRects(): Rectangle[] {
@@ -160,8 +159,9 @@ export class Presenter {
if (this.selectedHierarchyTree) {
this.uiData.propertiesTree = this.getTreeWithTransformedProperties(this.selectedHierarchyTree);
this.uiData.selectedLayer = this.selectedLayer;
this.uiData.displayPropertyGroups = this.shouldDisplayPropertyGroups(this.selectedLayer);
}
this.notifyViewCallback(this.uiData);
this.copyUiDataAndNotifyView();
}
private generateTree() {
@@ -252,6 +252,20 @@ export class Presenter {
return transformedTree;
}
private shouldDisplayPropertyGroups(selectedLayer: Layer): boolean {
// Do not display property groups when the root layer is selected. The root layer doesn't
// provide property groups info (visibility, geometry transforms, ...).
const isRoot = selectedLayer === this.entry;
return !isRoot;
}
private copyUiDataAndNotifyView() {
// Create a shallow copy of the data, otherwise the Angular OnPush change detection strategy
// won't detect the new input
const copy = Object.assign({}, this.uiData);
this.notifyViewCallback(copy);
}
private readonly notifyViewCallback: NotifyViewCallbackType;
private uiData: UiData;
private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter("");

View File

@@ -30,6 +30,7 @@ export class UiData {
tree: HierarchyTreeNode | null = null;
propertiesTree: PropertiesTreeNode | null = null;
selectedLayer: Layer = {};
displayPropertyGroups = true;
constructor(dependencies?: Array<TraceType>) {
this.dependencies = dependencies ?? [];

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
import {
ChangeDetectionStrategy,
Component,
Input,
} from "@angular/core";
@@ -24,6 +25,7 @@ import { PersistentStore } from "common/utils/persistent_store";
@Component({
selector: "viewer-surface-flinger",
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="card-grid">
<rects-view
@@ -49,7 +51,7 @@ import { PersistentStore } from "common/utils/persistent_store";
[userOptions]="inputData?.propertiesUserOptions ?? {}"
[propertiesTree]="inputData?.propertiesTree ?? {}"
[selectedFlickerItem]="inputData?.selectedLayer ?? {}"
[propertyGroups]="true"
[displayPropertyGroups]="inputData?.displayPropertyGroups"
[isProtoDump]="true"
></properties-view>
</div>
@@ -67,7 +69,7 @@ import { PersistentStore } from "common/utils/persistent_store";
]
})
export class ViewerSurfaceFlingerComponent {
@Input() inputData: UiData | null = null;
@Input() inputData?: UiData;
@Input() store: PersistentStore = new PersistentStore();
@Input() active = false;
TRACE_INFO = TRACE_INFO;

View File

@@ -13,22 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TraceType} from "common/trace/trace_type";
import {View, Viewer, ViewType} from "viewers/viewer";
import {Presenter} from "./presenter";
import {UiData} from "./ui_data";
import {TraceType} from "common/trace/trace_type";
import {View, Viewer, ViewType} from "viewers/viewer";
import {ViewerEvents} from "viewers/common/viewer_events";
class ViewerSurfaceFlinger implements Viewer {
public static readonly DEPENDENCIES: TraceType[] = [TraceType.SURFACE_FLINGER];
private htmlElement: HTMLElement;
private presenter: Presenter;
constructor(storage: Storage) {
this.htmlElement = document.createElement("viewer-surface-flinger");
this.presenter = new Presenter((uiData: UiData) => {
// Angular does not deep watch @Input properties. Clearing inputData to null before repopulating
// automatically ensures that the UI will change via the Angular change detection cycle. Without
// resetting, Angular does not auto-detect that inputData has changed.
(this.htmlElement as any).inputData = null;
(this.htmlElement as any).inputData = uiData;
}, storage);
this.htmlElement.addEventListener(ViewerEvents.HierarchyPinnedChange, (event) => this.presenter.updatePinnedItems(((event as CustomEvent).detail.pinnedItem)));
this.htmlElement.addEventListener(ViewerEvents.HighlightedChange, (event) => this.presenter.updateHighlightedItems(`${(event as CustomEvent).detail.id}`));
this.htmlElement.addEventListener(ViewerEvents.HierarchyUserOptionsChange, (event) => this.presenter.updateHierarchyTree((event as CustomEvent).detail.userOptions));
@@ -49,10 +51,6 @@ class ViewerSurfaceFlinger implements Viewer {
public getDependencies(): TraceType[] {
return ViewerSurfaceFlinger.DEPENDENCIES;
}
public static readonly DEPENDENCIES: TraceType[] = [TraceType.SURFACE_FLINGER];
private htmlElement: HTMLElement;
private presenter: Presenter;
}
export {ViewerSurfaceFlinger};

View File

@@ -65,7 +65,7 @@ import { PersistentStore } from "common/utils/persistent_store";
]
})
export class ViewerWindowManagerComponent {
@Input() inputData: UiData | null = null;
@Input() inputData?: UiData;
@Input() store: PersistentStore = new PersistentStore();
@Input() active = false;
TRACE_INFO = TRACE_INFO;