Make winscope compatible with flicker/CTS infra
Flickerlib is migrating to the same structure as the CTS tests. This cl makes winscope compatible with this changes. It now parses traces with the new information and add a "flickerObj" entry to each node with the calculated vlaues from flickerlib Test: yarn run dev and open a few WM traces Bug: 167521440 Bug: 170372278 Change-Id: I4a116ccabe392c75e5b5049808d4837f865cb2c7
This commit is contained in:
@@ -252,7 +252,8 @@ export default {
|
|||||||
this.item = item;
|
this.item = item;
|
||||||
this.tree = this.generateTreeFromItem(item);
|
this.tree = this.generateTreeFromItem(item);
|
||||||
|
|
||||||
this.rects = [...item.rects].reverse();
|
const rects = item.rects //.toArray()
|
||||||
|
this.rects = [...rects].reverse();
|
||||||
this.bounds = item.bounds;
|
this.bounds = item.bounds;
|
||||||
|
|
||||||
this.hierarchySelected = null;
|
this.hierarchySelected = null;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
import { FILE_TYPES, DUMP_TYPES } from "@/decode.js";
|
import { FILE_TYPES, DUMP_TYPES } from "@/decode.js";
|
||||||
import DumpBase from "./DumpBase";
|
import DumpBase from "./DumpBase";
|
||||||
|
|
||||||
import { WindowManagerTraceEntry } from '@/flickerlib';
|
import { WindowManagerTrace } from '@/flickerlib';
|
||||||
|
|
||||||
export default class WindowManager extends DumpBase {
|
export default class WindowManager extends DumpBase {
|
||||||
wmDumpFile: any;
|
wmDumpFile: any;
|
||||||
@@ -32,7 +32,7 @@ export default class WindowManager extends DumpBase {
|
|||||||
return DUMP_TYPES.WINDOW_MANAGER;
|
return DUMP_TYPES.WINDOW_MANAGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromProto(proto): WindowManagerTraceEntry {
|
static fromProto(proto): WindowManagerTrace {
|
||||||
return WindowManagerTraceEntry.fromProto(proto);
|
return WindowManagerTrace.fromDump(proto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
110
tools/winscope/src/flickerlib/WindowManagerState.ts
Normal file
110
tools/winscope/src/flickerlib/WindowManagerState.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { nanosToString, TimeUnits } from "../utils/utils.js"
|
||||||
|
import { getWMPropertiesForDisplay } from './mixin'
|
||||||
|
|
||||||
|
import {
|
||||||
|
KeyguardControllerState,
|
||||||
|
RootWindowContainer,
|
||||||
|
WindowManagerPolicy,
|
||||||
|
WindowManagerState
|
||||||
|
} from "./common"
|
||||||
|
|
||||||
|
import WindowContainer from "./windows/WindowContainer"
|
||||||
|
|
||||||
|
|
||||||
|
WindowManagerState.fromProto = function ({proto, timestamp = 0, where = ""}): WindowManagerState {
|
||||||
|
var inputMethodWIndowAppToken = ""
|
||||||
|
if (proto.inputMethodWindow != null) {
|
||||||
|
proto.inputMethodWindow.hashCode.toString(16)
|
||||||
|
}
|
||||||
|
const rootWindowContainer = newRootWindowContainer(proto.rootWindowContainer)
|
||||||
|
const keyguardControllerState = newKeyguardControllerState(
|
||||||
|
proto.rootWindowContainer.keyguardController)
|
||||||
|
const entry = new WindowManagerState(
|
||||||
|
where,
|
||||||
|
newWindowManagerPolicy(proto.policy),
|
||||||
|
proto.focusedApp,
|
||||||
|
proto.focusedDisplayId,
|
||||||
|
proto.focusedWindow?.title ?? "",
|
||||||
|
inputMethodWIndowAppToken,
|
||||||
|
proto.rootWindowContainer.isHomeRecentsComponent,
|
||||||
|
proto.displayFrozen,
|
||||||
|
proto.rotation,
|
||||||
|
proto.lastOrientation,
|
||||||
|
proto.rootWindowContainer.pendingActivities.map(it => it.title),
|
||||||
|
rootWindowContainer,
|
||||||
|
keyguardControllerState,
|
||||||
|
timestamp = timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.name = nanosToString(entry.timestamp, TimeUnits.MILLI_SECONDS)
|
||||||
|
entry.shortName = entry.name
|
||||||
|
entry.children = entry.root.childrenWindows.reverse()
|
||||||
|
entry.chips = []
|
||||||
|
entry.visible = true
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
|
||||||
|
function newWindowManagerPolicy(proto): WindowManagerPolicy {
|
||||||
|
return new WindowManagerPolicy(
|
||||||
|
proto.focusedAppToken || "",
|
||||||
|
proto.forceStatusBar,
|
||||||
|
proto.forceStatusBarFromKeyguard,
|
||||||
|
proto.keyguardDrawComplete,
|
||||||
|
proto.keyguardOccluded,
|
||||||
|
proto.keyguardOccludedChanged,
|
||||||
|
proto.keyguardOccludedPending,
|
||||||
|
proto.lastSystemUiFlags,
|
||||||
|
proto.orientation,
|
||||||
|
proto.rotation,
|
||||||
|
proto.rotationMode,
|
||||||
|
proto.screenOnFully,
|
||||||
|
proto.windowManagerDrawComplete
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function newRootWindowContainer(proto): RootWindowContainer {
|
||||||
|
const windowContainer = WindowContainer.fromProto({proto: proto.windowContainer})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
|
}
|
||||||
|
const entry = new RootWindowContainer(windowContainer)
|
||||||
|
proto.windowContainer.children.reverse()
|
||||||
|
.map(it => WindowContainer.childrenFromProto(entry, it, /* isActivityInTree */ false))
|
||||||
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
|
||||||
|
function newKeyguardControllerState(proto): KeyguardControllerState {
|
||||||
|
const keyguardOccludedStates = {}
|
||||||
|
|
||||||
|
if (proto) {
|
||||||
|
proto.keyguardOccludedStates.forEach(it =>
|
||||||
|
keyguardOccludedStates[it.displayId] = it.keyguardOccluded)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KeyguardControllerState(
|
||||||
|
proto?.aodShowing ?? false,
|
||||||
|
proto?.keyguardShowing ?? false,
|
||||||
|
keyguardOccludedStates
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WindowManagerState;
|
||||||
@@ -14,23 +14,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { WindowManagerTrace } from "./common"
|
||||||
WindowManagerTrace,
|
import WindowManagerState from "./WindowManagerState"
|
||||||
} from "./common"
|
|
||||||
|
|
||||||
import WindowManagerTraceEntry from "./WindowManagerTraceEntry"
|
|
||||||
|
|
||||||
WindowManagerTrace.fromProto = function (proto) {
|
WindowManagerTrace.fromProto = function (proto) {
|
||||||
const entries = []
|
const entries = []
|
||||||
for (const entryProto of proto.entry) {
|
for (const entryProto of proto.entry) {
|
||||||
const transformedEntry = WindowManagerTraceEntry.fromProto(
|
const transformedEntry = WindowManagerState.fromProto({
|
||||||
entryProto.windowManagerService, entryProto.elapsedRealtimeNanos)
|
proto: entryProto.windowManagerService,
|
||||||
|
timestamp: entryProto.elapsedRealtimeNanos,
|
||||||
|
where: entryProto.where})
|
||||||
entries.push(transformedEntry)
|
entries.push(transformedEntry)
|
||||||
}
|
|
||||||
|
|
||||||
const source = null;
|
}
|
||||||
const sourceChecksum = null;
|
const source = null
|
||||||
|
const sourceChecksum = null
|
||||||
return new WindowManagerTrace(entries, source, sourceChecksum)
|
return new WindowManagerTrace(entries, source, sourceChecksum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowManagerTrace.fromDump = function(proto): WindowManagerTrace {
|
||||||
|
return WindowManagerState.fromProto({proto: proto})
|
||||||
|
}
|
||||||
|
|
||||||
export default WindowManagerTrace;
|
export default WindowManagerTrace;
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020, The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { nanosToString, TimeUnits } from "../utils/utils.js"
|
|
||||||
|
|
||||||
import { WindowManagerTraceEntry } from "./common"
|
|
||||||
|
|
||||||
import { applyMixins } from "./mixin"
|
|
||||||
|
|
||||||
import ITreeViewElement from './treeview/IClickableTreeViewElement'
|
|
||||||
import IClickableTreeViewElement from './treeview/IClickableTreeViewElement'
|
|
||||||
import Chip from './treeview/Chip'
|
|
||||||
import WindowContainer from "./windows/WindowContainer"
|
|
||||||
|
|
||||||
class WindowManagerTraceEntryMixin implements IClickableTreeViewElement {
|
|
||||||
common: any
|
|
||||||
kind: string
|
|
||||||
name: string
|
|
||||||
shortName: string
|
|
||||||
stableId: string
|
|
||||||
chips: Array<Chip>
|
|
||||||
children: Array<ITreeViewElement>
|
|
||||||
obj: any
|
|
||||||
rawTreeViewObject
|
|
||||||
|
|
||||||
timestamp: number
|
|
||||||
rootWindow
|
|
||||||
|
|
||||||
mixinConstructor(obj) {
|
|
||||||
const name = this.timestamp ? nanosToString(this.timestamp, TimeUnits.MILLI_SECONDS) : ""
|
|
||||||
this.kind = "entry"
|
|
||||||
this.name = name
|
|
||||||
this.shortName = name
|
|
||||||
this.stableId = "entry"
|
|
||||||
this.children = this.rootWindow.children
|
|
||||||
this.chips = []
|
|
||||||
this.obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromProto(proto, timestamp) {
|
|
||||||
const rootWindow =
|
|
||||||
WindowContainer.fromProto(proto.rootWindowContainer.windowContainer, null)
|
|
||||||
const windowManagerTraceEntry =
|
|
||||||
new WindowManagerTraceEntry(rootWindow, timestamp)
|
|
||||||
|
|
||||||
windowManagerTraceEntry.kind = 'service'
|
|
||||||
|
|
||||||
windowManagerTraceEntry.focusedApp = proto.focusedApp
|
|
||||||
windowManagerTraceEntry.focusedDisplayId = proto.focusedDisplayId
|
|
||||||
windowManagerTraceEntry.lastOrientation = proto.lastOrientation
|
|
||||||
windowManagerTraceEntry.policy = proto.policy
|
|
||||||
windowManagerTraceEntry.rotation = proto.rotation
|
|
||||||
windowManagerTraceEntry.displayFrozen = proto.displayFrozen
|
|
||||||
windowManagerTraceEntry.inputMethodWindow = proto.inputMethodWindow
|
|
||||||
|
|
||||||
// Remove anything that is part of the children elements
|
|
||||||
// allows for faster loading of properties and less information cluttering
|
|
||||||
// this applied to anywhere the proto is passed to be saved as .obj
|
|
||||||
const obj = Object.assign({}, proto)
|
|
||||||
obj.rootWindowContainer = {};
|
|
||||||
Object.assign(obj.rootWindowContainer,
|
|
||||||
proto.rootWindowContainer)
|
|
||||||
obj.rootWindowContainer.windowContainer = {};
|
|
||||||
Object.assign(obj.rootWindowContainer.windowContainer,
|
|
||||||
proto.rootWindowContainer.windowContainer)
|
|
||||||
delete obj.rootWindowContainer.windowContainer.children
|
|
||||||
windowManagerTraceEntry.mixinConstructor(obj)
|
|
||||||
|
|
||||||
return windowManagerTraceEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
attachObject(obj) {
|
|
||||||
this.obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
asRawTreeViewObject() {
|
|
||||||
// IMPORTANT: We want to always return the same tree view object and not
|
|
||||||
// generate a new one every time this function is called.
|
|
||||||
if (!this.rawTreeViewObject) {
|
|
||||||
const children = this.children.map(child => child.asRawTreeViewObject())
|
|
||||||
|
|
||||||
this.rawTreeViewObject = {
|
|
||||||
kind: this.kind,
|
|
||||||
name: this.name,
|
|
||||||
shortName: this.shortName,
|
|
||||||
stableId: this.stableId,
|
|
||||||
chips: this.chips,
|
|
||||||
obj: this.obj,
|
|
||||||
children,
|
|
||||||
ref: this,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.rawTreeViewObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyMixins(WindowManagerTraceEntry, [WindowManagerTraceEntryMixin])
|
|
||||||
|
|
||||||
export default WindowManagerTraceEntry;
|
|
||||||
@@ -17,42 +17,69 @@
|
|||||||
// Imports all the compiled common Flicker library classes and exports them
|
// Imports all the compiled common Flicker library classes and exports them
|
||||||
// as clean es6 modules rather than having them be commonjs modules
|
// as clean es6 modules rather than having them be commonjs modules
|
||||||
|
|
||||||
const WindowManagerTrace = require('flicker').com.android.server.wm.flicker
|
const WindowManagerTrace = require('flicker').com.android.server.wm.flicker.
|
||||||
.common.traces.windowmanager.WindowManagerTrace;
|
common.traces.windowmanager.WindowManagerTrace;
|
||||||
const WindowManagerTraceEntry = require('flicker').com.android.server.wm.
|
const WindowManagerState = require('flicker').com.android.server.wm.
|
||||||
flicker.common.traces.windowmanager.WindowManagerTraceEntry;
|
flicker.common.traces.windowmanager.WindowManagerState;
|
||||||
|
|
||||||
const WindowContainer = require('flicker').com.android.server.wm.flicker.common.
|
const Activity = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.WindowContainer;
|
traces.windowmanager.windows.Activity;
|
||||||
const WindowState = require('flicker').com.android.server.wm.flicker.common.
|
const ActivityTask = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.WindowState;
|
traces.windowmanager.windows.ActivityTask;
|
||||||
const DisplayContent = require('flicker').com.android.server.wm.flicker.common.
|
const Configuration = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.DisplayContent;
|
traces.windowmanager.windows.Configuration;
|
||||||
const ActivityRecord = require('flicker').com.android.server.wm.flicker.common.
|
const ConfigurationContainer = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.ActivityRecord;
|
traces.windowmanager.windows.ConfigurationContainer;
|
||||||
const WindowToken = require('flicker').com.android.server.wm.flicker.common.
|
|
||||||
traces.windowmanager.windows.WindowToken;
|
|
||||||
const DisplayArea = require('flicker').com.android.server.wm.flicker.common.
|
const DisplayArea = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.DisplayArea;
|
traces.windowmanager.windows.DisplayArea;
|
||||||
const RootDisplayArea = require('flicker').com.android.server.wm.flicker.common.
|
const DisplayContent = require('flicker').com.android.server.wm.flicker.common.
|
||||||
traces.windowmanager.windows.RootDisplayArea;
|
traces.windowmanager.windows.DisplayContent;
|
||||||
const Task = require('flicker').com.android.server.wm.flicker.common.traces.
|
const KeyguardControllerState = require('flicker').com.android.server.wm.flicker.common.
|
||||||
windowmanager.windows.Task;
|
traces.windowmanager.windows.KeyguardControllerState;
|
||||||
|
const RootWindowContainer = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.RootWindowContainer;
|
||||||
|
const WindowConfiguration = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowConfiguration;
|
||||||
|
const WindowContainer = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowContainer;
|
||||||
|
const WindowContainerChild = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowContainerChild;
|
||||||
|
const WindowManagerPolicy = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowManagerPolicy;
|
||||||
|
const WindowState = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowState;
|
||||||
|
const WindowToken = require('flicker').com.android.server.wm.flicker.common.
|
||||||
|
traces.windowmanager.windows.WindowToken;
|
||||||
|
|
||||||
const Rect = require('flicker').com.android.server.wm.flicker.common.Rect;
|
const Rect = require('flicker').com.android.server.wm.flicker.common.Rect;
|
||||||
const Bounds = require('flicker').com.android.server.wm.flicker.common.Bounds;
|
const Bounds = require('flicker').com.android.server.wm.flicker.common.Bounds;
|
||||||
|
|
||||||
|
function toRect(proto) {
|
||||||
|
if (proto == null) {
|
||||||
|
return new Rect(0, 0, 0, 0)
|
||||||
|
} else {
|
||||||
|
return new Rect(proto.left, proto.top, proto.right, proto.bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
WindowManagerTrace,
|
Activity,
|
||||||
WindowManagerTraceEntry,
|
ActivityTask,
|
||||||
WindowContainer,
|
Configuration,
|
||||||
WindowState,
|
ConfigurationContainer,
|
||||||
DisplayContent,
|
|
||||||
ActivityRecord,
|
|
||||||
WindowToken,
|
|
||||||
DisplayArea,
|
DisplayArea,
|
||||||
RootDisplayArea,
|
DisplayContent,
|
||||||
Task,
|
KeyguardControllerState,
|
||||||
|
RootWindowContainer,
|
||||||
|
WindowConfiguration,
|
||||||
|
WindowContainer,
|
||||||
|
WindowContainerChild,
|
||||||
|
WindowState,
|
||||||
|
WindowToken,
|
||||||
|
WindowManagerPolicy,
|
||||||
|
WindowManagerTrace,
|
||||||
|
WindowManagerState,
|
||||||
Rect,
|
Rect,
|
||||||
Bounds,
|
Bounds,
|
||||||
|
toRect
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import WindowManagerTraceEntry from './WindowManagerTraceEntry';
|
import WindowManagerState from './WindowManagerState';
|
||||||
import WindowManagerTrace from './WindowManagerTrace';
|
import WindowManagerTrace from './WindowManagerTrace';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point into the flickerlib for Winscope.
|
* Entry point into the flickerlib for Winscope.
|
||||||
* Expose everything we want Winscope to have access to here.
|
* Expose everything we want Winscope to have access to here.
|
||||||
*/
|
*/
|
||||||
export {WindowManagerTraceEntry, WindowManagerTrace};
|
export {WindowManagerState, WindowManagerTrace};
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,44 @@
|
|||||||
/**
|
/*
|
||||||
* Injects all the properties (getters, setters, functions...) of a list of
|
* Copyright 2020, The Android Open Source Project
|
||||||
* classes (baseCtors) into a class (derivedCtor).
|
*
|
||||||
* @param derivedCtor The constructor of the class we want to inject the
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* properties into.
|
* you may not use this file except in compliance with the License.
|
||||||
* @param baseCtors A list of consturctor of the classes we want to mixin the
|
* You may obtain a copy of the License at
|
||||||
* properties of into the derivedCtor.
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
export function applyMixins(derivedCtor: any, baseCtors: any[]) {
|
|
||||||
baseCtors.forEach(baseCtor => {
|
|
||||||
Object.getOwnPropertyNames(baseCtor).forEach(name => {
|
|
||||||
if (['length', 'name', 'prototype'].includes(name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(derivedCtor, name, Object.getOwnPropertyDescriptor(baseCtor, name))
|
/**
|
||||||
})
|
* Get the properties of a WM object for display.
|
||||||
|
*
|
||||||
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
|
* @param entry WM hierarchy element
|
||||||
Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name))
|
* @param proto Associated proto object
|
||||||
})
|
*/
|
||||||
});
|
export function getWMPropertiesForDisplay(proto: any): any {
|
||||||
|
const obj = Object.assign({}, proto)
|
||||||
|
if (obj.children) delete obj.children
|
||||||
|
if (obj.childWindows) delete obj.childWindows
|
||||||
|
if (obj.childrenWindows) delete obj.childrenWindows
|
||||||
|
if (obj.childContainers) delete obj.childContainers
|
||||||
|
if (obj.identifier) delete obj.identifier
|
||||||
|
if (obj.windowToken) delete obj.windowToken
|
||||||
|
if (obj.rootDisplayArea) delete obj.rootDisplayArea
|
||||||
|
if (obj.rootWindowContainer) delete obj.rootWindowContainer
|
||||||
|
if (obj.windowContainer) delete obj.windowContainer
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shortenName(name: any): string {
|
||||||
|
const classParts = (name + "").split(".")
|
||||||
|
if (classParts.length <= 3) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
const className = classParts.slice(-1)[0] // last element
|
||||||
|
return `${classParts[0]}.${classParts[1]}.(...).${className}`
|
||||||
}
|
}
|
||||||
53
tools/winscope/src/flickerlib/windows/Activity.ts
Normal file
53
tools/winscope/src/flickerlib/windows/Activity.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
|
import { Activity } from "../common"
|
||||||
|
import WindowContainer from "./WindowContainer"
|
||||||
|
|
||||||
|
Activity.fromProto = function (proto, parent: WindowContainer): Activity {
|
||||||
|
if (proto == null) {
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
const windowContainer = WindowContainer.fromProto({proto: proto.windowToken.windowContainer,
|
||||||
|
identifierOverride: proto.identifier})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
|
}
|
||||||
|
const entry = new Activity(
|
||||||
|
proto.name,
|
||||||
|
proto.state,
|
||||||
|
proto.visible,
|
||||||
|
proto.frontOfTask,
|
||||||
|
proto.procId,
|
||||||
|
proto.translucent,
|
||||||
|
parent,
|
||||||
|
windowContainer
|
||||||
|
)
|
||||||
|
|
||||||
|
proto.windowToken.windowContainer.children.reverse()
|
||||||
|
.map(it => WindowContainer.childrenFromProto(entry, it, /* isActivityInTree */ true))
|
||||||
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.shortName = shortenName(entry.name)
|
||||||
|
entry.children = entry.childrenWindows
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Activity
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020, The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
ActivityRecord,
|
|
||||||
} from "../common"
|
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowToken from "./WindowToken"
|
|
||||||
|
|
||||||
export class ActivityRecordMixin {
|
|
||||||
get kind() {
|
|
||||||
return "DisplayArea"
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromProto(proto) {
|
|
||||||
const windowToken = WindowToken.fromProto(proto.windowToken)
|
|
||||||
|
|
||||||
const activityRecord = new ActivityRecord(windowToken)
|
|
||||||
|
|
||||||
const obj = Object.assign({}, proto)
|
|
||||||
delete proto.windowToken
|
|
||||||
Object.assign(obj, windowToken.obj)
|
|
||||||
activityRecord.attachObject(obj)
|
|
||||||
|
|
||||||
return activityRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyMixins(ActivityRecord, [ActivityRecordMixin])
|
|
||||||
|
|
||||||
export default ActivityRecord
|
|
||||||
62
tools/winscope/src/flickerlib/windows/ActivityTask.ts
Normal file
62
tools/winscope/src/flickerlib/windows/ActivityTask.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
|
import { ActivityTask, toRect } from "../common"
|
||||||
|
import WindowContainer from "./WindowContainer"
|
||||||
|
|
||||||
|
ActivityTask.fromProto = function (proto, isActivityInTree: Boolean): ActivityTask {
|
||||||
|
if (proto == null) {
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
const windowContainer = WindowContainer.fromProto({proto: proto.windowContainer})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
|
}
|
||||||
|
const entry = new ActivityTask(
|
||||||
|
proto.activityType,
|
||||||
|
proto.fillsParent,
|
||||||
|
toRect(proto.bounds),
|
||||||
|
proto.id,
|
||||||
|
proto.rootTaskId,
|
||||||
|
proto.displayId,
|
||||||
|
toRect(proto.lastNonFullscreenBounds),
|
||||||
|
proto.realActivity,
|
||||||
|
proto.origActivity,
|
||||||
|
proto.resizeMode,
|
||||||
|
proto.resumedActivity?.title ?? "",
|
||||||
|
proto.animatingBounds,
|
||||||
|
proto.surfaceWidth,
|
||||||
|
proto.surfaceHeight,
|
||||||
|
proto.createdByOrganizer,
|
||||||
|
proto.minWidth,
|
||||||
|
proto.minHeight,
|
||||||
|
windowContainer
|
||||||
|
)
|
||||||
|
|
||||||
|
proto.windowContainer.children.reverse()
|
||||||
|
.map(it => WindowContainer.childrenFromProto(entry, it, isActivityInTree))
|
||||||
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.shortName = shortenName(entry.name)
|
||||||
|
entry.children = entry.childrenWindows
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActivityTask
|
||||||
@@ -14,34 +14,30 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
DisplayArea,
|
import { DisplayArea } from "../common"
|
||||||
} from "../common"
|
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowContainer from "./WindowContainer"
|
import WindowContainer from "./WindowContainer"
|
||||||
|
|
||||||
export class DisplayAreaMixin {
|
DisplayArea.fromProto = function (proto, isActivityInTree: Boolean): DisplayArea {
|
||||||
get kind() {
|
if (proto == null) {
|
||||||
return "DisplayArea"
|
return null
|
||||||
|
} else {
|
||||||
|
const windowContainer = WindowContainer.fromProto({proto: proto.windowContainer, nameOverride: proto.name})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
}
|
}
|
||||||
|
const entry = new DisplayArea(proto.isTaskDisplayArea, windowContainer)
|
||||||
|
|
||||||
static fromProto(proto) {
|
proto.windowContainer.children.reverse()
|
||||||
const windowContainer = WindowContainer.fromProto(proto.windowContainer,
|
.map(it => WindowContainer.childrenFromProto(entry, it, isActivityInTree))
|
||||||
null)
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
const displayArea = new DisplayArea(windowContainer)
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.shortName = shortenName(entry.name)
|
||||||
const obj = Object.assign({}, proto)
|
entry.children = entry.childrenWindows
|
||||||
delete obj.windowContainer
|
return entry
|
||||||
Object.assign(obj, windowContainer.obj)
|
|
||||||
displayArea.attachObject(obj)
|
|
||||||
|
|
||||||
return displayArea
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMixins(DisplayArea, [DisplayAreaMixin])
|
|
||||||
|
|
||||||
export default DisplayArea
|
export default DisplayArea
|
||||||
|
|||||||
@@ -14,50 +14,57 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
DisplayContent,
|
import { toRect, DisplayContent, Rect } from "../common"
|
||||||
Bounds
|
|
||||||
} from "../common"
|
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowContainer from "./WindowContainer"
|
import WindowContainer from "./WindowContainer"
|
||||||
import DisplayArea from "./DisplayArea"
|
|
||||||
|
|
||||||
export class DisplayContentMixin {
|
DisplayContent.fromProto = function (proto, isActivityInTree: Boolean): DisplayContent {
|
||||||
get kind() {
|
if (proto == null) {
|
||||||
return "DisplayContent"
|
return null
|
||||||
}
|
|
||||||
|
|
||||||
static fromProto(proto) {
|
|
||||||
let rootDisplayArea;
|
|
||||||
if (proto.rootDisplayArea.windowContainer == null) {
|
|
||||||
// For backward compatibility
|
|
||||||
const windowContainer = WindowContainer.fromProto(proto.windowContainer,
|
|
||||||
null)
|
|
||||||
rootDisplayArea = new DisplayArea(windowContainer)
|
|
||||||
} else {
|
} else {
|
||||||
// New protos should always be using this
|
const windowContainer = WindowContainer.fromProto({proto: proto.rootDisplayArea.windowContainer,
|
||||||
rootDisplayArea = DisplayArea.fromProto(proto.rootDisplayArea)
|
nameOverride: proto.displayInfo?.name ?? null})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
const bounds = new Bounds(
|
const displayRectWidth = proto.displayInfo?.logicalWidth ?? 0
|
||||||
proto.displayInfo.logicalWidth || 0,
|
const displayRectHeight = proto.displayInfo?.logicalHeight ?? 0
|
||||||
proto.displayInfo.logicalHeight || 0,
|
const appRectWidth = proto.displayInfo?.appWidth ?? 0
|
||||||
|
const appRectHeight = proto.displayInfo?.appHeight ?? 0
|
||||||
|
|
||||||
|
const defaultBounds = proto.pinnedStackController?.defaultBounds ?? null
|
||||||
|
const movementBounds = proto.pinnedStackController?.movementBounds ?? null
|
||||||
|
|
||||||
|
const entry = new DisplayContent(
|
||||||
|
proto.id,
|
||||||
|
proto.focusedRootTaskId,
|
||||||
|
proto.resumedActivity?.title ?? "",
|
||||||
|
proto.singleTaskInstance,
|
||||||
|
toRect(defaultBounds),
|
||||||
|
toRect(movementBounds),
|
||||||
|
new Rect(0, 0, displayRectWidth, displayRectHeight),
|
||||||
|
new Rect(0, 0, appRectWidth, appRectHeight),
|
||||||
|
proto.dpi,
|
||||||
|
proto.displayInfo?.flags ?? 0,
|
||||||
|
toRect(proto.displayFrames.stableBounds),
|
||||||
|
proto.surfaceSize,
|
||||||
|
proto.focusedApp,
|
||||||
|
proto.appTransition?.lastUsedAppTransition ?? "",
|
||||||
|
proto.appTransition?.appTransitionState ?? "",
|
||||||
|
windowContainer
|
||||||
)
|
)
|
||||||
|
|
||||||
const displayContent = new DisplayContent(rootDisplayArea, bounds)
|
proto.rootDisplayArea.windowContainer.children.reverse()
|
||||||
|
.map(it => WindowContainer.childrenFromProto(entry, it, isActivityInTree))
|
||||||
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
const obj = Object.assign({}, proto)
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
delete obj.windowContainer
|
entry.shortName = shortenName(entry.name)
|
||||||
delete obj.rootDisplayArea
|
entry.children = entry.childrenWindows
|
||||||
Object.assign(obj, rootDisplayArea.obj)
|
return entry
|
||||||
displayContent.attachObject(obj)
|
|
||||||
|
|
||||||
return displayContent
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMixins(DisplayContent, [DisplayContentMixin])
|
|
||||||
|
|
||||||
export default DisplayContent
|
export default DisplayContent
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020, The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { RootDisplayArea } from "../common"
|
|
||||||
import DisplayArea from "./DisplayArea"
|
|
||||||
|
|
||||||
RootDisplayArea.fromProto = DisplayArea.fromProto
|
|
||||||
|
|
||||||
export default DisplayArea
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020, The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Task } from "../common"
|
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowContainer from "./WindowContainer"
|
|
||||||
|
|
||||||
export class TaskMixin {
|
|
||||||
get kind() {
|
|
||||||
return "Task"
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromProto(proto) {
|
|
||||||
const windowContainer = WindowContainer.fromProto(proto.windowContainer,
|
|
||||||
null)
|
|
||||||
|
|
||||||
const task = new Task(windowContainer)
|
|
||||||
|
|
||||||
const obj = Object.assign({}, proto)
|
|
||||||
delete obj.windowContainer
|
|
||||||
Object.assign(obj, windowContainer.obj)
|
|
||||||
task.attachObject(obj)
|
|
||||||
|
|
||||||
return task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyMixins(Task, [TaskMixin])
|
|
||||||
|
|
||||||
export default Task
|
|
||||||
@@ -14,192 +14,105 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WindowContainer } from "../common"
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
import {
|
||||||
|
Configuration,
|
||||||
import IClickableTreeViewElement from '../treeview/IClickableTreeViewElement'
|
ConfigurationContainer,
|
||||||
import { TreeViewObject } from '../treeview/types'
|
toRect,
|
||||||
|
WindowConfiguration,
|
||||||
|
WindowContainer,
|
||||||
|
WindowContainerChild,
|
||||||
|
} from "../common"
|
||||||
|
|
||||||
|
import Activity from "./Activity"
|
||||||
import DisplayArea from "./DisplayArea"
|
import DisplayArea from "./DisplayArea"
|
||||||
import DisplayContent from "./DisplayContent"
|
import DisplayContent from "./DisplayContent"
|
||||||
import Task from "./Task"
|
import ActivityTask from "./ActivityTask"
|
||||||
import ActivityRecord from "./ActivityRecord"
|
|
||||||
import WindowToken from "./WindowToken"
|
|
||||||
import WindowState from "./WindowState"
|
import WindowState from "./WindowState"
|
||||||
|
import WindowToken from "./WindowToken"
|
||||||
|
|
||||||
import { CompatibleFeatures } from '@/utils/compatibility.js'
|
WindowContainer.fromProto = function ({
|
||||||
|
proto,
|
||||||
export class WindowContainerMixin implements IClickableTreeViewElement {
|
nameOverride = null,
|
||||||
title: string
|
identifierOverride = null,
|
||||||
windowHashCode: number
|
tokenOverride = null
|
||||||
childrenWindows
|
}): WindowContainer {
|
||||||
visible: boolean
|
if (proto == null) {
|
||||||
rawTreeViewObject
|
|
||||||
|
|
||||||
_obj: { name: string }
|
|
||||||
_children
|
|
||||||
|
|
||||||
get kind() {
|
|
||||||
return "WindowContainer"
|
|
||||||
}
|
|
||||||
|
|
||||||
get name() {
|
|
||||||
if (this.obj && this.obj.name) {
|
|
||||||
return this.obj.name
|
|
||||||
}
|
|
||||||
|
|
||||||
if (["WindowContainer", "Task"].includes(this.title)) {
|
|
||||||
return null
|
return null
|
||||||
}
|
} else {
|
||||||
|
const identifier = identifierOverride ?? proto.identifier
|
||||||
|
var name = nameOverride ?? identifier?.title ?? ""
|
||||||
|
var token = tokenOverride?.toString(16) ?? identifier?.hashCode?.toString(16) ?? ""
|
||||||
|
|
||||||
return `${removeRedundancyInName(this.title)}@${this.windowHashCode}`
|
const entry = new WindowContainer(
|
||||||
}
|
name,
|
||||||
|
token,
|
||||||
|
proto.orientation,
|
||||||
|
proto.visible,
|
||||||
|
newConfigurationContainer(proto.configurationContainer)
|
||||||
|
)
|
||||||
|
|
||||||
get shortName() {
|
|
||||||
return this.name ? shortenName(this.name) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get stableId() {
|
|
||||||
return this.windowHashCode
|
|
||||||
}
|
|
||||||
|
|
||||||
get children() {
|
|
||||||
return this._children ?? this.childrenWindows
|
|
||||||
}
|
|
||||||
|
|
||||||
set children(children) {
|
|
||||||
this._children = children
|
|
||||||
}
|
|
||||||
|
|
||||||
get chips() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
set obj(obj) {
|
|
||||||
this._obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
get obj() {
|
|
||||||
return this._obj
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromProto(proto, parent_identifier) {
|
|
||||||
const children = proto.children.map(
|
|
||||||
child => transformWindowContainerChildProto(child))
|
|
||||||
|
|
||||||
// A kind of hacky way to check if the proto is from a device which
|
|
||||||
// didn't have the changes required for the diff viewer to work properly
|
|
||||||
// We required that all elements have a stable identifier in order to do the
|
|
||||||
// diff properly. In theory properties diff would still work, but are
|
|
||||||
// currently disabled. If required in the future don't hesitate to make
|
|
||||||
// the required changes.
|
|
||||||
if (!proto.identifier) {
|
|
||||||
CompatibleFeatures.DiffVisualization = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fallback_title = parent_identifier?.title ?? ""
|
|
||||||
const fallback_hashCode = parent_identifier?.hashCode ?? ""
|
|
||||||
const title = proto.identifier?.title ?? fallback_title
|
|
||||||
const hashCode = proto.identifier?.hashCode ?? fallback_hashCode
|
|
||||||
const visible = proto.visible
|
|
||||||
const windowContainer =
|
|
||||||
new WindowContainer(children, title, hashCode, visible)
|
|
||||||
|
|
||||||
const obj = Object.assign({}, proto)
|
|
||||||
// we remove the children property from the object to avoid it showing the
|
// we remove the children property from the object to avoid it showing the
|
||||||
// the properties view of the element as we can always see those elements'
|
// the properties view of the element as we can always see those elements'
|
||||||
// properties by changing the target element in the hierarchy tree view.
|
// properties by changing the target element in the hierarchy tree view.
|
||||||
delete obj.children
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
windowContainer.attachObject(obj)
|
entry.shortName = shortenName(entry.name)
|
||||||
|
return entry
|
||||||
return windowContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
attachObject(obj) {
|
|
||||||
this._obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
asRawTreeViewObject(): TreeViewObject {
|
|
||||||
// IMPORTANT: We want to always return the same tree view object and not
|
|
||||||
// generate a new one every time this function is called.
|
|
||||||
if (!this.rawTreeViewObject) {
|
|
||||||
const children = this.children.map(child => child.asRawTreeViewObject())
|
|
||||||
|
|
||||||
this.rawTreeViewObject = {
|
|
||||||
kind: this.kind,
|
|
||||||
name: this.name,
|
|
||||||
shortName: this.shortName,
|
|
||||||
stableId: this.stableId,
|
|
||||||
chips: this.chips,
|
|
||||||
obj: this.obj,
|
|
||||||
children,
|
|
||||||
ref: this,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.rawTreeViewObject;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMixins(WindowContainer, [WindowContainerMixin])
|
WindowContainer.childrenFromProto = function(parent: WindowContainer, proto, isActivityInTree: Boolean): WindowContainerChild {
|
||||||
|
return new WindowContainerChild(
|
||||||
function transformWindowContainerChildProto(proto) {
|
DisplayContent.fromProto(proto.displayContent, isActivityInTree),
|
||||||
if (proto.displayArea != null) {
|
DisplayArea.fromProto(proto.displayArea, isActivityInTree),
|
||||||
return DisplayArea.fromProto(proto.displayArea)
|
ActivityTask.fromProto(proto.task, isActivityInTree),
|
||||||
}
|
Activity.fromProto(proto.activity, parent),
|
||||||
|
WindowToken.fromProto(proto.windowToken, isActivityInTree),
|
||||||
if (proto.displayContent != null) {
|
WindowState.fromProto(proto.window, isActivityInTree),
|
||||||
return DisplayContent.fromProto(proto.displayContent)
|
WindowContainer.fromProto({proto: proto.windowContainer})
|
||||||
}
|
)
|
||||||
|
|
||||||
if (proto.task != null) {
|
|
||||||
return Task.fromProto(proto.task)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto.activity != null) {
|
|
||||||
return ActivityRecord.fromProto(proto.activity)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto.windowToken != null) {
|
|
||||||
return WindowToken.fromProto(proto.windowToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto.window != null) {
|
|
||||||
return WindowState.fromProto(proto.window)
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Unhandled WindowContainerChildProto case...")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeRedundancyInName(name: string): string {
|
function newConfigurationContainer(proto): ConfigurationContainer {
|
||||||
if (!name.includes('/')) {
|
const entry = new ConfigurationContainer(
|
||||||
return name
|
newConfiguration(proto?.overrideConfiguration ?? null),
|
||||||
}
|
newConfiguration(proto?.fullConfiguration ?? null),
|
||||||
|
newConfiguration(proto?.mergedOverrideConfiguration ?? null)
|
||||||
|
)
|
||||||
|
|
||||||
const split = name.split('/')
|
entry.kind = "ConfigurationContainer"
|
||||||
const pkg = split[0]
|
entry.obj = entry
|
||||||
var clazz = split.slice(1).join("/")
|
return entry
|
||||||
|
|
||||||
if (clazz.startsWith("$pkg.")) {
|
|
||||||
clazz = clazz.slice(pkg.length + 1)
|
|
||||||
|
|
||||||
return "$pkg/$clazz"
|
|
||||||
}
|
|
||||||
|
|
||||||
return name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shortenName(name: string): string {
|
function newConfiguration(proto): Configuration {
|
||||||
const classParts = name.split(".")
|
var windowConfiguration = null
|
||||||
|
|
||||||
if (classParts.length <= 3) {
|
if (proto != null && proto.windowConfiguration != null) {
|
||||||
return name
|
windowConfiguration = newWindowConfiguration(proto.windowConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
const className = classParts.slice(-1)[0] // last element
|
return new Configuration(
|
||||||
|
windowConfiguration,
|
||||||
|
proto?.densityDpi ?? 0,
|
||||||
|
proto?.orientation ?? 0,
|
||||||
|
proto?.screenHeightDp ?? 0,
|
||||||
|
proto?.screenHeightDp ?? 0,
|
||||||
|
proto?.smallestScreenWidthDp ?? 0,
|
||||||
|
proto?.screenLayout ?? 0,
|
||||||
|
proto?.uiMode ?? 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return `${classParts[0]}.${classParts[1]}.(...).${className}`
|
function newWindowConfiguration(proto): WindowConfiguration {
|
||||||
|
return new WindowConfiguration(
|
||||||
|
toRect(proto.appBounds),
|
||||||
|
toRect(proto.bounds),
|
||||||
|
toRect(proto.maxBounds),
|
||||||
|
proto.windowingMode,
|
||||||
|
proto.activityType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WindowContainer
|
export default WindowContainer
|
||||||
|
|||||||
@@ -14,43 +14,75 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WindowState, Rect } from "../common"
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
|
import { toRect, WindowState } from "../common"
|
||||||
import { VISIBLE_CHIP } from '../treeview/Chips'
|
import { VISIBLE_CHIP } from '../treeview/Chips'
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowContainer from "./WindowContainer"
|
import WindowContainer from "./WindowContainer"
|
||||||
|
|
||||||
export class WindowStateMixin {
|
WindowState.fromProto = function (proto, isActivityInTree: Boolean): WindowState {
|
||||||
visible: boolean
|
if (proto == null) {
|
||||||
|
return null
|
||||||
get kind() {
|
} else {
|
||||||
return "WindowState"
|
const identifierName = proto.windowContainer.identifier?.title ?? proto.identifier?.title ?? ""
|
||||||
|
var windowType = 0
|
||||||
|
if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) {
|
||||||
|
windowType = WindowState.WINDOW_TYPE_STARTING
|
||||||
|
} else if (proto.animatingExit) {
|
||||||
|
windowType = WindowState.WINDOW_TYPE_EXITING
|
||||||
|
} else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) {
|
||||||
|
windowType = WindowState.WINDOW_TYPE_STARTING
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromProto(proto) {
|
var nameOverride = identifierName
|
||||||
const windowContainer = WindowContainer.fromProto(proto.windowContainer,
|
|
||||||
proto.identifier)
|
|
||||||
|
|
||||||
const frame = (proto.windowFrames ?? proto).frame ?? {}
|
if (identifierName.startsWith(WindowState.STARTING_WINDOW_PREFIX)) {
|
||||||
const rect = new Rect(frame.left ?? 0, frame.top ?? 0, frame.right ?? 0, frame.bottom ?? 0)
|
nameOverride = identifierName.substring(WindowState.STARTING_WINDOW_PREFIX.length)
|
||||||
|
} else if (identifierName.startsWith(WindowState.DEBUGGER_WINDOW_PREFIX)) {
|
||||||
const windowState =
|
nameOverride = identifierName.substring(WindowState.DEBUGGER_WINDOW_PREFIX.length)
|
||||||
new WindowState(windowContainer, /* childWindows */[], rect)
|
|
||||||
|
|
||||||
const obj = Object.assign({}, proto)
|
|
||||||
Object.assign(obj, windowContainer.obj)
|
|
||||||
delete obj.windowContainer
|
|
||||||
windowState.attachObject(obj)
|
|
||||||
|
|
||||||
return windowState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get chips() {
|
const windowContainer = WindowContainer.fromProto({
|
||||||
return this.visible ? [VISIBLE_CHIP] : []
|
proto: proto.windowContainer,
|
||||||
|
nameOverride: nameOverride,
|
||||||
|
identifierOverride: proto.identifier})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.windowContainer.children.reverse()
|
||||||
|
.map(it => WindowContainer.childrenFromProto(entry, it, isActivityInTree))
|
||||||
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
|
const entry = new WindowState(
|
||||||
|
proto.attributes?.type ?? 0,
|
||||||
|
proto.displayId,
|
||||||
|
proto.stackId,
|
||||||
|
proto.animator?.surface?.layer ?? 0,
|
||||||
|
proto.animator?.surface?.shown ?? false,
|
||||||
|
windowType,
|
||||||
|
toRect(proto.windowFrames?.frame ?? null),
|
||||||
|
toRect(proto.windowFrames?.containingFrame ?? null),
|
||||||
|
toRect(proto.windowFrames?.parentFrame ?? null),
|
||||||
|
toRect(proto.windowFrames?.contentFrame ?? null),
|
||||||
|
toRect(proto.windowFrames?.contentInsets ?? null),
|
||||||
|
toRect(proto.surfaceInsets),
|
||||||
|
toRect(proto.givenContentInsets),
|
||||||
|
toRect(proto.animator?.lastClipRect ?? null),
|
||||||
|
windowContainer,
|
||||||
|
/* isAppWindow */ isActivityInTree
|
||||||
|
)
|
||||||
|
|
||||||
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.shortName = shortenName(entry.name)
|
||||||
|
entry.visible = entry.isVisible ?? false
|
||||||
|
entry.chips = entry.isVisible ? [VISIBLE_CHIP] : []
|
||||||
|
entry.children = entry.childrenWindows
|
||||||
|
if (entry.isVisible) {
|
||||||
|
entry.rect = entry.rects[0]
|
||||||
|
}
|
||||||
|
return entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMixins(WindowState, [WindowStateMixin])
|
|
||||||
|
|
||||||
export default WindowState
|
export default WindowState
|
||||||
|
|||||||
@@ -14,32 +14,30 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { getWMPropertiesForDisplay, shortenName } from '../mixin'
|
||||||
import { WindowToken } from "../common"
|
import { WindowToken } from "../common"
|
||||||
|
|
||||||
import { applyMixins } from '../mixin'
|
|
||||||
|
|
||||||
import WindowContainer from "./WindowContainer"
|
import WindowContainer from "./WindowContainer"
|
||||||
|
|
||||||
export class WindowContainerMixin {
|
WindowToken.fromProto = function (proto, isActivityInTree: Boolean): WindowToken {
|
||||||
get kind() {
|
if (proto == null) {
|
||||||
return "WindowToken"
|
return null
|
||||||
|
} else {
|
||||||
|
const windowContainer = WindowContainer.fromProto({proto: proto.windowContainer, tokenOverride: proto.hashCode})
|
||||||
|
if (windowContainer == null) {
|
||||||
|
throw "Window container should not be null: " + JSON.stringify(proto)
|
||||||
}
|
}
|
||||||
|
const entry = new WindowToken(windowContainer)
|
||||||
|
|
||||||
static fromProto(proto) {
|
proto.windowContainer.children.reverse()
|
||||||
const windowContainer = WindowContainer.fromProto(proto.windowContainer,
|
.map(it => WindowContainer.childrenFromProto(entry, it, isActivityInTree))
|
||||||
null)
|
.filter(it => it != null)
|
||||||
|
.forEach(it => windowContainer.childContainers.push(it))
|
||||||
|
|
||||||
const windowToken = new WindowToken(windowContainer)
|
entry.obj = getWMPropertiesForDisplay(proto)
|
||||||
|
entry.shortName = shortenName(entry.name)
|
||||||
const obj = Object.assign({}, proto)
|
entry.children = entry.childrenWindows
|
||||||
Object.assign(obj, windowContainer.obj)
|
return entry
|
||||||
delete obj.windowContainer
|
|
||||||
windowToken.attachObject(obj)
|
|
||||||
|
|
||||||
return windowToken
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMixins(WindowToken, [WindowContainerMixin])
|
|
||||||
|
|
||||||
export default WindowToken
|
export default WindowToken
|
||||||
|
|||||||
@@ -373,6 +373,11 @@ function getIntFlagsAsStrings(intFlags, annotationType) {
|
|||||||
|
|
||||||
const mapping = intDefMapping[annotationType].values;
|
const mapping = intDefMapping[annotationType].values;
|
||||||
|
|
||||||
|
if (mapping.length == 0) {
|
||||||
|
console.warn("No mapping for type", annotationType)
|
||||||
|
return intFlags + ""
|
||||||
|
}
|
||||||
|
|
||||||
// Will only contain bits that have not been associated with a flag.
|
// Will only contain bits that have not been associated with a flag.
|
||||||
let leftOver = intFlags;
|
let leftOver = intFlags;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user