diff --git a/tools/winscope/adb_proxy/winscope_proxy.py b/tools/winscope/adb_proxy/winscope_proxy.py index 5bfc531e2..8c16e9647 100755 --- a/tools/winscope/adb_proxy/winscope_proxy.py +++ b/tools/winscope/adb_proxy/winscope_proxy.py @@ -55,6 +55,14 @@ WINSCOPE_TOKEN_HEADER = "Winscope-Token" # Location to save the proxy security token WINSCOPE_TOKEN_LOCATION = os.path.expanduser('~/.config/winscope/.token') +# Winscope traces extensions +WINSCOPE_EXT = ".winscope" +WINSCOPE_EXT_LEGACY = ".pb" +WINSCOPE_EXTS = [WINSCOPE_EXT, WINSCOPE_EXT_LEGACY] + +# Winscope traces directory +WINSCOPE_DIR = "/data/misc/wmtrace/" + # Max interval between the client keep-alive requests in seconds KEEP_ALIVE_INTERVAL_S = 5 @@ -85,12 +93,29 @@ class FileMatcher: matchingFiles = call_adb( f"shell su root find {self.path} -name {self.matcher}", device_id) + log.debug("Found file %s", matchingFiles.split('\n')[:-1]) return matchingFiles.split('\n')[:-1] def get_filetype(self): return self.type +class WinscopeFileMatcher(FileMatcher): + def __init__(self, path, matcher, filetype) -> None: + self.path = path + self.internal_matchers = list(map(lambda ext: FileMatcher(path, f'{matcher}{ext}', filetype), + WINSCOPE_EXTS)) + self.type = filetype + + def get_filepaths(self, device_id): + for matcher in self.internal_matchers: + files = matcher.get_filepaths(device_id) + if len(files) > 0: + return files + log.debug("No files found") + return [] + + class TraceTarget: """Defines a single parameter to trace. @@ -111,51 +136,50 @@ class TraceTarget: # Order of files matters as they will be expected in that order and decoded in that order TRACE_TARGETS = { "window_trace": TraceTarget( - File("/data/misc/wmtrace/wm_trace.pb", "window_trace"), + WinscopeFileMatcher(WINSCOPE_DIR, "wm_trace", "window_trace"), 'su root cmd window tracing start\necho "WM trace started."', 'su root cmd window tracing stop >/dev/null 2>&1' ), "accessibility_trace": TraceTarget( - File("/data/misc/a11ytrace/a11y_trace.pb", "accessibility_trace"), + WinscopeFileMatcher("/data/misc/a11ytrace", "a11y_trace", "accessibility_trace"), 'su root cmd accessibility start-trace\necho "Accessibility trace started."', 'su root cmd accessibility stop-trace >/dev/null 2>&1' ), "layers_trace": TraceTarget( - File("/data/misc/wmtrace/layers_trace.pb", "layers_trace"), + WinscopeFileMatcher(WINSCOPE_DIR, "layers_trace", "layers_trace"), 'su root service call SurfaceFlinger 1025 i32 1\necho "SF trace started."', 'su root service call SurfaceFlinger 1025 i32 0 >/dev/null 2>&1' ), "screen_recording": TraceTarget( - File("/data/local/tmp/screen.winscope.mp4", "screen_recording"), - 'screenrecord --bit-rate 8M /data/local/tmp/screen.winscope.mp4 >/dev/null 2>&1 &\necho "ScreenRecorder started."', + File(f'/data/local/tmp/screen.mp4', "screen_recording"), + f'screenrecord --bit-rate 8M /data/local/tmp/screen.mp4 >/dev/null 2>&1 &\necho "ScreenRecorder started."', 'pkill -l SIGINT screenrecord >/dev/null 2>&1' ), "transaction": TraceTarget( [ - File("/data/misc/wmtrace/transaction_trace.pb", "transactions"), - FileMatcher("/data/misc/wmtrace/", "transaction_merges_*.pb", - "transaction_merges"), + WinscopeFileMatcher(WINSCOPE_DIR, "transaction_trace", "transactions"), + FileMatcher(WINSCOPE_DIR, f'transaction_merges_*', "transaction_merges"), ], 'su root service call SurfaceFlinger 1020 i32 1\necho "SF transactions recording started."', 'su root service call SurfaceFlinger 1020 i32 0 >/dev/null 2>&1' ), "proto_log": TraceTarget( - File("/data/misc/wmtrace/wm_log.pb", "proto_log"), + WinscopeFileMatcher(WINSCOPE_DIR, "wm_log", "proto_log"), 'su root cmd window logging start\necho "WM logging started."', 'su root cmd window logging stop >/dev/null 2>&1' ), "ime_trace_clients": TraceTarget( - File("/data/misc/wmtrace/ime_trace_clients.pb", "ime_trace_clients"), + WinscopeFileMatcher(WINSCOPE_DIR, "ime_trace_clients", "ime_trace_clients"), 'su root ime tracing start\necho "Clients IME trace started."', 'su root ime tracing stop >/dev/null 2>&1' ), "ime_trace_service": TraceTarget( - File("/data/misc/wmtrace/ime_trace_service.pb", "ime_trace_service"), + WinscopeFileMatcher(WINSCOPE_DIR, "ime_trace_service", "ime_trace_service"), 'su root ime tracing start\necho "Service IME trace started."', 'su root ime tracing stop >/dev/null 2>&1' ), "ime_trace_managerservice": TraceTarget( - File("/data/misc/wmtrace/ime_trace_managerservice.pb", "ime_trace_managerservice"), + WinscopeFileMatcher(WINSCOPE_DIR, "ime_trace_managerservice", "ime_trace_managerservice"), 'su root ime tracing start\necho "ManagerService IME trace started."', 'su root ime tracing stop >/dev/null 2>&1' ), @@ -204,12 +228,12 @@ class DumpTarget: DUMP_TARGETS = { "window_dump": DumpTarget( - File("/data/local/tmp/wm_dump.pb", "window_dump"), - 'su root dumpsys window --proto > /data/local/tmp/wm_dump.pb' + File(f'/data/local/tmp/wm_dump{WINSCOPE_EXT}', "window_dump"), + f'su root dumpsys window --proto > /data/local/tmp/wm_dump{WINSCOPE_EXT}' ), "layers_dump": DumpTarget( - File("/data/local/tmp/sf_dump.pb", "layers_dump"), - 'su root dumpsys SurfaceFlinger --proto > /data/local/tmp/sf_dump.pb' + File(f'/data/local/tmp/sf_dump{WINSCOPE_EXT}', "layers_dump"), + f'su root dumpsys SurfaceFlinger --proto > /data/local/tmp/sf_dump{WINSCOPE_EXT}' ) } @@ -425,6 +449,9 @@ class FetchFilesEndpoint(DeviceRequestEndpoint): buf = base64.encodebytes(tmp.read()).decode("utf-8") file_buffers[file_type].append(buf) + if (len(file_buffers) == 0): + log.error("Proxy didn't find any file to fetch") + # server.send_header('X-Content-Type-Options', 'nosniff') # add_standard_headers(server) j = json.dumps(file_buffers) diff --git a/tools/winscope/spec/DiffSpec.js b/tools/winscope/spec/DiffSpec.js index 68dfa4e82..a0600a263 100644 --- a/tools/winscope/spec/DiffSpec.js +++ b/tools/winscope/spec/DiffSpec.js @@ -1,10 +1,24 @@ import { DiffGenerator, DiffType } from "../src/utils/diff.js"; import { Node, DiffNode, toPlainObject } from "./utils/tree.js"; +const treeOne = new Node({ id: 1 }, [ + new Node({ id: 2 }, []), + new Node({ id: 3 }, []), + new Node({ id: 4 }, []), +]); +const treeTwo = new Node({ id: 1 }, [ + new Node({ id: 2 }, []), + new Node({ id: 3 }, [ + new Node({ id: 5 }, []), + ]), + new Node({ id: 4 }, []), +]); + function checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree) { const diffTree = new DiffGenerator(newTree) .compareWith(oldTree) .withUniqueNodeId(node => node.id) + .withModifiedCheck(() => false) .generateDiffTree(); expect(diffTree).toEqual(expectedDiffTree); @@ -12,25 +26,8 @@ function checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree) { describe("DiffGenerator", () => { it("can generate a simple add diff", () => { - const oldTree = new Node({ id: 1 }, [ - new Node({ id: 2 }, []), - new Node({ id: 3 }, []), - new Node({ id: 4 }, []), - ]); - - const newTree = new Node({ id: 1 }, [ - new Node({ id: 2 }, []), - new Node({ id: 3 }, [ - new Node({ id: 5 }, []), - ]), - new Node({ id: 4 }, []), - ]); - - const diffTree = new DiffGenerator(newTree) - .compareWith(oldTree) - .withUniqueNodeId(node => node.id) - .withModifiedCheck(() => false) - .generateDiffTree(); + const oldTree = treeOne; + const newTree = treeTwo; const expectedDiffTree = toPlainObject( new DiffNode({ id: 1 }, DiffType.NONE, [ @@ -46,19 +43,8 @@ describe("DiffGenerator", () => { }); it("can generate a simple delete diff", () => { - const oldTree = new Node({ id: 1 }, [ - new Node({ id: 2 }, []), - new Node({ id: 3 }, [ - new Node({ id: 5 }, []), - ]), - new Node({ id: 4 }, []), - ]); - - const newTree = new Node({ id: 1 }, [ - new Node({ id: 2 }, []), - new Node({ id: 3 }, []), - new Node({ id: 4 }, []), - ]); + const oldTree = treeTwo; + const newTree = treeOne; const expectedDiffTree = toPlainObject( new DiffNode({ id: 1 }, DiffType.NONE, [ @@ -74,13 +60,7 @@ describe("DiffGenerator", () => { }); it("can generate a simple move diff", () => { - const oldTree = new Node({ id: 1 }, [ - new Node({ id: 2 }, []), - new Node({ id: 3 }, [ - new Node({ id: 5 }, []), - ]), - new Node({ id: 4 }, []), - ]); + const oldTree = treeTwo; const newTree = new Node({ id: 1 }, [ new Node({ id: 2 }, []), @@ -264,4 +244,4 @@ describe("DiffGenerator", () => { checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope/spec/ObjectTransformerSpec.js b/tools/winscope/spec/ObjectTransformerSpec.js index 4d84fd951..ab2a4c7c2 100644 --- a/tools/winscope/spec/ObjectTransformerSpec.js +++ b/tools/winscope/spec/ObjectTransformerSpec.js @@ -1,32 +1,6 @@ import { DiffType } from "../src/utils/diff.js"; import { ObjectTransformer } from "../src/transform.js"; -import { Node, DiffNode, toPlainObject } from "./utils/tree.js"; - -class ObjNode extends Node { - constructor(name, children, combined) { - const nodeDef = { - kind: '', - name: name, - }; - if (combined) { - nodeDef.combined = true; - } - super(nodeDef, children); - } -} - -class ObjDiffNode extends DiffNode { - constructor(name, diffType, children, combined) { - const nodeDef = { - kind: '', - name: name, - }; - if (combined) { - nodeDef.combined = true; - } - super(nodeDef, diffType, children); - } -} +import { ObjNode, ObjDiffNode, toPlainObject } from "./utils/tree.js"; describe("ObjectTransformer", () => { it("can transform a simple object", () => { @@ -46,19 +20,19 @@ describe("ObjectTransformer", () => { const expectedTransformedObj = toPlainObject( new ObjNode('root', [ new ObjNode('obj', [ - new ObjNode('string: string', [], true), - new ObjNode('number: 3', [], true), - ]), + new ObjNode('string: string', [], true, 'root.obj.string'), + new ObjNode('number: 3', [], true, 'root.obj.number'), + ], undefined, 'root.obj'), new ObjNode('array', [ new ObjNode('0', [ - new ObjNode('nested: item', [], true), - ]), - new ObjNode("1: two", [], true), - ]), - ]) + new ObjNode('nested: item', [], true, 'root.array.0.nested'), + ], undefined, 'root.array.0'), + new ObjNode("1: two", [], true, 'root.array.1'), + ], undefined, 'root.array'), + ], undefined, 'root') ); - const transformedObj = new ObjectTransformer(obj, 'root') + const transformedObj = new ObjectTransformer(obj, 'root', 'root') .setOptions({ formatter: () => { } }) .transform(); @@ -75,12 +49,12 @@ describe("ObjectTransformer", () => { const expectedTransformedObj = toPlainObject( new ObjNode('root', [ new ObjNode('obj', [ - new ObjNode('null: null', [], true), - ]), - ]) + new ObjNode('null: null', [], true, 'root.obj.null'), + ], undefined, 'root.obj'), + ], undefined, 'root') ); - const transformedObj = new ObjectTransformer(obj, 'root') + const transformedObj = new ObjectTransformer(obj, 'root', 'root') .setOptions({ formatter: () => { } }) .transform(); @@ -106,14 +80,14 @@ describe("ObjectTransformer", () => { const expectedTransformedObj = toPlainObject( new ObjDiffNode('root', DiffType.NONE, [ new ObjDiffNode('a', DiffType.NONE, [ - new ObjDiffNode('b: 1', DiffType.NONE, [], true), - new ObjDiffNode('d: 3', DiffType.ADDED, [], true), - ]), - new ObjDiffNode('c: 2', DiffType.NONE, [], true), - ]) + new ObjDiffNode('b: 1', DiffType.NONE, [], true, 'root.a.b'), + new ObjDiffNode('d: 3', DiffType.ADDED, [], true, 'root.a.d'), + ], false, 'root.a'), + new ObjDiffNode('c: 2', DiffType.NONE, [], true, 'root.c'), + ], false, 'root') ); - const transformedObj = new ObjectTransformer(newObj, 'root') + const transformedObj = new ObjectTransformer(newObj, 'root', 'root') .setOptions({ formatter: () => { } }) .withDiff(oldObj) .transform(); @@ -133,13 +107,13 @@ describe("ObjectTransformer", () => { const expectedTransformedObj = toPlainObject( new ObjDiffNode('root', DiffType.NONE, [ new ObjDiffNode('a', DiffType.NONE, [ - new ObjDiffNode('1', DiffType.ADDED, []), - new ObjDiffNode('null', DiffType.DELETED, []), - ]), - ]) + new ObjDiffNode('1', DiffType.ADDED, [], false, 'root.a.1'), + new ObjDiffNode('null', DiffType.DELETED, [], false, 'root.a.null'), + ], false, 'root.a'), + ], false, 'root') ); - const transformedObj = new ObjectTransformer(newObj, 'root') + const transformedObj = new ObjectTransformer(newObj, 'root', 'root') .setOptions({ formatter: () => { } }) .withDiff(oldObj) .transform(); @@ -166,19 +140,19 @@ describe("ObjectTransformer", () => { new ObjDiffNode('root', DiffType.NONE, [ new ObjDiffNode('a', DiffType.NONE, [ new ObjDiffNode('b', DiffType.NONE, [ - new ObjDiffNode('1', DiffType.ADDED, []), - new ObjDiffNode('null', DiffType.DELETED, []), - ]), - ]), - new ObjDiffNode('c: 2', DiffType.NONE, [], true), - ]) + new ObjDiffNode('1', DiffType.ADDED, [], false, 'root.a.b.1'), + new ObjDiffNode('null', DiffType.DELETED, [], false, 'root.a.b.null'), + ], false, 'root.a.b'), + ], false, 'root.a'), + new ObjDiffNode('c: 2', DiffType.NONE, [], true, 'root.c'), + ], false, 'root') ); - const transformedObj = new ObjectTransformer(newObj, 'root') + const transformedObj = new ObjectTransformer(newObj, 'root', 'root') .setOptions({ formatter: () => { } }) .withDiff(oldObj) .transform(); expect(transformedObj).toEqual(expectedTransformedObj); }); -}); \ No newline at end of file +}); diff --git a/tools/winscope/spec/ProtoTransformSpec.js b/tools/winscope/spec/ProtoTransformSpec.js index 8db736b6e..7c554412f 100644 --- a/tools/winscope/spec/ProtoTransformSpec.js +++ b/tools/winscope/spec/ProtoTransformSpec.js @@ -1,25 +1,28 @@ -import { detectAndDecode, decodeAndTransformProto, FILE_TYPES } from '../src/decode'; +import { decodeAndTransformProto, FILE_TYPES, FILE_DECODERS } from '../src/decode'; import fs from 'fs'; import path from 'path'; - -const layers_traces = [ - require('./traces/layers_trace/layers_trace_emptyregion.pb'), - require('./traces/layers_trace/layers_trace_invalid_layer_visibility.pb'), - require('./traces/layers_trace/layers_trace_orphanlayers.pb'), - require('./traces/layers_trace/layers_trace_root.pb'), - require('./traces/layers_trace/layers_trace_root_aosp.pb'), -]; +import { expectedEntries, expectedLayers, layers_traces } from './traces/ExpectedTraces'; describe("Proto Transformations", () => { it("can transform surface flinger traces", () => { - for (const trace of layers_traces) { - fs.readFileSync(path.resolve(__dirname, trace)); - const traceBuffer = fs.readFileSync(path.resolve(__dirname, trace)); + for (var i = 0; i < layers_traces.length; i++) { + const trace = layers_traces[i]; + const buffer = new Uint8Array(fs.readFileSync(path.resolve(__dirname, trace))); + const data = decodeAndTransformProto(buffer, FILE_DECODERS[FILE_TYPES.SURFACE_FLINGER_TRACE].decoderParams, true); - const buffer = new Uint8Array(traceBuffer); - const data = decodeAndTransformProto(buffer, FILE_TYPES.layers_trace, true); + // use final entry as this determines if there was any error in previous entry parsing + const transformedEntry = data.entries[data.entries.length-1]; + const expectedEntry = expectedEntries[i]; + for (const property in expectedEntry) { + expect(transformedEntry[property]).toEqual(expectedEntry[property]); + } - expect(true).toBe(true); + // check final flattened layer + const transformedLayer = transformedEntry.flattenedLayers[transformedEntry.flattenedLayers.length-1]; + const expectedLayer = expectedLayers[i]; + for (const property in expectedLayer) { + expect(transformedLayer[property]).toEqual(expectedLayer[property]); + } } }); -}); \ No newline at end of file +}); diff --git a/tools/winscope/spec/TagErrorSpec.js b/tools/winscope/spec/TagErrorSpec.js new file mode 100644 index 000000000..e8919a0e9 --- /dev/null +++ b/tools/winscope/spec/TagErrorSpec.js @@ -0,0 +1,50 @@ +import { decodeAndTransformProto, FILE_TYPES, FILE_DECODERS } from '../src/decode'; +import Tag from '../src/flickerlib/tags/Tag'; +import Error from '../src/flickerlib/errors/Error'; +import fs from 'fs'; +import path from 'path'; + +const tagTrace = '../spec/traces/tag_trace.winscope'; +const errorTrace = '../spec/traces/error_trace.winscope'; + +describe("Tag Transformation", () => { + it("can transform tag traces", () => { + const buffer = new Uint8Array(fs.readFileSync(path.resolve(__dirname, tagTrace))); + + const data = decodeAndTransformProto(buffer, FILE_DECODERS[FILE_TYPES.TAG_TRACE].decoderParams, true); + + expect(data.entries[0].timestamp.toString()).toEqual('159979677861'); + expect(data.entries[1].timestamp.toString()).toEqual('161268519083'); + expect(data.entries[2].timestamp.toString()).toEqual('161126718496'); + expect(data.entries[3].timestamp.toString()).toEqual('161613497398'); + expect(data.entries[4].timestamp.toString()).toEqual('161227062777'); + expect(data.entries[5].timestamp.toString()).toEqual('161268519083'); + expect(data.entries[6].timestamp.toString()).toEqual('161825945076'); + expect(data.entries[7].timestamp.toString()).toEqual('162261072567'); + + expect(data.entries[0].tags).toEqual([new Tag(12345,"PIP_ENTER",true,1,"",0)]); + expect(data.entries[1].tags).toEqual([new Tag(12345,"PIP_ENTER",false,2,"",2)]); + expect(data.entries[2].tags).toEqual([new Tag(67890,"ROTATION",true,3,"",3)]); + expect(data.entries[3].tags).toEqual([new Tag(67890,"ROTATION",false,4,"",4)]); + expect(data.entries[4].tags).toEqual([new Tag(9876,"PIP_EXIT",true,5,"",5)]); + expect(data.entries[5].tags).toEqual([new Tag(9876,"PIP_EXIT",false,6,"",6)]); + expect(data.entries[6].tags).toEqual([new Tag(54321,"IME_APPEAR",true,7,"",7)]); + expect(data.entries[7].tags).toEqual([new Tag(54321,"IME_APPEAR",false,8,"",8)]); + }) +}); + +describe("Error Transformation", () => { + it("can transform error traces", () => { + const buffer = new Uint8Array(fs.readFileSync(path.resolve(__dirname, errorTrace))); + + const data = decodeAndTransformProto(buffer, FILE_DECODERS[FILE_TYPES.ERROR_TRACE].decoderParams, true); + + expect(data.entries[0].timestamp.toString()).toEqual('161401263106'); + expect(data.entries[1].timestamp.toString()).toEqual('161126718496'); + expect(data.entries[2].timestamp.toString()).toEqual('162261072567'); + + expect(data.entries[0].errors).toEqual([new Error("","",33,"",33)]); + expect(data.entries[1].errors).toEqual([new Error("","",66,"",66)]); + expect(data.entries[2].errors).toEqual([new Error("","",99,"",99)]); + }) +}); \ No newline at end of file diff --git a/tools/winscope/spec/traces/ExpectedTraces.js b/tools/winscope/spec/traces/ExpectedTraces.js new file mode 100644 index 000000000..1f01de07e --- /dev/null +++ b/tools/winscope/spec/traces/ExpectedTraces.js @@ -0,0 +1,492 @@ +import { Buffer, RectF, Transform, Matrix, Color, Rect, Region } from '../../src/flickerlib/common.js'; +import { VISIBLE_CHIP } from '../../src/flickerlib/treeview/Chips'; + +const standardTransform = new Transform(0, new Matrix(1, 0, 0, 0, 1, 0)); +const standardRect = new Rect(0, 0, 0, 0); +const standardColor = new Color(0, 0, 0, 1); +const standardCrop = new Rect(0, 0, -1, -1); + +const expectedEmptyRegionLayer = { + backgroundBlurRadius: 0, + chips: [], + cornerRadius: 0, + effectiveScalingMode: 0, + hwcCompositionType: "INVALID", + id: 580, + isOpaque: false, + isRelativeOf: false, + kind: "580", + name: "SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + shadowRadius: 0, + shortName: "SurfaceView - com.android.(...).Main#0", + type: "BufferLayer", + z: -1, + zOrderRelativeOf: null, + parentId: 579, + activeBuffer: new Buffer(1440, 2614, 1472, 1), + bufferTransform: standardTransform, + color: new Color(0, 0, 0, 0.0069580078125), + crop: standardCrop, + hwcFrame: standardRect, + screenBounds: new RectF(37, 43, 146, 152), + transform: new Transform(0, new Matrix(1, 0, 37.37078094482422, 0, 1, -3.5995326042175293)), + visibleRegion: new Region([new Rect(37, 43, 146, 152)]), +}; +const emptyRegionProto = { + 2: "\nparent=0\ntype=BufferLayer\nname=Display Root#0", + 3: "\nparent=0\ntype=BufferLayer\nname=Display Overlays#0", + 4: "\nparent=2\ntype=BufferLayer\nname=mBelowAppWindowsContainers#0", + 5: "\nparent=2\ntype=BufferLayer\nname=com.android.server.wm.DisplayContent$TaskStackContainers@193aa46#0", + 6: "\nparent=5\ntype=BufferLayer\nname=animationLayer#0", + 7: "\nparent=5\ntype=BufferLayer\nname=splitScreenDividerAnchor#0", + 8: "\nparent=2\ntype=BufferLayer\nname=mAboveAppWindowsContainers#0", + 9: "\nparent=2\ntype=BufferLayer\nname=mImeWindowsContainers#0", + 10: "\nparent=5\ntype=BufferLayer\nname=Stack=0#0", + 11: "\nparent=10\ntype=ColorLayer\nname=animation background stackId=0#0", + 12: "\nparent=9\ntype=BufferLayer\nname=WindowToken{f81e7fc android.os.Binder@7c880ef}#0", + 13: "\nparent=4\ntype=BufferLayer\nname=WallpaperWindowToken{3756850 token=android.os.Binder@25b3e13}#0", + 18: "\nparent=13\ntype=BufferLayer\nname=fd46a8e com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 19: "\nparent=18\ntype=BufferLayer\nname=com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 20: "\nparent=8\ntype=BufferLayer\nname=WindowToken{fc1aa98 android.os.BinderProxy@3517c7b}#0", + 21: "\nparent=20\ntype=BufferLayer\nname=10022f1 DockedStackDivider#0", + 22: "\nparent=8\ntype=BufferLayer\nname=WindowToken{49a6772 android.os.BinderProxy@7ba1c7d}#0", + 23: "\nparent=22\ntype=BufferLayer\nname=56ef7c3 AssistPreviewPanel#0", + 24: "\nparent=8\ntype=BufferLayer\nname=WindowToken{35f7d5c android.os.BinderProxy@8b38fcf}#0", + 25: "\nparent=24\ntype=BufferLayer\nname=9029865 NavigationBar#0", + 26: "\nparent=8\ntype=BufferLayer\nname=WindowToken{a9a69ab android.os.BinderProxy@f64ffa}#0", + 27: "\nparent=26\ntype=BufferLayer\nname=5334808 StatusBar#0", + 28: "\nparent=8\ntype=BufferLayer\nname=WindowToken{a63ca37 android.os.BinderProxy@435eb36}#0", + 29: "\nparent=28\ntype=BufferLayer\nname=1a40ba4 ScreenDecorOverlay#0", + 30: "\nparent=8\ntype=BufferLayer\nname=WindowToken{4ed84c2 android.os.BinderProxy@33d1d0d}#0", + 31: "\nparent=30\ntype=BufferLayer\nname=7a0d2d3 ScreenDecorOverlayBottom#0", + 32: "\nparent=25\ntype=BufferLayer\nname=NavigationBar#0", + 33: "\nparent=27\ntype=BufferLayer\nname=StatusBar#0", + 34: "\nparent=29\ntype=BufferLayer\nname=ScreenDecorOverlay#0", + 35: "\nparent=31\ntype=BufferLayer\nname=ScreenDecorOverlayBottom#0", + 36: "\nparent=10\ntype=BufferLayer\nname=Task=239#0", + 37: "\nparent=632\ntype=BufferLayer\nname=AppWindowToken{188ce21 token=Token{824488 ActivityRecord{b0d882b u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t239}}}#0", + 38: "\nparent=37\ntype=BufferLayer\nname=9f6e33d com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 44: "\nparent=37\ntype=BufferLayer\nname=81a00fc com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 88: "\nparent=5\ntype=BufferLayer\nname=Stack=2#0", + 89: "\nparent=88\ntype=ColorLayer\nname=animation background stackId=2#0", + 90: "\nparent=88\ntype=BufferLayer\nname=Task=241#0", + 91: "\nparent=633\ntype=BufferLayer\nname=AppWindowToken{a9f5144 token=Token{f102257 ActivityRecord{3a0fd6 u0 com.android.chrome/com.google.android.apps.chrome.Main t241}}}#0", + 96: "\nparent=91\ntype=BufferLayer\nname=87e310e com.android.chrome/com.google.android.apps.chrome.Main#0", + 574: "\nparent=8\ntype=BufferLayer\nname=WindowToken{37eed7d android.os.Binder@6e217d4}#0", + 579: "\nparent=96\ntype=BufferLayer\nname=com.android.chrome/com.google.android.apps.chrome.Main#0", + 580: "\nparent=579\ntype=BufferLayer\nname=SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + 581: "\nparent=579\ntype=ColorLayer\nname=Background for -SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + 583: "\nparent=44\ntype=BufferLayer\nname=com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 629: "\nparent=38\ntype=BufferLayer\nname=com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#2", + 632: "\nparent=6\ntype=BufferLayer\nname=Surface(name=AppWindowToken{188ce21 token=Token{824488 ActivityRecord{b0d882b u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t239}}})/@0x90c9c46 - animation-leash#1", + 633: "\nparent=6\ntype=BufferLayer\nname=Surface(name=AppWindowToken{a9f5144 token=Token{f102257 ActivityRecord{3a0fd6 u0 com.android.chrome/com.google.android.apps.chrome.Main t241}}})/@0xd9b9374 - animation-leash#1" +}; +const expectedEmptyRegion = { + chips: [], + proto: emptyRegionProto, + hwcBlob: "", + isVisible: true, + kind: "entry", + rects: [], + shortName: "0d0h38m28s521ms", + timestampMs: "2308521813510", + where: "", + name: "0d0h38m28s521ms", + stableId: "LayerTraceEntry", + visibleLayers: [], +}; + +const expectedInvalidLayerVisibilityLayer = { + backgroundBlurRadius: 0, + chips: [], + cornerRadius: 0, + effectiveScalingMode: 0, + hwcCompositionType: "INVALID", + id: 1536, + isOpaque: false, + isRelativeOf: false, + kind: "1536", + name: "com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#2", + shadowRadius: 0, + shortName: "com.google.(...).NexusLauncherActivity#2", + type: "BufferLayer", + z: 0, + zOrderRelativeOf: null, + parentId: 1535, + stableId: "BufferLayer 1536 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#2", + activeBuffer: new Buffer(1440, 2880, 1472, 1), + bufferTransform: standardTransform, + color: new Color(-1, -1, -1, 0), + hwcFrame: standardRect, + transform: standardTransform, + visibleRegion: new Region([standardRect]), +}; +const invalidLayerVisibilityProto = { + 2: "\nparent=0\ntype=BufferLayer\nname=Display Root#0", + 3: "\nparent=0\ntype=BufferLayer\nname=Display Overlays#0", + 4: "\nparent=2\ntype=BufferLayer\nname=mBelowAppWindowsContainers#0", + 5: "\nparent=2\ntype=BufferLayer\nname=com.android.server.wm.DisplayContent$TaskStackContainers@4270eb4#0", + 6: "\nparent=5\ntype=BufferLayer\nname=animationLayer#0", + 7: "\nparent=5\ntype=BufferLayer\nname=boostedAnimationLayer#0", + 8: "\nparent=5\ntype=BufferLayer\nname=homeAnimationLayer#0", + 9: "\nparent=5\ntype=BufferLayer\nname=splitScreenDividerAnchor#0", + 10: "\nparent=2\ntype=BufferLayer\nname=mAboveAppWindowsContainers#0", + 11: "\nparent=2\ntype=BufferLayer\nname=mImeWindowsContainers#0", + 12: "\nparent=5\ntype=BufferLayer\nname=Stack=0#0", + 13: "\nparent=12\ntype=ColorLayer\nname=animation background stackId=0#0", + 14: "\nparent=11\ntype=BufferLayer\nname=WindowToken{268fcff android.os.Binder@6688c1e}#0", + 15: "\nparent=4\ntype=BufferLayer\nname=WallpaperWindowToken{6572e20 token=android.os.Binder@9543923}#0", + 20: "\nparent=15\ntype=BufferLayer\nname=5e2e96f com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 21: "\nparent=20\ntype=BufferLayer\nname=com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 26: "\nparent=10\ntype=BufferLayer\nname=WindowToken{68e3f31 android.os.BinderProxy@f018fd8}#0", + 27: "\nparent=26\ntype=BufferLayer\nname=2b80616 NavigationBar#0", + 28: "\nparent=10\ntype=BufferLayer\nname=WindowToken{4e20cae android.os.BinderProxy@9086129}#0", + 29: "\nparent=28\ntype=BufferLayer\nname=b09a4f StatusBar#0", + 30: "\nparent=3\ntype=BufferLayer\nname=WindowToken{501e3b8 android.os.BinderProxy@238661b}#0", + 31: "\nparent=30\ntype=BufferLayer\nname=d803591 ScreenDecorOverlay#0", + 32: "\nparent=3\ntype=BufferLayer\nname=WindowToken{56d48f7 android.os.BinderProxy@f0f2cf6}#0", + 33: "\nparent=32\ntype=BufferLayer\nname=1cd8364 ScreenDecorOverlayBottom#0", + 35: "\nparent=29\ntype=BufferLayer\nname=StatusBar#0", + 36: "\nparent=31\ntype=BufferLayer\nname=ScreenDecorOverlay#0", + 37: "\nparent=33\ntype=BufferLayer\nname=ScreenDecorOverlayBottom#0", + 38: "\nparent=12\ntype=BufferLayer\nname=Task=2#0", + 39: "\nparent=38\ntype=BufferLayer\nname=AppWindowToken{215b919 token=Token{104a060 ActivityRecord{7e30c63 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t2}}}#0", + 821: "\nparent=14\ntype=BufferLayer\nname=5c937c8 InputMethod#0", + 1078: "\nparent=10\ntype=BufferLayer\nname=WindowToken{7dc6283 android.os.BinderProxy@f83c532}#0", + 1079: "\nparent=1078\ntype=BufferLayer\nname=32c0c00 AssistPreviewPanel#0", + 1080: "\nparent=10\ntype=BufferLayer\nname=WindowToken{9f8a3df android.os.BinderProxy@825027e}#0", + 1081: "\nparent=1080\ntype=BufferLayer\nname=26d9efb DockedStackDivider#0", + 1403: "\nparent=10\ntype=BufferLayer\nname=WindowToken{dedcfff android.os.Binder@a80cb1e}#0", + 1447: "\nparent=39\ntype=BufferLayer\nname=39ca531 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 1454: "\nparent=27\ntype=BufferLayer\nname=NavigationBar#0", + 1502: "\nparent=10\ntype=BufferLayer\nname=WindowToken{3ea357b android.os.Binder@6d9a90a}#0", + 1505: "\nparent=1518\ntype=BufferLayer\nname=Task=623#0", + 1506: "\nparent=1505\ntype=BufferLayer\nname=AppWindowToken{6deed44 token=Token{45cae57 ActivityRecord{7f14bd6 u0 com.android.server.wm.flicker.testapp/.SimpleActivity t623}}}#0", + 1518: "\nparent=5\ntype=BufferLayer\nname=Stack=51#0", + 1519: "\nparent=1518\ntype=ColorLayer\nname=animation background stackId=51#0", + 1521: "\nparent=1506\ntype=BufferLayer\nname=496d52e com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.SimpleActivity#0", + 1534: "\nparent=1447\ntype=BufferLayer\nname=com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 1535: "\nparent=39\ntype=BufferLayer\nname=e280197 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 1536: "\nparent=1535\ntype=BufferLayer\nname=com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#2", +}; +const expectedInvalidLayerVisibility = { + chips: [], + proto: invalidLayerVisibilityProto, + hwcBlob: "", + isVisible: true, + kind: "entry", + rects: [], + shortName: "2d22h13m17s233ms", + timestampMs: "252797233543024", + where: "", + name: "2d22h13m17s233ms", + stableId: "LayerTraceEntry", + visibleLayers: [], +}; + +const expectedOrphanLayersLayer = { + backgroundBlurRadius: 0, + chips: [], + cornerRadius: 0, + effectiveScalingMode: 0, + hwcCompositionType: "INVALID", + id: 1012, + isOpaque: true, + isRelativeOf: false, + kind: "1012", + name: "SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + shadowRadius: 0, + shortName: "SurfaceView - com.android.(...).Main#0", + type: "BufferLayer", + z: -1, + zOrderRelativeOf: null, + parentId: 1011, + stableId: "BufferLayer 1012 SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + activeBuffer: new Buffer(1440, 2614, 1472, 1), + bufferTransform: standardTransform, + color: standardColor, + crop: standardCrop, + hwcFrame: standardRect, + screenBounds: new RectF(0, 98, 1440, 2712), + transform: new Transform(0, new Matrix(1, 0, 0, 0, 1, 98)), + visibleRegion: new Region([new Rect(0, 98, 1440, 2712)]), +}; +const expectedOrphanLayersProto = { + 2: "\nparent=0\ntype=BufferLayer\nname=Display Root#0", + 3: "\nparent=0\ntype=BufferLayer\nname=Display Overlays#0", + 4: "\nparent=2\ntype=BufferLayer\nname=mBelowAppWindowsContainers#0", + 5: "\nparent=2\ntype=BufferLayer\nname=com.android.server.wm.DisplayContent$TaskStackContainers@e7dd520#0", + 6: "\nparent=5\ntype=BufferLayer\nname=animationLayer#0", + 7: "\nparent=5\ntype=BufferLayer\nname=splitScreenDividerAnchor#0", + 8: "\nparent=2\ntype=BufferLayer\nname=mAboveAppWindowsContainers#0", + 9: "\nparent=2\ntype=BufferLayer\nname=mImeWindowsContainers#0", + 10: "\nparent=5\ntype=BufferLayer\nname=Stack=0#0", + 11: "\nparent=10\ntype=ColorLayer\nname=animation background stackId=0#0", + 12: "\nparent=9\ntype=BufferLayer\nname=WindowToken{1350b6f android.os.Binder@d1b0e4e}#0", + 13: "\nparent=4\ntype=BufferLayer\nname=WallpaperWindowToken{4537182 token=android.os.Binder@d87c4cd}#0", + 18: "\nparent=13\ntype=BufferLayer\nname=8d26107 com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 19: "\nparent=18\ntype=BufferLayer\nname=com.breel.wallpapers.dioramas.lagos.LagosWallpaperService#0", + 20: "\nparent=8\ntype=BufferLayer\nname=WindowToken{fba948d android.os.BinderProxy@756b124}#0", + 21: "\nparent=20\ntype=BufferLayer\nname=dc26642 DockedStackDivider#0", + 22: "\nparent=8\ntype=BufferLayer\nname=WindowToken{45663b4 android.os.BinderProxy@5273887}#0", + 23: "\nparent=22\ntype=BufferLayer\nname=c617bdd AssistPreviewPanel#0", + 24: "\nparent=8\ntype=BufferLayer\nname=WindowToken{ef90888 android.os.BinderProxy@9d4dc2b}#0", + 25: "\nparent=24\ntype=BufferLayer\nname=1d24221 NavigationBar#0", + 26: "\nparent=8\ntype=BufferLayer\nname=WindowToken{6b1dca9 android.os.BinderProxy@a53d830}#0", + 27: "\nparent=26\ntype=BufferLayer\nname=eaca22e StatusBar#0", + 28: "\nparent=8\ntype=BufferLayer\nname=WindowToken{72e584c android.os.BinderProxy@3ba407f}#0", + 29: "\nparent=28\ntype=BufferLayer\nname=46af095 ScreenDecorOverlay#0", + 30: "\nparent=8\ntype=BufferLayer\nname=WindowToken{bc659b android.os.BinderProxy@f1405aa}#0", + 31: "\nparent=30\ntype=BufferLayer\nname=80ead38 ScreenDecorOverlayBottom#0", + 33: "\nparent=27\ntype=BufferLayer\nname=StatusBar#0", + 34: "\nparent=29\ntype=BufferLayer\nname=ScreenDecorOverlay#0", + 35: "\nparent=31\ntype=BufferLayer\nname=ScreenDecorOverlayBottom#0", + 36: "\nparent=10\ntype=BufferLayer\nname=Task=2#0", + 37: "\nparent=36\ntype=BufferLayer\nname=AppWindowToken{5162f77 token=Token{ac99d76 ActivityRecord{7749795 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t2}}}#0", + 38: "\nparent=37\ntype=BufferLayer\nname=2c19e73 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 41: "\nparent=25\ntype=BufferLayer\nname=NavigationBar#1", + 43: "\nparent=37\ntype=BufferLayer\nname=2f0c80b com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 46: "\nparent=5\ntype=BufferLayer\nname=Stack=1#0", + 47: "\nparent=46\ntype=ColorLayer\nname=animation background stackId=1#0", + 48: "\nparent=46\ntype=BufferLayer\nname=Task=89#0", + 49: "\nparent=48\ntype=BufferLayer\nname=AppWindowToken{1d514da token=Token{d36fe85 ActivityRecord{e0ec0ef u0 com.android.chrome/com.google.android.apps.chrome.Main t89}}}#0", + 54: "\nparent=49\ntype=BufferLayer\nname=8ae6e06 com.android.chrome/com.google.android.apps.chrome.Main#0", + 607: "\nparent=5\ntype=BufferLayer\nname=Stack=9#0", + 608: "\nparent=607\ntype=ColorLayer\nname=animation background stackId=9#0", + 609: "\nparent=607\ntype=BufferLayer\nname=Task=97#0", + 615: "\nparent=609\ntype=BufferLayer\nname=AppWindowToken{28730c9 token=Token{4d768d0 ActivityRecord{faf093 u0 com.google.android.gm/.welcome.WelcomeTourActivity t97}}}#0", + 616: "\nparent=615\ntype=BufferLayer\nname=44e6e5c com.google.android.gm/com.google.android.gm.welcome.WelcomeTourActivity#0", + 679: "\nparent=12\ntype=BufferLayer\nname=2d0b1e4 InputMethod#0", + 993: "\nparent=8\ntype=BufferLayer\nname=WindowToken{e425e58 android.os.Binder@6d9a73b}#0", + 1011: "\nparent=54\ntype=BufferLayer\nname=com.android.chrome/com.google.android.apps.chrome.Main#0", + 1012: "\nparent=1011\ntype=BufferLayer\nname=SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", + 1013: "\nparent=1011\ntype=ColorLayer\nname=Background for -SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0", +}; +const expectedOrphanLayers = { + chips: [], + proto: expectedOrphanLayersProto, + hwcBlob: "", + isVisible: true, + kind: "entry", + rects: [], + shortName: "3d23h30m9s820ms", + timestampMs: "343809820196384", + where: "", + name: "3d23h30m9s820ms", + stableId: "LayerTraceEntry", + visibleLayers: [], +}; + +const expectedRootLayer = { + backgroundBlurRadius: 0, + cornerRadius: 0, + effectiveScalingMode: 0, + hwcCompositionType: "INVALID", + id: 12545, + isOpaque: true, + isRelativeOf: false, + kind: "12545", + name: "com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.SimpleActivity#0", + shadowRadius: 0, + shortName: "com.android.(...).SimpleActivity#0", + type: "BufferQueueLayer", + z: 0, + zOrderRelativeOf: null, + parentId: 12541, + stableId: "BufferQueueLayer 12545 com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.SimpleActivity#0", + activeBuffer: new Buffer(1440, 2960, 1472, 1), + chips: [VISIBLE_CHIP], + bufferTransform: standardTransform, + color: standardColor, + crop: new Rect(0, 0, 1440, 2960), + hwcFrame: standardRect, + screenBounds: new RectF(0, 0, 1440, 2960), + sourceBounds: new RectF(0, 0, 1440, 2960), + transform: standardTransform, + visibleRegion: new Region([new Rect(0, 0, 1440, 2960)]), +}; +const expectedRootProto = { + 2: "\nparent=-1\ntype=ContainerLayer\nname=Root#0", + 3: "\nparent=2\ntype=ContainerLayer\nname=mWindowContainers#0", + 4: "\nparent=2\ntype=ContainerLayer\nname=mOverlayContainers#0", + 5: "\nparent=3\ntype=ContainerLayer\nname=mBelowAppWindowsContainers#0", + 6: "\nparent=3\ntype=ContainerLayer\nname=com.android.server.wm.DisplayContent$TaskContainers@708b672#0", + 7: "\nparent=6\ntype=ContainerLayer\nname=animationLayer#0", + 8: "\nparent=6\ntype=ContainerLayer\nname=boostedAnimationLayer#0", + 9: "\nparent=6\ntype=ContainerLayer\nname=homeAnimationLayer#0", + 10: "\nparent=6\ntype=ContainerLayer\nname=splitScreenDividerAnchor#0", + 11: "\nparent=3\ntype=ContainerLayer\nname=mAboveAppWindowsContainers#0", + 12: "\nparent=3\ntype=ContainerLayer\nname=ImeContainer#0", + 13: "\nparent=6\ntype=ContainerLayer\nname=Task=1#0", + 18: "\nparent=5\ntype=ContainerLayer\nname=WallpaperWindowToken{4c3f8ef token=android.os.Binder@a0341ce}#0", + 19: "\nparent=18\ntype=ContainerLayer\nname=aa9ba7e com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2#0", + 20: "\nparent=19\ntype=BufferQueueLayer\nname=com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2#0", + 23: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{2e98b86 android.os.BinderProxy@6e5dbc8}#0", + 24: "\nparent=23\ntype=ContainerLayer\nname=5976c47 NavigationBar0#0", + 25: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{525aa4 android.os.BinderProxy@df1e236}#0", + 26: "\nparent=25\ntype=ContainerLayer\nname=986c00d NotificationShade#0", + 27: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{7ec5009 android.os.BinderProxy@de2add3}#0", + 28: "\nparent=27\ntype=ContainerLayer\nname=3a0542f StatusBar#0", + 31: "\nparent=-1\ntype=ContainerLayer\nname=WindowToken{eef604c android.os.BinderProxy@d3a687f}#0", + 32: "\nparent=31\ntype=ContainerLayer\nname=20b5895 ScreenDecorOverlay#0", + 33: "\nparent=-1\ntype=ContainerLayer\nname=WindowToken{4846f6f android.os.BinderProxy@39824e}#0", + 34: "\nparent=33\ntype=ContainerLayer\nname=1d714 ScreenDecorOverlayBottom#0", + 36: "\nparent=32\ntype=BufferQueueLayer\nname=ScreenDecorOverlay#0", + 38: "\nparent=34\ntype=BufferQueueLayer\nname=ScreenDecorOverlayBottom#0", + 40: "\nparent=28\ntype=BufferQueueLayer\nname=StatusBar#0", + 43: "\nparent=12\ntype=ContainerLayer\nname=WindowToken{fa12db9 android.os.Binder@4b88380}#0", + 46: "\nparent=13\ntype=ContainerLayer\nname=Task=4#0", + 47: "\nparent=46\ntype=ContainerLayer\nname=ActivityRecord{99bbfb0 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity#0", + 54: "\nparent=24\ntype=BufferQueueLayer\nname=NavigationBar0#0", + 71: "\nparent=43\ntype=ContainerLayer\nname=e8f94d2 InputMethod#0", + 11499: "\nparent=47\ntype=ContainerLayer\nname=6737b79 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 11501: "\nparent=-1\ntype=ContainerLayer\nname=Input Consumer recents_animation_input_consumer#2", + 11759: "\nparent=6\ntype=ContainerLayer\nname=Task=873#0", + 11760: "\nparent=11759\ntype=ContainerLayer\nname=Task=874#0", + 11761: "\nparent=11760\ntype=ContainerLayer\nname=ActivityRecord{7398002 u0 com.android.server.wm.flicker.testapp/.ImeActivityAutoFocus#0", + 11785: "\nparent=11761\ntype=ColorLayer\nname=Letterbox - right#0", + 12131: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{bbffcfd android.os.Binder@547b554}#0", + 12379: "\nparent=47\ntype=ContainerLayer\nname=3f8f098 com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#0", + 12412: "\nparent=11761\ntype=ContainerLayer\nname=edca7c6 com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.ImeActivityAutoFocus#0", + 12448: "\nparent=2147483645\ntype=ContainerLayer\nname=Surface(name=ActivityRecord{99bbfb0 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity)/@0x2c3972c - animation-leash#0", + 12449: "\nparent=2147483645\ntype=ContainerLayer\nname=Surface(name=ActivityRecord{fc16c94 u0 com.android.server.wm.flicker.testapp/.ImeActivity)/@0x7049863 - animation-leash#0", + 12485: "\nparent=6\ntype=ContainerLayer\nname=Task=908#0", + 12486: "\nparent=12485\ntype=ContainerLayer\nname=Task=909#0", + 12487: "\nparent=12486\ntype=ContainerLayer\nname=ActivityRecord{4b3c5cb u0 com.android.server.wm.flicker.testapp/.ImeActivity#0", + 12500: "\nparent=2147483645\ntype=ContainerLayer\nname=Surface(name=ActivityRecord{99bbfb0 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity)/@0x2c3972c - animation-leash#0", + 12501: "\nparent=2147483645\ntype=ContainerLayer\nname=Surface(name=ActivityRecord{4b3c5cb u0 com.android.server.wm.flicker.testapp/.ImeActivity)/@0x4ad47a1 - animation-leash#0", + 12502: "\nparent=2147483645\ntype=ContainerLayer\nname=Surface(name=WallpaperWindowToken{4c3f8ef token=android.os.Binder@a0341ce})/@0xcde5e65 - animation-leash#0", + 12511: "\nparent=12487\ntype=ColorLayer\nname=Letterbox - right#1", + 12514: "\nparent=12487\ntype=ContainerLayer\nname=debe1ed com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.ImeActivity#0", + 12526: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{6b7d663 android.os.BinderProxy@391f21d}#0", + 12527: "\nparent=12526\ntype=ContainerLayer\nname=32aa260 AssistPreviewPanel#0", + 12529: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{31f7489 android.os.BinderProxy@67b1e53}#0", + 12530: "\nparent=12529\ntype=ContainerLayer\nname=cbb28bc DockedStackDivider#0", + 12536: "\nparent=6\ntype=ContainerLayer\nname=Task=910#0", + 12537: "\nparent=12536\ntype=ContainerLayer\nname=Task=911#0", + 12538: "\nparent=12537\ntype=ContainerLayer\nname=ActivityRecord{d3b8a44 u0 com.android.server.wm.flicker.testapp/.SimpleActivity#0", + 12541: "\nparent=12538\ntype=ContainerLayer\nname=a3583c5 com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.SimpleActivity#0", + 12545: "\nparent=12541\ntype=BufferQueueLayer\nname=com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.SimpleActivity#0", + 2147483645: "\nparent=-1\ntype=\nname=Offscreen Root", +}; +const expectedRoot = { + chips: [], + proto: expectedRootProto, + hwcBlob: "", + isVisible: true, + kind: "entry", + shortName: "0d1h46m19s146ms", + timestampMs: "6379146308030", + where: "", + name: "0d1h46m19s146ms", + stableId: "LayerTraceEntry", +}; + +const expectedRootAospLayer = { + backgroundBlurRadius: 0, + cornerRadius: 0, + effectiveScalingMode: 0, + hwcCompositionType: "INVALID", + id: 876, + isOpaque: false, + isRelativeOf: false, + kind: "876", + name: "com.android.launcher3/com.android.launcher3.Launcher#0", + shadowRadius: 0, + shortName: "com.android.(...).Launcher#0", + type: "BufferLayer", + z: 0, + zOrderRelativeOf: null, + parentId: 41, + activeBuffer: new Buffer(1440, 2880, 1472, 1), + bufferTransform: standardTransform, + chips: [VISIBLE_CHIP], + color: standardColor, + crop: new Rect(0, 0, 1440, 2880), + hwcFrame: standardRect, + screenBounds: new RectF(0, 0, 1440, 2880), + sourceBounds: new RectF(0, 0, 1440, 2880), + transform: standardTransform, + visibleRegion: new Region([new Rect(0, 0, 1440, 2880)]), +}; +const expectedRootAospProto = { + 2: "\nparent=-1\ntype=ContainerLayer\nname=Display Root#0", + 3: "\nparent=-1\ntype=ContainerLayer\nname=Display Overlays#0", + 4: "\nparent=2\ntype=ContainerLayer\nname=mBelowAppWindowsContainers#0", + 5: "\nparent=2\ntype=ContainerLayer\nname=com.android.server.wm.DisplayContent$TaskStackContainers@d8077b3#0", + 6: "\nparent=5\ntype=ContainerLayer\nname=animationLayer#0", + 7: "\nparent=5\ntype=ContainerLayer\nname=boostedAnimationLayer#0", + 8: "\nparent=5\ntype=ContainerLayer\nname=homeAnimationLayer#0", + 9: "\nparent=5\ntype=ContainerLayer\nname=splitScreenDividerAnchor#0", + 10: "\nparent=2\ntype=ContainerLayer\nname=mAboveAppWindowsContainers#0", + 11: "\nparent=2\ntype=ContainerLayer\nname=mImeWindowsContainers#0", + 12: "\nparent=5\ntype=ContainerLayer\nname=Stack=0#0", + 13: "\nparent=12\ntype=ColorLayer\nname=animation background stackId=0#0", + 18: "\nparent=4\ntype=ContainerLayer\nname=WallpaperWindowToken{5a7eaca token=android.os.Binder@438b635}#0", + 23: "\nparent=10\ntype=ContainerLayer\nname=WindowToken{d19e48 android.os.BinderProxy@560ac3a}#0", + 24: "\nparent=23\ntype=ContainerLayer\nname=b2a84e1 NavigationBar0#0", + 25: "\nparent=10\ntype=ContainerLayer\nname=WindowToken{74d6851 android.os.BinderProxy@8b22adb}#0", + 26: "\nparent=25\ntype=ContainerLayer\nname=16448b6 StatusBar#0", + 27: "\nparent=-1\ntype=ContainerLayer\nname=WindowToken{624863c android.os.BinderProxy@975b02f}#0", + 28: "\nparent=27\ntype=ContainerLayer\nname=cdb9fc5 ScreenDecorOverlay#0", + 29: "\nparent=-1\ntype=ContainerLayer\nname=WindowToken{cb7204b android.os.BinderProxy@b8f3d1a}#0", + 30: "\nparent=29\ntype=ContainerLayer\nname=ad1ca28 ScreenDecorOverlayBottom#0", + 31: "\nparent=28\ntype=BufferLayer\nname=ScreenDecorOverlay#0", + 32: "\nparent=30\ntype=BufferLayer\nname=ScreenDecorOverlayBottom#0", + 33: "\nparent=18\ntype=ContainerLayer\nname=4f4b23b com.android.systemui.ImageWallpaper#0", + 34: "\nparent=33\ntype=BufferLayer\nname=com.android.systemui.ImageWallpaper#0", + 36: "\nparent=26\ntype=BufferLayer\nname=StatusBar#0", + 37: "\nparent=12\ntype=ContainerLayer\nname=Task=144#0", + 38: "\nparent=37\ntype=ContainerLayer\nname=AppWindowToken{54e2de0 token=Token{f4c5fe3 ActivityRecord{6a9dc12 u0 com.android.launcher3/.Launcher t144}}}#0", + 40: "\nparent=-1\ntype=ContainerLayer\nname=Input Consumer recents_animation_input_consumer#1", + 41: "\nparent=38\ntype=ContainerLayer\nname=418b5c0 com.android.launcher3/com.android.launcher3.Launcher#0", + 45: "\nparent=11\ntype=ContainerLayer\nname=WindowToken{9158878 android.os.Binder@4f4a5db}#0", + 46: "\nparent=24\ntype=BufferLayer\nname=NavigationBar0#0", + 731: "\nparent=10\ntype=ContainerLayer\nname=WindowToken{c0ebbde android.os.BinderProxy@1af0e60}#0", + 732: "\nparent=731\ntype=ContainerLayer\nname=b37d1bf AssistPreviewPanel#0", + 733: "\nparent=10\ntype=ContainerLayer\nname=WindowToken{dc6b7ea android.os.BinderProxy@166b08c}#0", + 734: "\nparent=733\ntype=ContainerLayer\nname=2a1cadb DockedStackDivider#0", + 862: "\nparent=10\ntype=ContainerLayer\nname=WindowToken{f63efe6 android.os.Binder@d536e41}#0", + 865: "\nparent=887\ntype=ContainerLayer\nname=Task=170#0", + 866: "\nparent=865\ntype=ContainerLayer\nname=AppWindowToken{c829d40 token=Token{59970c3 ActivityRecord{36f2472 u0 com.android.server.wm.flicker.testapp/.PipActivity t170}}}#0", + 871: "\nparent=866\ntype=ContainerLayer\nname=8153ff7 com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.PipActivity#0", + 876: "\nparent=41\ntype=BufferLayer\nname=com.android.launcher3/com.android.launcher3.Launcher#0", + 887: "\nparent=5\ntype=ContainerLayer\nname=Stack=78#0", + 888: "\nparent=887\ntype=ColorLayer\nname=animation background stackId=78#0", +}; +const expectedRootAosp = { + chips: [], + proto: expectedRootAospProto, + hwcBlob: "", + isVisible: true, + kind: "entry", + shortName: "0d1h3m1s911ms", + timestampMs: "3781911657318", + where: "", + name: "0d1h3m1s911ms", + stableId: "LayerTraceEntry", +}; + +const expectedEntries = [ + expectedEmptyRegion, + expectedInvalidLayerVisibility, + expectedOrphanLayers, + expectedRoot, + expectedRootAosp +]; +const expectedLayers = [ + expectedEmptyRegionLayer, + expectedInvalidLayerVisibilityLayer, + expectedOrphanLayersLayer, + expectedRootLayer, + expectedRootAospLayer +]; +const layers_traces = [ + '../spec/traces/layers_trace/layers_trace_emptyregion.pb', + '../spec/traces/layers_trace/layers_trace_invalid_layer_visibility.pb', + '../spec/traces/layers_trace/layers_trace_orphanlayers.pb', + '../spec/traces/layers_trace/layers_trace_root.pb', + '../spec/traces/layers_trace/layers_trace_root_aosp.pb', +]; + +export { expectedEntries, expectedLayers, layers_traces }; diff --git a/tools/winscope/spec/traces/error_trace.winscope b/tools/winscope/spec/traces/error_trace.winscope new file mode 100644 index 000000000..fd970722d Binary files /dev/null and b/tools/winscope/spec/traces/error_trace.winscope differ diff --git a/tools/winscope/spec/traces/tag_trace.winscope b/tools/winscope/spec/traces/tag_trace.winscope new file mode 100644 index 000000000..83459ba81 Binary files /dev/null and b/tools/winscope/spec/traces/tag_trace.winscope differ diff --git a/tools/winscope/spec/utils/tree.js b/tools/winscope/spec/utils/tree.js index 379ebaf46..63d0cb41d 100644 --- a/tools/winscope/spec/utils/tree.js +++ b/tools/winscope/spec/utils/tree.js @@ -9,6 +9,31 @@ class DiffNode extends Node { constructor(nodeDef, diffType, children) { super(nodeDef, children); this.diff = { type: diffType }; + this.name = undefined; + this.stableId = undefined; + this.kind = undefined; + this.shortName = undefined; + } +} + +class ObjNode extends Node { + constructor(name, children, combined, stableId) { + const nodeDef = { + kind: '', + name: name, + stableId: stableId, + }; + if (combined) { + nodeDef.combined = true; + } + super(nodeDef, children); + } +} + +class ObjDiffNode extends ObjNode { + constructor(name, diffType, children, combined, stableId) { + super(name, children, combined, stableId); + this.diff = { type: diffType }; } } @@ -30,4 +55,4 @@ function toPlainObject(theClass) { } } -export { Node, DiffNode, toPlainObject }; \ No newline at end of file +export { Node, DiffNode, ObjNode, ObjDiffNode, toPlainObject }; diff --git a/tools/winscope/src/AccessibilityTraceView.vue b/tools/winscope/src/AccessibilityTraceView.vue index 036699e94..63e7b3a9f 100644 --- a/tools/winscope/src/AccessibilityTraceView.vue +++ b/tools/winscope/src/AccessibilityTraceView.vue @@ -14,7 +14,13 @@ --> \ No newline at end of file + diff --git a/tools/winscope/src/App.vue b/tools/winscope/src/App.vue index 75d7b32bf..d7717613f 100644 --- a/tools/winscope/src/App.vue +++ b/tools/winscope/src/App.vue @@ -52,13 +52,20 @@ :ref="file.type" :store="store" :file="file" + :presentTags="Object.freeze(presentTags)" + :presentErrors="Object.freeze(presentErrors)" + :dataViewFiles="dataViewFiles" @click="onDataViewFocus(file)" /> @@ -77,7 +84,8 @@ import FileType from './mixins/FileType.js'; import SaveAsZip from './mixins/SaveAsZip'; import FocusedDataViewFinder from './mixins/FocusedDataViewFinder'; import {DIRECTION} from './utils/utils'; -import {NAVIGATION_STYLE} from './utils/consts'; +import Searchbar from './Searchbar.vue'; +import {NAVIGATION_STYLE, SEARCH_TYPE} from './utils/consts'; const APP_NAME = 'Winscope'; @@ -97,11 +105,17 @@ export default { simplifyNames: true, displayDefaults: true, navigationStyle: NAVIGATION_STYLE.GLOBAL, + flickerTraceView: false, + showFileTypes: [], }), overlayRef: 'overlay', mainContentStyle: { 'padding-bottom': `${CONTENT_BOTTOM_PADDING}px`, }, + presentTags: [], + presentErrors: [], + searchTypes: [SEARCH_TYPE.TIMESTAMP], + tagAndErrorTraces: false, }; }, created() { @@ -113,8 +127,58 @@ export default { window.removeEventListener('keydown', this.onKeyDown); window.removeEventListener('scroll', this.onScroll); }, + methods: { + /** Get states from either tag files or error files */ + getUpdatedStates(files) { + var states = []; + for (const file of files) { + states.push(...file.data); + } + return states; + }, + /** Get tags from all uploaded tag files*/ + getUpdatedTags() { + var tagStates = this.getUpdatedStates(this.tagFiles); + var tags = []; + tagStates.forEach(tagState => { + tagState.tags.forEach(tag => { + tag.timestamp = tagState.timestamp; + tags.push(tag); + }); + }); + return tags; + }, + /** Get tags from all uploaded error files*/ + getUpdatedErrors() { + var errorStates = this.getUpdatedStates(this.errorFiles); + var errors = []; + //TODO (b/196201487) add check if errors empty + errorStates.forEach(errorState => { + errorState.errors.forEach(error => { + error.timestamp = errorState.timestamp; + errors.push(error); + }); + }); + return errors; + }, + /** Set flicker mode check for if there are tag/error traces uploaded*/ + shouldUpdateTagAndErrorTraces() { + return this.tagFiles.length > 0 || this.errorFiles.length > 0; + }, + /** Activate flicker search tab if tags/errors uploaded*/ + updateSearchTypes() { + this.searchTypes = [SEARCH_TYPE.TIMESTAMP]; + if (this.tagAndErrorTraces) this.searchTypes.push(SEARCH_TYPE.TAG); + }, + /** Filter data view files by current show settings*/ + updateShowFileTypes() { + this.store.showFileTypes = this.dataViewFiles + .filter((file) => file.show) + .map(file => file.type); + }, clear() { + this.store.showFileTypes = []; this.$store.commit('clearFiles'); }, onDataViewFocus(file) { @@ -139,7 +203,12 @@ export default { }, onDataReady(files) { this.$store.dispatch('setFiles', files); + this.tagAndErrorTraces = this.shouldUpdateTagAndErrorTraces(); + this.presentTags = this.getUpdatedTags(); + this.presentErrors = this.getUpdatedErrors(); + this.updateSearchTypes(); this.updateFocusedView(); + this.updateShowFileTypes(); }, setStatus(status) { if (status) { @@ -158,7 +227,10 @@ export default { }, computed: { files() { - return this.$store.getters.sortedFiles; + return this.$store.getters.sortedFiles.map(file => { + if (this.hasDataView(file)) file.show = true; + return file; + }); }, prettyDump() { return JSON.stringify(this.dump, null, 2); @@ -174,7 +246,16 @@ export default { return this.activeDataView; }, dataViewFiles() { - return this.files.filter((f) => this.hasDataView(f)); + return this.files.filter((file) => this.hasDataView(file)); + }, + tagFiles() { + return this.$store.getters.tagFiles; + }, + errorFiles() { + return this.$store.getters.errorFiles; + }, + timelineFiles() { + return this.$store.getters.timelineFiles; }, }, watch: { @@ -187,6 +268,7 @@ export default { dataview: DataView, datainput: DataInput, dataadb: DataAdb, + searchbar: Searchbar, }, }; @@ -194,7 +276,7 @@ export default { @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&display=swap'); #app .md-app-container { - /* Get rid of tranforms which prevent fixed position from being used */ + /* Get rid of transforms which prevent fixed position from being used */ transform: none!important; min-height: 100vh; } @@ -240,20 +322,10 @@ export default { margin-top: 1em } -h1, -h2 { +h1 { font-weight: normal; } -ul { - list-style-type: none; - padding: 0; -} - -a { - color: #42b983; -} - .data-inputs { display: flex; flex-wrap: wrap; @@ -281,16 +353,16 @@ a { } .snackbar-break-words { - /* These are technically the same, but use both */ - overflow-wrap: break-word; - word-wrap: break-word; - -ms-word-break: break-all; - word-break: break-word; - /* Adds a hyphen where the word breaks, if supported (No Blink) */ - -ms-hyphens: auto; - -moz-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; - padding: 10px 10px 10px 10px; - } - + /* These are technically the same, but use both */ + overflow-wrap: break-word; + word-wrap: break-word; + -ms-word-break: break-all; + word-break: break-word; + /* Adds a hyphen where the word breaks, if supported (No Blink) */ + -ms-hyphens: auto; + -moz-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; + padding: 10px 10px 10px 10px; +} + \ No newline at end of file diff --git a/tools/winscope/src/DataAdb.vue b/tools/winscope/src/DataAdb.vue index 9b68c941c..0c34f2661 100644 --- a/tools/winscope/src/DataAdb.vue +++ b/tools/winscope/src/DataAdb.vue @@ -158,6 +158,9 @@ const TRACES = { 'window_trace': { name: 'Window Manager', }, + 'accessibility_trace': { + name: 'Accessibility', + }, 'layers_trace': { name: 'Surface Flinger', }, diff --git a/tools/winscope/src/DataView.vue b/tools/winscope/src/DataView.vue index db3c07f5f..a2751f191 100644 --- a/tools/winscope/src/DataView.vue +++ b/tools/winscope/src/DataView.vue @@ -16,10 +16,15 @@
+
{{ TRACE_ICONS[file.type] }} - {{file.type}} + {{ file.type }}
-

