diff --git a/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger_multidisplay.pb b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger_multidisplay.pb new file mode 100644 index 000000000..07fa2c797 Binary files /dev/null and b/tools/winscope/src/test/fixtures/traces/elapsed_and_real_timestamp/SurfaceFlinger_multidisplay.pb differ diff --git a/tools/winscope/src/test/unit/utils.ts b/tools/winscope/src/test/unit/utils.ts index 45ed005c3..df3882f69 100644 --- a/tools/winscope/src/test/unit/utils.ts +++ b/tools/winscope/src/test/unit/utils.ts @@ -38,6 +38,10 @@ class UnitTestUtils extends CommonTestUtils { return await UnitTestUtils.getTraceEntry('traces/elapsed_timestamp/SurfaceFlinger.pb'); } + static async getMultiDisplayLayerTraceEntry(): Promise { + return await UnitTestUtils.getTraceEntry('traces/elapsed_and_real_timestamp/SurfaceFlinger_multidisplay.pb'); + } + static async getImeTraceEntries(): Promise> { let surfaceFlingerEntry: LayerTraceEntry | undefined; { diff --git a/tools/winscope/src/viewers/components/rects/rects_component_test.ts b/tools/winscope/src/viewers/components/rects/rects_component_test.ts index b0818c815..e7145f29e 100644 --- a/tools/winscope/src/viewers/components/rects/rects_component_test.ts +++ b/tools/winscope/src/viewers/components/rects/rects_component_test.ts @@ -114,4 +114,19 @@ describe('RectsComponent', () => { slider?.dispatchEvent(new MouseEvent('mousedown')); expect(Canvas.prototype.draw).toHaveBeenCalledTimes(1); }); + + it('draws display buttons', () => { + component.displayIds = [0, 1, 2]; + + fixture.detectChanges(); + + const displayButtonContainer = htmlElement.querySelector(".display-button-container"); + expect(displayButtonContainer).toBeTruthy(); + + const buttons = Array.from(displayButtonContainer?.querySelectorAll('button') ?? []); + expect(buttons.length).toBe(3); + + const buttonValues = buttons.map((it) => it.textContent?.trim()); + expect(buttonValues).toEqual(["0", "1", "2"]); + }) }); diff --git a/tools/winscope/src/viewers/viewer_surface_flinger/presenter.ts b/tools/winscope/src/viewers/viewer_surface_flinger/presenter.ts index eefef04aa..7578974a5 100644 --- a/tools/winscope/src/viewers/viewer_surface_flinger/presenter.ts +++ b/tools/winscope/src/viewers/viewer_surface_flinger/presenter.ts @@ -121,7 +121,8 @@ export class Presenter { }; return rect; }) ?? []; - this.displayIds = []; + this.displayIds = this.entry.displays.map((it: any) => it.layerStackId) + this.displayIds.sort(); const rects = this.getLayersForRectsView() .sort(this.compareLayerZ) .map((it: any) => { @@ -136,6 +137,7 @@ export class Presenter { }; return rect; }); + return this.rectsToUiData(rects.concat(displayRects)); } diff --git a/tools/winscope/src/viewers/viewer_surface_flinger/presenter_test.ts b/tools/winscope/src/viewers/viewer_surface_flinger/presenter_test.ts index ddb22becc..e050c5c3f 100644 --- a/tools/winscope/src/viewers/viewer_surface_flinger/presenter_test.ts +++ b/tools/winscope/src/viewers/viewer_surface_flinger/presenter_test.ts @@ -213,4 +213,20 @@ describe('PresenterSurfaceFlinger', () => { ) ?? []; expect(nonTerminalChildren.length).toEqual(3); }); + + it('handles displays with no visible layers', async () => { + presenter.notifyCurrentTraceEntries(await getEntriesWithMultiDisplaySfTrace()); + expect(uiData.displayIds.length).toEqual(5); + // we want the ids to be sorted + expect(uiData.displayIds).toEqual([0,2,3,4,5]); + }); + + async function getEntriesWithMultiDisplaySfTrace(): Promise> { + const entries = new Map(); + const entry: LayerTraceEntry = await UnitTestUtils.getMultiDisplayLayerTraceEntry(); + + entries.set(TraceType.SURFACE_FLINGER, [entry, null]); + + return entries; + } }); diff --git a/tools/winscope/src/viewers/viewer_window_manager/presenter.ts b/tools/winscope/src/viewers/viewer_window_manager/presenter.ts index 252da331e..96bf1cc31 100644 --- a/tools/winscope/src/viewers/viewer_window_manager/presenter.ts +++ b/tools/winscope/src/viewers/viewer_window_manager/presenter.ts @@ -131,6 +131,7 @@ export class Presenter { } return rect; }) ?? []; + this.displayIds.sort(); return this.rectsToUiData(rects.concat(displayRects)); }