blob: 94a3de07a5ca14964a76255a951f2644a7c33bb7 [file] [log] [blame]
Adam Pardylf33d6162019-07-16 12:20:13 +02001/*
2 * Copyright 2017, 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
17
Vishnu Nair9c93e692020-05-07 17:59:03 -070018import jsonProtoDefsWm from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'
19import jsonProtoDefsProtoLog from 'frameworks/base/core/proto/android/server/protolog.proto'
20import jsonProtoDefsSf from 'frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto'
21import jsonProtoDefsTransaction from 'frameworks/native/cmds/surfacereplayer/proto/src/trace.proto'
22import jsonProtoDefsWl from 'WaylandSafePath/waylandtrace.proto'
Vadim Caen9f291642020-02-12 15:45:39 +010023import jsonProtoDefsSysUi from 'frameworks/base/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto'
Winson Chung94289552019-11-22 17:06:19 -080024import jsonProtoDefsLauncher from 'packages/apps/Launcher3/protos/launcher_trace_file.proto'
Adam Pardylf33d6162019-07-16 12:20:13 +020025import protobuf from 'protobufjs'
26import { transform_layers, transform_layers_trace } from './transform_sf.js'
27import { transform_window_service, transform_window_trace } from './transform_wm.js'
Robert Delgadob6eb9922019-07-23 16:21:21 -070028import { transform_transaction_trace } from './transform_transaction.js'
Evan Roskye1f3d5d2019-08-28 15:45:35 -070029import { transform_wl_outputstate, transform_wayland_trace } from './transform_wl.js'
Adam Pardylc5708b22019-09-16 12:18:15 +020030import { transform_protolog } from './transform_protolog.js'
Winson Chung94289552019-11-22 17:06:19 -080031import { transform_sysui_trace } from './transform_sys_ui.js'
32import { transform_launcher_trace } from './transform_launcher.js'
Adam Pardylf33d6162019-07-16 12:20:13 +020033import { fill_transform_data } from './matrix_utils.js'
34import { mp4Decoder } from './decodeVideo.js'
35
Vishnu Nair9c93e692020-05-07 17:59:03 -070036var WmTraceMessage = lookup_type(jsonProtoDefsWm, "com.android.server.wm.WindowManagerTraceFileProto");
37var WmDumpMessage = lookup_type(jsonProtoDefsWm, "com.android.server.wm.WindowManagerServiceDumpProto");
38var SfTraceMessage = lookup_type(jsonProtoDefsSf, "android.surfaceflinger.LayersTraceFileProto");
39var SfDumpMessage = lookup_type(jsonProtoDefsSf, "android.surfaceflinger.LayersProto");
40var SfTransactionTraceMessage = lookup_type(jsonProtoDefsTransaction, "Trace");
41var WaylandTraceMessage = lookup_type(jsonProtoDefsWl, "org.chromium.arc.wayland_composer.TraceFileProto");
42var WaylandDumpMessage = lookup_type(jsonProtoDefsWl, "org.chromium.arc.wayland_composer.OutputStateProto");
43var ProtoLogMessage = lookup_type(jsonProtoDefsProtoLog, "com.android.server.protolog.ProtoLogFileProto");
44var SystemUiTraceMessage = lookup_type(jsonProtoDefsSysUi, "com.android.systemui.tracing.SystemUiTraceFileProto");
45var LauncherTraceMessage = lookup_type(jsonProtoDefsLauncher, "com.android.launcher3.tracing.LauncherTraceFileProto");
Adam Pardylf33d6162019-07-16 12:20:13 +020046
47const LAYER_TRACE_MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45] // .LYRTRACE
48const WINDOW_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45] // .WINTRACE
49const MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32] // ....ftypmp42
Evan Roskye1f3d5d2019-08-28 15:45:35 -070050const WAYLAND_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x59, 0x4c, 0x54, 0x52, 0x41, 0x43, 0x45] // .WYLTRACE
Adam Pardyl819c3452019-09-25 11:59:23 +020051const PROTO_LOG_MAGIC_NUMBER = [0x09, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47] // .PROTOLOG
Winson Chung94289552019-11-22 17:06:19 -080052const SYSTEM_UI_MAGIC_NUMBER = [0x09, 0x53, 0x59, 0x53, 0x55, 0x49, 0x54, 0x52, 0x43] // .SYSUITRC
53const LAUNCHER_MAGIC_NUMBER = [0x09, 0x4C, 0x4E, 0x43, 0x48, 0x52, 0x54, 0x52, 0x43] // .LNCHRTRC
Adam Pardylf33d6162019-07-16 12:20:13 +020054
55const DATA_TYPES = {
56 WINDOW_MANAGER: {
57 name: "WindowManager",
58 icon: "view_compact",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020059 mime: "application/octet-stream",
Adam Pardylf33d6162019-07-16 12:20:13 +020060 },
61 SURFACE_FLINGER: {
62 name: "SurfaceFlinger",
63 icon: "filter_none",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020064 mime: "application/octet-stream",
Adam Pardylf33d6162019-07-16 12:20:13 +020065 },
66 SCREEN_RECORDING: {
67 name: "Screen recording",
68 icon: "videocam",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020069 mime: "video/mp4",
Robert Delgadob6eb9922019-07-23 16:21:21 -070070 },
71 TRANSACTION: {
72 name: "Transaction",
73 icon: "timeline",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020074 mime: "application/octet-stream",
Robert Delgadob6eb9922019-07-23 16:21:21 -070075 },
Evan Roskye1f3d5d2019-08-28 15:45:35 -070076 WAYLAND: {
77 name: "Wayland",
78 icon: "filter_none",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020079 mime: "application/octet-stream",
Evan Roskye1f3d5d2019-08-28 15:45:35 -070080 },
Adam Pardyl819c3452019-09-25 11:59:23 +020081 PROTO_LOG: {
82 name: "ProtoLog",
Adam Pardylc5708b22019-09-16 12:18:15 +020083 icon: "notes",
Adam Pardyl2a94ec62019-09-16 18:48:59 +020084 mime: "application/octet-stream",
Winson Chung94289552019-11-22 17:06:19 -080085 },
86 SYSTEM_UI: {
87 name: "SystemUI",
88 icon: "filter_none",
89 mime: "application/octet-stream",
90 },
91 LAUNCHER: {
92 name: "Launcher",
93 icon: "filter_none",
94 mime: "application/octet-stream",
95 },
Adam Pardylf33d6162019-07-16 12:20:13 +020096}
97
98const FILE_TYPES = {
99 'window_trace': {
100 name: "WindowManager trace",
101 dataType: DATA_TYPES.WINDOW_MANAGER,
102 decoder: protoDecoder,
103 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700104 protoType: WmTraceMessage,
Adam Pardylf33d6162019-07-16 12:20:13 +0200105 transform: transform_window_trace,
106 timeline: true,
107 },
108 },
109 'layers_trace': {
110 name: "SurfaceFlinger trace",
111 dataType: DATA_TYPES.SURFACE_FLINGER,
112 decoder: protoDecoder,
113 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700114 protoType: SfTraceMessage,
Adam Pardylf33d6162019-07-16 12:20:13 +0200115 transform: transform_layers_trace,
116 timeline: true,
117 },
118 },
Evan Roskye1f3d5d2019-08-28 15:45:35 -0700119 'wl_trace': {
120 name: "Wayland trace",
121 dataType: DATA_TYPES.WAYLAND,
122 decoder: protoDecoder,
123 decoderParams: {
124 protoType: WaylandTraceMessage,
125 transform: transform_wayland_trace,
126 timeline: true,
127 },
128 },
Adam Pardylf33d6162019-07-16 12:20:13 +0200129 'layers_dump': {
130 name: "SurfaceFlinger dump",
131 dataType: DATA_TYPES.SURFACE_FLINGER,
132 decoder: protoDecoder,
133 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700134 protoType: SfDumpMessage,
Vishnu Nair691c1042020-04-10 16:33:33 -0700135 transform: (decoded) => transform_layers(true /*includesCompositionState*/, decoded),
Adam Pardylf33d6162019-07-16 12:20:13 +0200136 timeline: false,
137 },
138 },
139 'window_dump': {
140 name: "WindowManager dump",
141 dataType: DATA_TYPES.WINDOW_MANAGER,
142 decoder: protoDecoder,
143 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700144 protoType: WmDumpMessage,
Adam Pardylf33d6162019-07-16 12:20:13 +0200145 transform: transform_window_service,
146 timeline: false,
147 },
148 },
Evan Roskye1f3d5d2019-08-28 15:45:35 -0700149 'wl_dump': {
150 name: "Wayland dump",
151 dataType: DATA_TYPES.WAYLAND,
152 decoder: protoDecoder,
153 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700154 protoType: WaylandDumpMessage,
Evan Roskye1f3d5d2019-08-28 15:45:35 -0700155 transform: transform_wl_outputstate,
156 timeline: false,
157 },
158 },
Adam Pardylf33d6162019-07-16 12:20:13 +0200159 'screen_recording': {
160 name: "Screen recording",
161 dataType: DATA_TYPES.SCREEN_RECORDING,
162 decoder: videoDecoder,
163 decoderParams: {
164 videoDecoder: mp4Decoder,
165 },
Robert Delgadob6eb9922019-07-23 16:21:21 -0700166 },
167 'transaction': {
168 name: "Transaction",
169 dataType: DATA_TYPES.TRANSACTION,
170 decoder: protoDecoder,
171 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700172 protoType: SfTransactionTraceMessage,
Robert Delgadob6eb9922019-07-23 16:21:21 -0700173 transform: transform_transaction_trace,
174 timeline: true,
175 }
Adam Pardylc5708b22019-09-16 12:18:15 +0200176 },
Adam Pardyl819c3452019-09-25 11:59:23 +0200177 'proto_log': {
178 name: "ProtoLog",
179 dataType: DATA_TYPES.PROTO_LOG,
Adam Pardylc5708b22019-09-16 12:18:15 +0200180 decoder: protoDecoder,
181 decoderParams: {
Vishnu Nair9c93e692020-05-07 17:59:03 -0700182 protoType: ProtoLogMessage,
Adam Pardylc5708b22019-09-16 12:18:15 +0200183 transform: transform_protolog,
184 timeline: true,
185 }
Winson Chung94289552019-11-22 17:06:19 -0800186 },
187 'system_ui_trace': {
188 name: "SystemUI trace",
189 dataType: DATA_TYPES.SYSTEM_UI,
190 decoder: protoDecoder,
191 decoderParams: {
192 protoType: SystemUiTraceMessage,
193 transform: transform_sysui_trace,
194 timeline: true,
195 }
196 },
197 'launcher_trace': {
198 name: "Launcher trace",
199 dataType: DATA_TYPES.LAUNCHER,
200 decoder: protoDecoder,
201 decoderParams: {
202 protoType: LauncherTraceMessage,
203 transform: transform_launcher_trace,
204 timeline: true,
205 }
206 },
Adam Pardylf33d6162019-07-16 12:20:13 +0200207};
208
Vishnu Nair9c93e692020-05-07 17:59:03 -0700209function lookup_type(protoPath, type) {
210 return protobuf.Root.fromJSON(protoPath).lookupType(type);
211}
212
Adam Pardylf33d6162019-07-16 12:20:13 +0200213// Replace enum values with string representation and
214// add default values to the proto objects. This function also handles
215// a special case with TransformProtos where the matrix may be derived
216// from the transform type.
217function modifyProtoFields(protoObj, displayDefaults) {
218 if (!protoObj || protoObj !== Object(protoObj) || !protoObj.$type) {
219 return;
220 }
221 for (var fieldName in protoObj.$type.fields) {
222 var fieldProperties = protoObj.$type.fields[fieldName];
223 var field = protoObj[fieldName];
224
225 if (Array.isArray(field)) {
226 field.forEach((item, _) => {
227 modifyProtoFields(item, displayDefaults);
228 })
229 continue;
230 }
231
232 if (displayDefaults && !(field)) {
233 protoObj[fieldName] = fieldProperties.defaultValue;
234 }
235
236 if (fieldProperties.type === 'TransformProto') {
237 fill_transform_data(protoObj[fieldName]);
238 continue;
239 }
240
241 if (fieldProperties.resolvedType && fieldProperties.resolvedType.valuesById) {
242 protoObj[fieldName] = fieldProperties.resolvedType.valuesById[protoObj[fieldProperties.name]];
243 continue;
244 }
245 modifyProtoFields(protoObj[fieldName], displayDefaults);
246 }
247}
248
249function protoDecoder(buffer, fileType, fileName, store) {
250 var decoded = fileType.decoderParams.protoType.decode(buffer);
251 modifyProtoFields(decoded, store.displayDefaults);
252 var transformed = fileType.decoderParams.transform(decoded);
253 var data
254 if (fileType.decoderParams.timeline) {
255 data = transformed.children;
256 } else {
257 data = [transformed];
258 }
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200259 let blobUrl = URL.createObjectURL(new Blob([buffer], { type: fileType.dataType.mime }));
260 return dataFile(fileName, data.map(x => x.timestamp), data, blobUrl, fileType.dataType);
Adam Pardylf33d6162019-07-16 12:20:13 +0200261}
262
263function videoDecoder(buffer, fileType, fileName, store) {
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200264 let [data, timeline] = fileType.decoderParams.videoDecoder(buffer);
265 let blobUrl = URL.createObjectURL(new Blob([data], { type: fileType.dataType.mime }));
266 return dataFile(fileName, timeline, blobUrl, blobUrl, fileType.dataType);
Adam Pardylf33d6162019-07-16 12:20:13 +0200267}
268
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200269function dataFile(filename, timeline, data, blobUrl, type) {
Adam Pardylf33d6162019-07-16 12:20:13 +0200270 return {
271 filename: filename,
272 timeline: timeline,
273 data: data,
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200274 blobUrl: blobUrl,
Adam Pardylf33d6162019-07-16 12:20:13 +0200275 type: type,
276 selectedIndex: 0,
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200277 destroy() {
278 URL.revokeObjectURL(this.blobUrl);
279 },
Adam Pardylf33d6162019-07-16 12:20:13 +0200280 }
281}
282
283function arrayEquals(a, b) {
284 if (a.length !== b.length) {
285 return false;
286 }
287 for (var i = 0; i < a.length; i++) {
288 if (a[i] != b[i]) {
289 return false;
290 }
291 }
292 return true;
293}
294
295function arrayStartsWith(array, prefix) {
296 return arrayEquals(array.slice(0, prefix.length), prefix);
297}
298
299function decodedFile(fileType, buffer, fileName, store) {
300 return [fileType, fileType.decoder(buffer, fileType, fileName, store)];
301}
302
303function detectAndDecode(buffer, fileName, store) {
304 if (arrayStartsWith(buffer, LAYER_TRACE_MAGIC_NUMBER)) {
305 return decodedFile(FILE_TYPES['layers_trace'], buffer, fileName, store);
306 }
307 if (arrayStartsWith(buffer, WINDOW_TRACE_MAGIC_NUMBER)) {
308 return decodedFile(FILE_TYPES['window_trace'], buffer, fileName, store);
309 }
310 if (arrayStartsWith(buffer, MPEG4_MAGIC_NMBER)) {
311 return decodedFile(FILE_TYPES['screen_recording'], buffer, fileName, store);
312 }
Evan Roskye1f3d5d2019-08-28 15:45:35 -0700313 if (arrayStartsWith(buffer, WAYLAND_TRACE_MAGIC_NUMBER)) {
314 return decodedFile(FILE_TYPES['wl_trace'], buffer, fileName, store);
315 }
Adam Pardyl819c3452019-09-25 11:59:23 +0200316 if (arrayStartsWith(buffer, PROTO_LOG_MAGIC_NUMBER)) {
317 return decodedFile(FILE_TYPES['proto_log'], buffer, fileName, store);
Adam Pardylc5708b22019-09-16 12:18:15 +0200318 }
Winson Chung94289552019-11-22 17:06:19 -0800319 if (arrayStartsWith(buffer, SYSTEM_UI_MAGIC_NUMBER)) {
320 return decodedFile(FILE_TYPES['system_ui_trace'], buffer, fileName, store);
321 }
322 if (arrayStartsWith(buffer, LAUNCHER_MAGIC_NUMBER)) {
323 return decodedFile(FILE_TYPES['launcher_trace'], buffer, fileName, store);
324 }
Evan Roskye1f3d5d2019-08-28 15:45:35 -0700325 for (var name of ['transaction', 'layers_dump', 'window_dump', 'wl_dump']) {
Adam Pardylf33d6162019-07-16 12:20:13 +0200326 try {
327 return decodedFile(FILE_TYPES[name], buffer, fileName, store);
328 } catch (ex) {
329 // ignore exception and try next filetype
330 }
331 }
332 throw new Error('Unable to detect file');
333}
334
Adam Pardyl2a94ec62019-09-16 18:48:59 +0200335export { detectAndDecode, DATA_TYPES, FILE_TYPES };