Unrecognized DataType

+

Unrecognized DataType

@@ -150,8 +161,23 @@ export default { // to component. this.$emit('click', e); }, + /** Filter data view files by current show settings */ + updateShowFileTypes() { + this.store.showFileTypes = this.dataViewFiles + .filter((file) => file.show) + .map(file => file.type); + }, + /** Expand or collapse data view */ + toggleView() { + this.file.show = !this.file.show; + this.updateShowFileTypes(); + }, + /** Check if data view file should be shown */ + isShowFileType(type) { + return this.store.showFileTypes.find(fileType => fileType===type); + }, }, - props: ['store', 'file'], + props: ['store', 'file', 'presentTags', 'presentErrors', 'dataViewFiles'], mixins: [FileType], components: { 'traceview': TraceView, @@ -170,4 +196,18 @@ export default { font-size: 4em; color: red; } + +.toggle-view-button { + background: none; + color: inherit; + border: none; + font: inherit; + cursor: pointer; + padding-right: 10px; + display: inline-block; +} + +.md-title { + display: inline-block; +} diff --git a/tools/winscope/src/DefaultTreeElement.vue b/tools/winscope/src/DefaultTreeElement.vue index 1df8d1769..96c7dcf09 100644 --- a/tools/winscope/src/DefaultTreeElement.vue +++ b/tools/winscope/src/DefaultTreeElement.vue @@ -43,13 +43,28 @@ {{c.long}}
+
+ + {{transitionTooltip(transition)}} +
+
+ + Error: {{error.message}} +
@@ -100,4 +124,12 @@ span { flex: 1 1 auto; width: 0; } + +.flicker-tags { + display: inline-block; +} + +.error-arrow { + color: red; +} diff --git a/tools/winscope/src/NodeContextMenu.vue b/tools/winscope/src/NodeContextMenu.vue index cba46eb5c..18d86e4bd 100644 --- a/tools/winscope/src/NodeContextMenu.vue +++ b/tools/winscope/src/NodeContextMenu.vue @@ -5,7 +5,7 @@ @@ -864,4 +920,8 @@ export default { margin-bottom: 15px; cursor: help; } + +.drop-search:hover { + background-color: #9af39f; +} diff --git a/tools/winscope/src/Searchbar.vue b/tools/winscope/src/Searchbar.vue new file mode 100644 index 000000000..50aca7b55 --- /dev/null +++ b/tools/winscope/src/Searchbar.vue @@ -0,0 +1,308 @@ + + + + diff --git a/tools/winscope/src/SurfaceFlingerTraceView.vue b/tools/winscope/src/SurfaceFlingerTraceView.vue index 94234ba71..5a848c10b 100644 --- a/tools/winscope/src/SurfaceFlingerTraceView.vue +++ b/tools/winscope/src/SurfaceFlingerTraceView.vue @@ -14,15 +14,21 @@ --> +.error { + stroke: rgb(255, 0, 0); + stroke-width: 2px; +} + \ No newline at end of file diff --git a/tools/winscope/src/TraceView.vue b/tools/winscope/src/TraceView.vue index 88bcabd3d..ab77d3542 100644 --- a/tools/winscope/src/TraceView.vue +++ b/tools/winscope/src/TraceView.vue @@ -42,6 +42,7 @@ Only visible Flat + Flicker @@ -55,6 +56,10 @@ :selected="hierarchySelected" :filter="hierarchyFilter" :flattened="store.flattened" + :onlyVisible="store.onlyVisible" + :flickerTraceView="store.flickerTraceView" + :presentTags="presentTags" + :presentErrors="presentErrors" :items-clickable="true" :useGlobalCollapsedState="true" :simplify-names="store.simplifyNames" @@ -165,7 +170,7 @@ function findEntryInTree(tree, id) { export default { name: 'traceview', - props: ['store', 'file', 'summarizer'], + props: ['store', 'file', 'summarizer', 'presentTags', 'presentErrors'], data() { return { propertyFilterString: '', @@ -306,10 +311,30 @@ export default { return prevEntry; }, + + /** Performs check for id match between entry and present tags/errors + * must be carried out for every present tag/error + */ + matchItems(flickerItems, entryItem) { + var match = false; + flickerItems.forEach(flickerItem => { + if (flickerItem.taskId===entryItem.taskId || flickerItem.layerId===entryItem.id) { + match = true; + } + }); + return match; + }, + /** Returns check for id match between entry and present tags/errors */ + isEntryTagMatch(entryItem) { + return this.matchItems(this.presentTags, entryItem) || this.matchItems(this.presentErrors, entryItem); + }, }, created() { this.setData(this.file.data[this.file.selectedIndex ?? 0]); }, + destroyed() { + this.store.flickerTraceView = false; + }, watch: { selectedIndex() { this.setData(this.file.data[this.file.selectedIndex ?? 0]); @@ -337,9 +362,12 @@ export default { hierarchyFilter() { const hierarchyPropertyFilter = getFilter(this.hierarchyPropertyFilterString); - return this.store.onlyVisible ? (c) => { + var fil = this.store.onlyVisible ? (c) => { return c.isVisible && hierarchyPropertyFilter(c); } : hierarchyPropertyFilter; + return this.store.flickerTraceView ? (c) => { + return this.isEntryTagMatch(c); + } : fil; }, propertyFilter() { return getFilter(this.propertyFilterString); @@ -363,6 +391,9 @@ export default { return summary; }, + hasTagsOrErrors() { + return this.presentTags.length > 0 || this.presentErrors.length > 0; + }, }, components: { 'tree-view': TreeView, diff --git a/tools/winscope/src/TreeView.vue b/tools/winscope/src/TreeView.vue index ff574a59c..846924e6e 100644 --- a/tools/winscope/src/TreeView.vue +++ b/tools/winscope/src/TreeView.vue @@ -31,7 +31,7 @@