Added transaction support for winscope.

Test: yarn run dev for a transaction file.
Change-Id: Icfc672e2ab8423da35602d6d3d2e174c53c0154a
Merged-In: Icfc672e2ab8423da35602d6d3d2e174c53c0154a
diff --git a/tools/winscope/src/DataView.vue b/tools/winscope/src/DataView.vue
index 2bc08fc..1de5c0f 100644
--- a/tools/winscope/src/DataView.vue
+++ b/tools/winscope/src/DataView.vue
@@ -44,7 +44,8 @@
   props: ['store', 'file'],
   computed: {
     isTrace() {
-      return this.file.type == DATA_TYPES.WINDOW_MANAGER || this.file.type == DATA_TYPES.SURFACE_FLINGER;
+      return this.file.type == DATA_TYPES.WINDOW_MANAGER ||
+          this.file.type == DATA_TYPES.SURFACE_FLINGER || this.file.type == DATA_TYPES.TRANSACTION;
     },
     isVideo() {
       return this.file.type == DATA_TYPES.SCREEN_RECORDING;
diff --git a/tools/winscope/src/decode.js b/tools/winscope/src/decode.js
index e78ca21..6dfc2cf 100644
--- a/tools/winscope/src/decode.js
+++ b/tools/winscope/src/decode.js
@@ -17,14 +17,17 @@
 
 import jsonProtoDefs from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'
 import jsonProtoDefsSF from 'frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto'
+import jsonProtoDefsTrans from 'frameworks/native/cmds/surfacereplayer/proto/src/trace.proto'
 import protobuf from 'protobufjs'
 import { transform_layers, transform_layers_trace } from './transform_sf.js'
 import { transform_window_service, transform_window_trace } from './transform_wm.js'
+import { transform_transaction_trace } from './transform_transaction.js'
 import { fill_transform_data } from './matrix_utils.js'
 import { mp4Decoder } from './decodeVideo.js'
 
 var protoDefs = protobuf.Root.fromJSON(jsonProtoDefs)
-  .addJSON(jsonProtoDefsSF.nested);
+  .addJSON(jsonProtoDefsSF.nested)
+  .addJSON(jsonProtoDefsTrans.nested);
 
 var WindowTraceMessage = protoDefs.lookupType(
   "com.android.server.wm.WindowManagerTraceFileProto");
@@ -32,7 +35,7 @@
   "com.android.server.wm.WindowManagerServiceDumpProto");
 var LayersMessage = protoDefs.lookupType("android.surfaceflinger.LayersProto");
 var LayersTraceMessage = protoDefs.lookupType("android.surfaceflinger.LayersTraceFileProto");
-
+var TransactionMessage = protoDefs.lookupType("Trace");
 
 const LAYER_TRACE_MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45] // .LYRTRACE
 const WINDOW_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45] // .WINTRACE
@@ -50,7 +53,11 @@
   SCREEN_RECORDING: {
     name: "Screen recording",
     icon: "videocam",
-  }
+  },
+  TRANSACTION: {
+    name: "Transaction",
+    icon: "timeline",
+  },
 }
 
 const FILE_TYPES = {
@@ -101,6 +108,16 @@
     decoderParams: {
       videoDecoder: mp4Decoder,
     },
+  },
+  'transaction': {
+    name: "Transaction",
+    dataType: DATA_TYPES.TRANSACTION,
+    decoder: protoDecoder,
+    decoderParams: {
+      protoType: TransactionMessage,
+      transform: transform_transaction_trace,
+      timeline: true,
+    }
   }
 };
 
@@ -198,7 +215,7 @@
   if (arrayStartsWith(buffer, MPEG4_MAGIC_NMBER)) {
     return decodedFile(FILE_TYPES['screen_recording'], buffer, fileName, store);
   }
-  for (var name of ['layers_dump', 'window_dump']) {
+  for (var name of ['transaction', 'layers_dump', 'window_dump']) {
     try {
       return decodedFile(FILE_TYPES[name], buffer, fileName, store);
     } catch (ex) {
diff --git a/tools/winscope/src/transform_transaction.js b/tools/winscope/src/transform_transaction.js
new file mode 100644
index 0000000..da40bd1
--- /dev/null
+++ b/tools/winscope/src/transform_transaction.js
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {transform, nanos_to_string} from './transform.js'
+
+function transform_transaction(transaction) {
+  return transform({
+    obj: transaction,
+    kind: 'transaction',
+    children:[[transaction.surfaceChange, transform_entry_type('surfaceChange')],
+        [transaction.displayChange, transform_entry_type('displayChange')]],
+    rects: [],
+    visible: false,
+  })
+}
+
+function transform_entry_type(transactionType) {
+  function return_transform(item) {
+    return Object.freeze({
+      obj: item,
+      kind: transactionType,
+      rects: [],
+      visible: false,
+      name: item.name || item.id || nanos_to_string(item.when),
+    });
+  }
+  return transactionType === 'transaction' ? transform_transaction : return_transform;
+}
+
+function transform_entry(entry) {
+  var transactionType = entry.increment;
+  return transform({
+    obj: entry,
+    kind: 'entry',
+    name: nanos_to_string(entry.timeStamp),
+    children: [[[entry[transactionType]], transform_entry_type(transactionType)]],
+    timestamp: entry.timeStamp,
+  });
+}
+
+function transform_transaction_trace(entries) {
+  var r = transform({
+    obj: entries,
+    kind: 'entries',
+    name: 'transactionstrace',
+    children: [
+      [entries.increment, transform_entry],
+    ],
+  })
+  return r;
+}
+
+export {transform_transaction_trace};