• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {TracesUtils} from 'test/unit/traces_utils';
18import {TraceBuilder} from 'test/unit/trace_builder';
19import {LayerTraceEntry} from './flickerlib/layers/LayerTraceEntry';
20import {WindowManagerState} from './flickerlib/windows/WindowManagerState';
21import {FrameMapper} from './frame_mapper';
22import {AbsoluteFrameIndex} from './index_types';
23import {LogMessage} from './protolog';
24import {ScreenRecordingTraceEntry} from './screen_recording';
25import {RealTimestamp} from './timestamp';
26import {Trace} from './trace';
27import {Traces} from './traces';
28import {TraceType} from './trace_type';
29
30describe('FrameMapper', () => {
31  const time0 = new RealTimestamp(0n);
32  const time1 = new RealTimestamp(1n);
33  const time2 = new RealTimestamp(2n);
34  const time3 = new RealTimestamp(3n);
35  const time4 = new RealTimestamp(4n);
36  const time5 = new RealTimestamp(5n);
37  const time6 = new RealTimestamp(6n);
38  const time7 = new RealTimestamp(7n);
39  const time8 = new RealTimestamp(8n);
40  const time9 = new RealTimestamp(9n);
41  const time10 = new RealTimestamp(10n);
42  const time10seconds = new RealTimestamp(10n * 1000000000n);
43
44  describe('ProtoLog <-> WindowManager', () => {
45    let protoLog: Trace<LogMessage>;
46    let windowManager: Trace<WindowManagerState>;
47    let traces: Traces;
48
49    beforeAll(async () => {
50      // Frames              F0        F1
51      //                 |<------>|  |<->|
52      // PROTO_LOG:      0  1  2     3  4  5
53      // WINDOW_MANAGER:          0     1
54      // Time:           0  1  2  3  4  5  6
55      protoLog = new TraceBuilder<LogMessage>()
56        .setEntries([
57          'entry-0' as unknown as LogMessage,
58          'entry-1' as unknown as LogMessage,
59          'entry-2' as unknown as LogMessage,
60          'entry-3' as unknown as LogMessage,
61          'entry-4' as unknown as LogMessage,
62          'entry-5' as unknown as LogMessage,
63        ])
64        .setTimestamps([time0, time1, time2, time4, time5, time6])
65        .build();
66
67      windowManager = new TraceBuilder<WindowManagerState>()
68        .setEntries([
69          'entry-0' as unknown as WindowManagerState,
70          'entry-1' as unknown as WindowManagerState,
71        ])
72        .setTimestamps([time3, time5])
73        .build();
74
75      traces = new Traces();
76      traces.setTrace(TraceType.PROTO_LOG, protoLog);
77      traces.setTrace(TraceType.WINDOW_MANAGER, windowManager);
78      await new FrameMapper(traces).computeMapping();
79    });
80
81    it('associates entries/frames', async () => {
82      const expectedFrames = new Map<AbsoluteFrameIndex, Map<TraceType, Array<{}>>>();
83      expectedFrames.set(
84        0,
85        new Map<TraceType, Array<{}>>([
86          [TraceType.PROTO_LOG, ['entry-0', 'entry-1', 'entry-2']],
87          [TraceType.WINDOW_MANAGER, ['entry-0']],
88        ])
89      );
90      expectedFrames.set(
91        1,
92        new Map<TraceType, Array<{}>>([
93          [TraceType.PROTO_LOG, ['entry-3', 'entry-4']],
94          [TraceType.WINDOW_MANAGER, ['entry-1']],
95        ])
96      );
97
98      expect(await TracesUtils.extractFrames(traces)).toEqual(expectedFrames);
99    });
100  });
101
102  describe('IME <-> WindowManager', () => {
103    let ime: Trace<object>;
104    let windowManager: Trace<WindowManagerState>;
105    let traces: Traces;
106
107    beforeAll(async () => {
108      // IME:            0--1--2     3
109      //                    |        |
110      // WINDOW_MANAGER:    0        1  2
111      // Time:           0  1  2  3  4  5
112      ime = new TraceBuilder<object>()
113        .setEntries([
114          'entry-0' as unknown as object,
115          'entry-1' as unknown as object,
116          'entry-2' as unknown as object,
117          'entry-3' as unknown as object,
118        ])
119        .setTimestamps([time0, time1, time2, time4])
120        .build();
121
122      windowManager = new TraceBuilder<WindowManagerState>()
123        .setEntries([
124          'entry-0' as unknown as WindowManagerState,
125          'entry-1' as unknown as WindowManagerState,
126          'entry-2' as unknown as WindowManagerState,
127        ])
128        .setTimestamps([time1, time4, time5])
129        .build();
130
131      traces = new Traces();
132      traces.setTrace(TraceType.INPUT_METHOD_CLIENTS, ime);
133      traces.setTrace(TraceType.WINDOW_MANAGER, windowManager);
134      await new FrameMapper(traces).computeMapping();
135    });
136
137    it('associates entries/frames', async () => {
138      const expectedFrames = new Map<AbsoluteFrameIndex, Map<TraceType, Array<{}>>>();
139      expectedFrames.set(
140        0,
141        new Map<TraceType, Array<{}>>([
142          [TraceType.INPUT_METHOD_CLIENTS, ['entry-0', 'entry-1', 'entry-2']],
143          [TraceType.WINDOW_MANAGER, ['entry-0']],
144        ])
145      );
146      expectedFrames.set(
147        1,
148        new Map<TraceType, Array<{}>>([
149          [TraceType.INPUT_METHOD_CLIENTS, ['entry-3']],
150          [TraceType.WINDOW_MANAGER, ['entry-1']],
151        ])
152      );
153      expectedFrames.set(
154        2,
155        new Map<TraceType, Array<{}>>([
156          [TraceType.INPUT_METHOD_CLIENTS, []],
157          [TraceType.WINDOW_MANAGER, ['entry-2']],
158        ])
159      );
160
161      expect(await TracesUtils.extractFrames(traces)).toEqual(expectedFrames);
162    });
163  });
164
165  describe('WindowManager <-> Transactions', () => {
166    let windowManager: Trace<WindowManagerState>;
167    let transactions: Trace<object>;
168    let traces: Traces;
169
170    beforeAll(async () => {
171      // WINDOW_MANAGER:     0  1     2  3
172      //                     |  |     |    \
173      // TRANSACTIONS:    0  1  2--3  4     5  ... 6  <-- ignored (not connected) because too far
174      //                  |  |   |    |     |      |
175      // Frames:          0  1   2    3     4  ... 5
176      // Time:            0  1  2  3  4  5  6  ... 10s
177      windowManager = new TraceBuilder<LogMessage>()
178        .setEntries([
179          'entry-0' as unknown as WindowManagerState,
180          'entry-1' as unknown as WindowManagerState,
181          'entry-2' as unknown as WindowManagerState,
182          'entry-3' as unknown as WindowManagerState,
183        ])
184        .setTimestamps([time1, time2, time4, time5])
185        .build();
186
187      transactions = new TraceBuilder<object>()
188        .setEntries([
189          'entry-0' as unknown as object,
190          'entry-1' as unknown as object,
191          'entry-2' as unknown as object,
192          'entry-3' as unknown as object,
193          'entry-4' as unknown as object,
194          'entry-5' as unknown as object,
195          'entry-6' as unknown as object,
196        ])
197        .setTimestamps([time0, time1, time2, time3, time4, time5, time10seconds])
198        .setFrame(0, 0)
199        .setFrame(1, 1)
200        .setFrame(2, 2)
201        .setFrame(3, 2)
202        .setFrame(4, 3)
203        .setFrame(5, 4)
204        .setFrame(6, 5)
205        .build();
206
207      traces = new Traces();
208      traces.setTrace(TraceType.WINDOW_MANAGER, windowManager);
209      traces.setTrace(TraceType.TRANSACTIONS, transactions);
210      await new FrameMapper(traces).computeMapping();
211    });
212
213    it('associates entries/frames', async () => {
214      const expectedFrames = new Map<AbsoluteFrameIndex, Map<TraceType, Array<{}>>>();
215      expectedFrames.set(
216        0,
217        new Map<TraceType, Array<{}>>([
218          [TraceType.WINDOW_MANAGER, []],
219          [TraceType.TRANSACTIONS, ['entry-0']],
220        ])
221      );
222      expectedFrames.set(
223        1,
224        new Map<TraceType, Array<{}>>([
225          [TraceType.WINDOW_MANAGER, ['entry-0']],
226          [TraceType.TRANSACTIONS, ['entry-1']],
227        ])
228      );
229      expectedFrames.set(
230        2,
231        new Map<TraceType, Array<{}>>([
232          [TraceType.WINDOW_MANAGER, ['entry-1']],
233          [TraceType.TRANSACTIONS, ['entry-2', 'entry-3']],
234        ])
235      );
236      expectedFrames.set(
237        3,
238        new Map<TraceType, Array<{}>>([
239          [TraceType.WINDOW_MANAGER, ['entry-2']],
240          [TraceType.TRANSACTIONS, ['entry-4']],
241        ])
242      );
243      expectedFrames.set(
244        4,
245        new Map<TraceType, Array<{}>>([
246          [TraceType.WINDOW_MANAGER, ['entry-3']],
247          [TraceType.TRANSACTIONS, ['entry-5']],
248        ])
249      );
250      expectedFrames.set(
251        5,
252        new Map<TraceType, Array<{}>>([
253          [TraceType.WINDOW_MANAGER, []],
254          [TraceType.TRANSACTIONS, ['entry-6']],
255        ])
256      );
257
258      expect(await TracesUtils.extractFrames(traces)).toEqual(expectedFrames);
259    });
260  });
261
262  describe('Transactions <-> SurfaceFlinger', () => {
263    let transactions: Trace<object>;
264    let surfaceFlinger: Trace<LayerTraceEntry>;
265    let traces: Traces;
266
267    beforeAll(async () => {
268      // TRANSACTIONS:   0  1--2        3  4
269      //                  \     \        \
270      //                   \     \        \
271      // SURFACE_FLINGER:   0     1        2
272      transactions = new TraceBuilder<object>()
273        .setEntries([
274          {id: 0, vsyncId: createVsyncId(0)},
275          {id: 1, vsyncId: createVsyncId(10)},
276          {id: 2, vsyncId: createVsyncId(10)},
277          {id: 3, vsyncId: createVsyncId(20)},
278          {id: 4, vsyncId: createVsyncId(30)},
279        ])
280        .setTimestamps([time0, time1, time2, time5, time6])
281        .build();
282
283      surfaceFlinger = new TraceBuilder<LayerTraceEntry>()
284        .setEntries([
285          {id: 0, vSyncId: createVsyncId(0)} as unknown as LayerTraceEntry,
286          {id: 1, vSyncId: createVsyncId(10)} as unknown as LayerTraceEntry,
287          {id: 2, vSyncId: createVsyncId(20)} as unknown as LayerTraceEntry,
288        ])
289        .setTimestamps([time0, time1, time2])
290        .build();
291
292      traces = new Traces();
293      traces.setTrace(TraceType.TRANSACTIONS, transactions);
294      traces.setTrace(TraceType.SURFACE_FLINGER, surfaceFlinger);
295      await new FrameMapper(traces).computeMapping();
296    });
297
298    it('associates entries/frames', async () => {
299      const expectedFrames = new Map<AbsoluteFrameIndex, Map<TraceType, Array<{}>>>();
300      expectedFrames.set(
301        0,
302        new Map<TraceType, Array<{}>>([
303          [TraceType.TRANSACTIONS, [await transactions.getEntry(0).getValue()]],
304          [TraceType.SURFACE_FLINGER, [await surfaceFlinger.getEntry(0).getValue()]],
305        ])
306      );
307      expectedFrames.set(
308        1,
309        new Map<TraceType, Array<{}>>([
310          [
311            TraceType.TRANSACTIONS,
312            [await transactions.getEntry(1).getValue(), await transactions.getEntry(2).getValue()],
313          ],
314          [TraceType.SURFACE_FLINGER, [await surfaceFlinger.getEntry(1).getValue()]],
315        ])
316      );
317      expectedFrames.set(
318        2,
319        new Map<TraceType, Array<{}>>([
320          [TraceType.TRANSACTIONS, [await transactions.getEntry(3).getValue()]],
321          [TraceType.SURFACE_FLINGER, [await surfaceFlinger.getEntry(2).getValue()]],
322        ])
323      );
324
325      expect(await TracesUtils.extractFrames(traces)).toEqual(expectedFrames);
326    });
327  });
328
329  describe('SurfaceFlinger <-> ScreenRecording', () => {
330    let surfaceFlinger: Trace<LayerTraceEntry>;
331    let screenRecording: Trace<ScreenRecordingTraceEntry>;
332    let traces: Traces;
333
334    beforeAll(async () => {
335      // SURFACE_FLINGER:      0  1  2---  3     4  5  6
336      //                              \  \  \        \
337      //                               \  \  \        \
338      // SCREEN_RECORDING:     0        1  2  3        4 ... 5 <-- ignored (not connected) because too far
339      // Time:                 0  1  2  3  4  5  6  7  8     10s
340      surfaceFlinger = new TraceBuilder<LayerTraceEntry>()
341        .setEntries([
342          'entry-0' as unknown as LayerTraceEntry,
343          'entry-1' as unknown as LayerTraceEntry,
344          'entry-2' as unknown as LayerTraceEntry,
345          'entry-3' as unknown as LayerTraceEntry,
346          'entry-4' as unknown as LayerTraceEntry,
347          'entry-5' as unknown as LayerTraceEntry,
348          'entry-6' as unknown as LayerTraceEntry,
349        ])
350        .setTimestamps([time0, time1, time2, time4, time6, time7, time8])
351        .build();
352
353      screenRecording = new TraceBuilder<ScreenRecordingTraceEntry>()
354        .setEntries([
355          'entry-0' as unknown as ScreenRecordingTraceEntry,
356          'entry-1' as unknown as ScreenRecordingTraceEntry,
357          'entry-2' as unknown as ScreenRecordingTraceEntry,
358          'entry-3' as unknown as ScreenRecordingTraceEntry,
359          'entry-4' as unknown as ScreenRecordingTraceEntry,
360          'entry-5' as unknown as ScreenRecordingTraceEntry,
361        ])
362        .setTimestamps([time0, time3, time4, time5, time8, time10seconds])
363        .build();
364
365      traces = new Traces();
366      traces.setTrace(TraceType.SURFACE_FLINGER, surfaceFlinger);
367      traces.setTrace(TraceType.SCREEN_RECORDING, screenRecording);
368      await new FrameMapper(traces).computeMapping();
369    });
370
371    it('associates entries/frames', async () => {
372      const expectedFrames = new Map<AbsoluteFrameIndex, Map<TraceType, Array<{}>>>();
373      expectedFrames.set(
374        0,
375        new Map<TraceType, Array<{}>>([
376          [TraceType.SURFACE_FLINGER, []],
377          [TraceType.SCREEN_RECORDING, ['entry-0']],
378        ])
379      );
380      expectedFrames.set(
381        1,
382        new Map<TraceType, Array<{}>>([
383          [TraceType.SURFACE_FLINGER, ['entry-2']],
384          [TraceType.SCREEN_RECORDING, ['entry-1']],
385        ])
386      );
387      expectedFrames.set(
388        2,
389        new Map<TraceType, Array<{}>>([
390          [TraceType.SURFACE_FLINGER, ['entry-2']],
391          [TraceType.SCREEN_RECORDING, ['entry-2']],
392        ])
393      );
394      expectedFrames.set(
395        3,
396        new Map<TraceType, Array<{}>>([
397          [TraceType.SURFACE_FLINGER, ['entry-3']],
398          [TraceType.SCREEN_RECORDING, ['entry-3']],
399        ])
400      );
401      expectedFrames.set(
402        4,
403        new Map<TraceType, Array<{}>>([
404          [TraceType.SURFACE_FLINGER, ['entry-5']],
405          [TraceType.SCREEN_RECORDING, ['entry-4']],
406        ])
407      );
408      expectedFrames.set(
409        5,
410        new Map<TraceType, Array<{}>>([
411          [TraceType.SURFACE_FLINGER, []],
412          [TraceType.SCREEN_RECORDING, ['entry-5']],
413        ])
414      );
415
416      expect(await TracesUtils.extractFrames(traces)).toEqual(expectedFrames);
417    });
418  });
419
420  const createVsyncId = (value: number): object => {
421    return {
422      toString() {
423        return value.toString();
424      },
425    };
426  };
427});
428