test: update diff testing script to Python3

Also make the synthetic Python traces more resilient by using PYTHONPATH
environment variable to find synth_common instead of adding a hardcoded
arbitrary number of dirnames.

Change-Id: I9482b2ed613e7f459ee82f05413a456bc1f91be5
diff --git a/test/metrics/legacy/android_ion.py b/test/metrics/legacy/android_ion.py
index c7b8a2c..9618460 100644
--- a/test/metrics/legacy/android_ion.py
+++ b/test/metrics/legacy/android_ion.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -31,4 +29,4 @@
 trace.add_ion_event(ts=200, tid=3, heap_name='system', size=1000, len=1000)
 trace.add_ion_event(ts=299, tid=3, heap_name='adsp', size=1000, len=100)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_lmk.py b/test/metrics/legacy/android_lmk.py
index 9f07540..eaf9a3e 100644
--- a/test/metrics/legacy/android_lmk.py
+++ b/test/metrics/legacy/android_lmk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -33,4 +31,4 @@
 trace.add_oom_score_update(ts=151, oom_score_adj=0, pid=3)
 trace.add_kernel_lmk(ts=152, tid=4)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_lmk_reason.py b/test/metrics/legacy/android_lmk_reason.py
index 7010b8f..f5841f3 100644
--- a/test/metrics/legacy/android_lmk_reason.py
+++ b/test/metrics/legacy/android_lmk_reason.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 anon_member = 1
@@ -68,4 +66,4 @@
 trace.add_ftrace_packet(cpu=0)
 trace.add_oom_score_update(ts=1001, oom_score_adj=-800, pid=2)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_mem_by_priority.py b/test/metrics/legacy/android_mem_by_priority.py
index 890059c..685af43 100644
--- a/test/metrics/legacy/android_mem_by_priority.py
+++ b/test/metrics/legacy/android_mem_by_priority.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 file_member = 0
@@ -55,4 +53,4 @@
 trace.add_rss_stat(300, 3, anon_member, 3000)
 trace.add_rss_stat(300, 4, anon_member, 6000)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_package_list.py b/test/metrics/legacy/android_package_list.py
index e34bcc7..95ebb44 100644
--- a/test/metrics/legacy/android_package_list.py
+++ b/test/metrics/legacy/android_package_list.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,11 +15,9 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
 trace.add_package_list(1, 'com.my.pkg', 123, 456000)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup.py b/test/metrics/legacy/android_startup.py
index d0445ae..707c98f 100644
--- a/test/metrics/legacy/android_startup.py
+++ b/test/metrics/legacy/android_startup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -88,4 +86,4 @@
 trace.add_sched(ts=160, prev_pid=0, next_pid=1)
 trace.add_sched(ts=200, prev_pid=1, next_pid=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup_battery.py b/test/metrics/legacy/android_startup_battery.py
index bfdfced..3727a12 100644
--- a/test/metrics/legacy/android_startup_battery.py
+++ b/test/metrics/legacy/android_startup_battery.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -25,4 +23,4 @@
 trace.add_battery_counters(80, 15, 0.5, 9, 5)
 trace.add_battery_counters_no_curr_ua(92, 21, 0.3, 25)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup_breakdown.py b/test/metrics/legacy/android_startup_breakdown.py
index e5de4a8..b7d2d7b 100644
--- a/test/metrics/legacy/android_startup_breakdown.py
+++ b/test/metrics/legacy/android_startup_breakdown.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -55,4 +53,4 @@
     buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
 trace.add_atrace_end(ts=212, tid=2, pid=2)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup_cpu.py b/test/metrics/legacy/android_startup_cpu.py
index c4a9789..0876340 100644
--- a/test/metrics/legacy/android_startup_cpu.py
+++ b/test/metrics/legacy/android_startup_cpu.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -59,4 +57,4 @@
 trace.add_sched(ts=16 * 1000000, prev_pid=6, next_pid=3)
 trace.add_sched(ts=18 * 1000000, prev_pid=3, next_pid=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup_powrails.py b/test/metrics/legacy/android_startup_powrails.py
index ecac7ff..3e1b6d7 100644
--- a/test/metrics/legacy/android_startup_powrails.py
+++ b/test/metrics/legacy/android_startup_powrails.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -36,4 +35,4 @@
 trace.add_power_rails_data(6, 2, 70)
 trace.add_power_rails_data(6, 3, 15)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/metrics/legacy/android_startup_process_track.py b/test/metrics/legacy/android_startup_process_track.py
index f7ea16d..9636990 100644
--- a/test/metrics/legacy/android_startup_process_track.py
+++ b/test/metrics/legacy/android_startup_process_track.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -56,4 +56,4 @@
 trace.add_process_free(ts=150, tid=3, comm='', prio=0)
 add_startup(trace, ts=200, pid=4)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/synth_common.py b/test/synth_common.py
index e8f2c74..e9ec22f 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -244,7 +244,7 @@
     if seq_id is not None:
       packet.trusted_packet_sequence_id = seq_id
     snap = self.packet.clock_snapshot
-    for k, v in clocks.iteritems():
+    for k, v in clocks.items():
       clock = snap.clocks.add()
       clock.clock_id = k
       clock.timestamp = v
diff --git a/test/trace_processor/common/synth_1.py b/test/trace_processor/common/synth_1.py
index c67df51..359e2db 100644
--- a/test/trace_processor/common/synth_1.py
+++ b/test/trace_processor/common/synth_1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -39,4 +38,4 @@
 trace.add_sched(ts=390, prev_pid=2, next_pid=4)
 trace.add_cpufreq(ts=400, freq=100, cpu=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/ftrace/rss_stat_after_free.py b/test/trace_processor/ftrace/rss_stat_after_free.py
index 72ad260..ef00a73 100644
--- a/test/trace_processor/ftrace/rss_stat_after_free.py
+++ b/test/trace_processor/ftrace/rss_stat_after_free.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -41,4 +41,4 @@
 # Emit an event on another thread which reuses the struct after free.
 trace.add_rss_stat(103, tid=11, member=0, size=10, mm_id=0x1234, curr=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/ftrace/rss_stat_legacy.py b/test/trace_processor/ftrace/rss_stat_legacy.py
index 1442487..1eeb6c7 100644
--- a/test/trace_processor/ftrace/rss_stat_legacy.py
+++ b/test/trace_processor/ftrace/rss_stat_legacy.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -49,4 +49,4 @@
 # Add an event on tid 10 from tid 3.
 trace.add_rss_stat(ts=101, tid=3, member=0, size=900)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/ftrace/rss_stat_mm_id.py b/test/trace_processor/ftrace/rss_stat_mm_id.py
index 72683b4..b48dab9 100644
--- a/test/trace_processor/ftrace/rss_stat_mm_id.py
+++ b/test/trace_processor/ftrace/rss_stat_mm_id.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -49,4 +49,4 @@
 # where kthreadd is cleaning up the mm struct of another process.
 trace.add_rss_stat(ts=101, tid=3, member=0, size=900, mm_id=1234, curr=False)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/ftrace/rss_stat_mm_id_clone.py b/test/trace_processor/ftrace/rss_stat_mm_id_clone.py
index f95af76..3b36d88 100644
--- a/test/trace_processor/ftrace/rss_stat_mm_id_clone.py
+++ b/test/trace_processor/ftrace/rss_stat_mm_id_clone.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -95,4 +95,4 @@
 # Emit a rss stat for the new kernel thread.
 trace.add_rss_stat(102, tid=4, member=0, size=20, mm_id=0x2345, curr=1)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/ftrace/rss_stat_mm_id_reuse.py b/test/trace_processor/ftrace/rss_stat_mm_id_reuse.py
index 5ea2fba..479ed94 100644
--- a/test/trace_processor/ftrace/rss_stat_mm_id_reuse.py
+++ b/test/trace_processor/ftrace/rss_stat_mm_id_reuse.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -40,4 +40,4 @@
 # Emit an event for the new thread.
 trace.add_rss_stat(103, tid=10, member=0, size=10, mm_id=0x1234, curr=1)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_counters.py b/test/trace_processor/graphics/gpu_counters.py
index 81fda01..00ded78 100644
--- a/test/trace_processor/graphics/gpu_counters.py
+++ b/test/trace_processor/graphics/gpu_counters.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 # See gpu_counter_descriptor.proto
@@ -67,4 +67,4 @@
 trace.add_gpu_counter(24, 34, 9)
 trace.add_gpu_counter(34, 34, 7)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_log.py b/test/trace_processor/graphics/gpu_log.py
index 1f6ff94..f064173 100644
--- a/test/trace_processor/graphics/gpu_log.py
+++ b/test/trace_processor/graphics/gpu_log.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -25,4 +25,4 @@
 trace.add_gpu_log(ts=4, severity=5, tag="tag0", message="message4")
 trace.add_gpu_log(ts=5, severity=1, tag="tag1", message="message5")
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_mem_total.py b/test/trace_processor/graphics/gpu_mem_total.py
index 3860a68..bb9757b 100755
--- a/test/trace_processor/graphics/gpu_mem_total.py
+++ b/test/trace_processor/graphics/gpu_mem_total.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2020 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -34,4 +34,4 @@
 trace.add_gpu_mem_total(pid=1, ts=5, size=233)
 trace.add_gpu_mem_total(pid=1, ts=10, size=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/gpu_render_stages.py b/test/trace_processor/graphics/gpu_render_stages.py
index a62b0f7..b2fc239 100644
--- a/test/trace_processor/graphics/gpu_render_stages.py
+++ b/test/trace_processor/graphics/gpu_render_stages.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -223,4 +223,4 @@
     context=42,
     render_subpass_index_mask=[0x08, 0xF0])
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/graphics_frame_events.py b/test/trace_processor/graphics/graphics_frame_events.py
index f0067e0..2366ad2 100755
--- a/test/trace_processor/graphics/graphics_frame_events.py
+++ b/test/trace_processor/graphics/graphics_frame_events.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 class BufferEvent:
@@ -52,4 +52,4 @@
 trace.add_buffer_event_packet(ts=6, buffer_id=-1, layer_name="layer6", frame_number=14, event_type=BufferEvent.HWC_COMPOSITION_QUEUED, duration=0)
 # Missing type.
 trace.add_buffer_event_packet(ts=7, buffer_id=7, layer_name="layer7", frame_number=15, event_type=-1, duration=0)
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/vulkan_api_events.py b/test/trace_processor/graphics/vulkan_api_events.py
index da97740..0fe4ef0 100644
--- a/test/trace_processor/graphics/vulkan_api_events.py
+++ b/test/trace_processor/graphics/vulkan_api_events.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2020 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -37,4 +37,4 @@
     vk_command_buffers=[200, 300, 400],
     submission_id=2)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/clock_sync.py b/test/trace_processor/legacy/clock_sync.py
index e153135..690c736 100644
--- a/test/trace_processor/legacy/clock_sync.py
+++ b/test/trace_processor/legacy/clock_sync.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,8 +22,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 from synth_common import CLONE_THREAD
 
@@ -90,4 +88,4 @@
 # Other sequence's default clock isn't changed, so this should be in BOOTTIME.
 trace.add_gpu_counter(ts=3010, counter_id=42, value=15, seq_id=3)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/counters_group_by_freq.py b/test/trace_processor/legacy/counters_group_by_freq.py
index 50a16bf..daf1775 100644
--- a/test/trace_processor/legacy/counters_group_by_freq.py
+++ b/test/trace_processor/legacy/counters_group_by_freq.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -25,4 +24,4 @@
 trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
 trace.add_cpufreq(ts=1003, freq=3000, cpu=1)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/counters_where_cpu.py b/test/trace_processor/legacy/counters_where_cpu.py
index a4c763c..239390e 100644
--- a/test/trace_processor/legacy/counters_where_cpu.py
+++ b/test/trace_processor/legacy/counters_where_cpu.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -25,4 +24,4 @@
 trace.add_cpufreq(ts=1001, freq=4000, cpu=1)
 trace.add_cpufreq(ts=1002, freq=5000, cpu=2)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/frame_missed.py b/test/trace_processor/legacy/frame_missed.py
index 719d2dd..d08191d 100644
--- a/test/trace_processor/legacy/frame_missed.py
+++ b/test/trace_processor/legacy/frame_missed.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2020 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -38,4 +36,4 @@
 trace.add_print(ts=104, tid=11, buf='C|10|PrevFrameMissed|1')
 trace.add_print(ts=105, tid=11, buf='C|10|PrevFrameMissed|0')
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/kernel_lmk.py b/test/trace_processor/legacy/kernel_lmk.py
index cbcb927..9b26d4f 100644
--- a/test/trace_processor/legacy/kernel_lmk.py
+++ b/test/trace_processor/legacy/kernel_lmk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -34,4 +33,4 @@
 trace.add_kernel_lmk(ts=100, tid=300)
 trace.add_kernel_lmk(ts=101, tid=4)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/synth_oom.py b/test/trace_processor/legacy/synth_oom.py
index 740d3b3..973835e 100644
--- a/test/trace_processor/legacy/synth_oom.py
+++ b/test/trace_processor/legacy/synth_oom.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 file_member = 0
@@ -61,4 +60,4 @@
 trace.add_rss_stat(130, 2, file_member, 0)
 trace.add_rss_stat(130, 2, anon_member, 0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/syscall.py b/test/trace_processor/legacy/syscall.py
index 8038584..84ec946 100644
--- a/test/trace_processor/legacy/syscall.py
+++ b/test/trace_processor/legacy/syscall.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -33,4 +32,4 @@
 trace.add_sys_exit(ts=106, tid=1, id=0, ret=0)
 trace.add_sys_exit(ts=110, tid=2, id=1, ret=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/legacy/thread_time_in_state_event.py b/test/trace_processor/legacy/thread_time_in_state_event.py
index 01040ac..ab3b7f6 100644
--- a/test/trace_processor/legacy/thread_time_in_state_event.py
+++ b/test/trace_processor/legacy/thread_time_in_state_event.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2020 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +15,6 @@
 
 from os import sys, path
 
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
 import synth_common
 
 # Since we do various time based conversions to build cycles/sec, ensure that
@@ -61,4 +59,4 @@
 # the little core but not the big one.
 trace.add_process_stats(pid=4, freqs={1: 2, 9: 1})
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py b/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py
index c636f91..0018381 100644
--- a/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py
+++ b/test/trace_processor/process_tracking/process_parent_pid_tracking_1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -33,4 +33,4 @@
 trace.add_ftrace_packet(0)
 trace.add_newtask(ts=15, tid=11, new_tid=20, new_comm='child', flags=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py b/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py
index 0916b2d..bbea355 100644
--- a/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py
+++ b/test/trace_processor/process_tracking/process_parent_pid_tracking_2.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -34,4 +34,4 @@
 trace.add_process(10, 0, "main_thread")
 trace.add_thread(11, 10, "worker_thread")
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_exec.py b/test/trace_processor/process_tracking/process_tracking_exec.py
index 8e054da..4fc2290 100644
--- a/test/trace_processor/process_tracking/process_tracking_exec.py
+++ b/test/trace_processor/process_tracking/process_tracking_exec.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -44,4 +44,4 @@
 trace.add_packet(ts=30)
 trace.add_process(11, 10, "true_process_name")
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_short_lived_1.py b/test/trace_processor/process_tracking/process_tracking_short_lived_1.py
index e3dadab..d862335 100644
--- a/test/trace_processor/process_tracking/process_tracking_short_lived_1.py
+++ b/test/trace_processor/process_tracking/process_tracking_short_lived_1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -34,4 +34,4 @@
 trace.add_sched(ts=16, prev_pid=10, next_pid=11, next_comm='child')
 trace.add_process_free(ts=20, tid=11, comm='child', prio=0)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/process_tracking_short_lived_2.py b/test/trace_processor/process_tracking/process_tracking_short_lived_2.py
index 2ce3f31..d8e3837 100644
--- a/test/trace_processor/process_tracking/process_tracking_short_lived_2.py
+++ b/test/trace_processor/process_tracking/process_tracking_short_lived_2.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -36,4 +36,4 @@
 trace.add_rename(
     ts=17, tid=11, old_comm='child', new_comm='true_name', oom_score_adj=1000)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/reused_thread_print.py b/test/trace_processor/process_tracking/reused_thread_print.py
index cdb0262..2429452 100644
--- a/test/trace_processor/process_tracking/reused_thread_print.py
+++ b/test/trace_processor/process_tracking/reused_thread_print.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -48,4 +48,4 @@
 trace.add_atrace_begin(ts=18, tid=10, pid=10, buf='test')
 trace.add_atrace_end(ts=19, tid=11, pid=10)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking/synth_process_tracking.py b/test/trace_processor/process_tracking/synth_process_tracking.py
index cbb023d..68641ad 100644
--- a/test/trace_processor/process_tracking/synth_process_tracking.py
+++ b/test/trace_processor/process_tracking/synth_process_tracking.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@
 # packets (i.e. the result of the userspace /proc/pid scraper).
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 from synth_common import CLONE_THREAD
 import synth_common
 
@@ -100,4 +100,4 @@
 trace.add_sched(
     ts=31, prev_pid=40, next_pid=31, prev_comm='p4-t0', next_comm='p4-t1')
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/systrace/print_systrace_unsigned.py b/test/trace_processor/systrace/print_systrace_unsigned.py
index 70f6fc2..c63ce57 100644
--- a/test/trace_processor/systrace/print_systrace_unsigned.py
+++ b/test/trace_processor/systrace/print_systrace_unsigned.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,7 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(
-    path.dirname(path.dirname(path.dirname(path.abspath(__file__)))))
+
 import synth_common
 
 trace = synth_common.create_trace()
@@ -48,4 +47,4 @@
     gfp_flags=0,
     ptr=(1 << 64) - 32)
 
-print(trace.trace.SerializeToString())
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index e7fc030..61ea9c2 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -62,9 +62,6 @@
                                 'perfetto.protos.TraceMetrics')
 
 
-
-
-
 def write_diff(expected, actual):
   expected_lines = expected.splitlines(True)
   actual_lines = actual.splitlines(True)
@@ -164,6 +161,8 @@
       test_failure += 1
       continue
 
+    is_generated_trace = trace_path.endswith('.py') or trace_path.endswith(
+        '.textproto')
     if trace_path.endswith('.py'):
       gen_trace_file = tempfile.NamedTemporaryFile(delete=False)
       serialize_python_trace(trace_descriptor_path, trace_path, gen_trace_file)
@@ -204,11 +203,22 @@
 
     if gen_trace_file:
       if keep_input:
-        print("Saving generated input trace: {}".format(gen_trace_path))
+        sys.stderr.write(
+            "Saving generated input trace: {}\n".format(gen_trace_path))
       else:
         gen_trace_file.close()
         os.remove(gen_trace_path)
 
+    def write_cmdlines():
+      if is_generated_trace:
+        sys.stderr.write(
+            'Command to generate trace:\n'
+            'tools/serialize_test_trace.py --descriptor {} {} > {}\n'.format(
+                os.path.relpath(trace_descriptor_path, ROOT_DIR),
+                os.path.relpath(trace_descriptor_path, trace_path),
+                os.path.relpath(gen_trace_path, ROOT_DIR)))
+      sys.stderr.write('Command line:\n{}\n'.format(' '.join(result.cmd)))
+
     if result.exit_code != 0 or result.expected != result.actual:
       sys.stderr.write(result.stderr)
 
@@ -217,11 +227,10 @@
             'Expected did not match actual for trace {} and {} {}\n'.format(
                 trace_path, result.test_type, result.input_name))
         sys.stderr.write('Expected file: {}\n'.format(expected_path))
-        sys.stderr.write('Command line: {}\n'.format(' '.join(result.cmd)))
-
+        write_cmdlines()
         write_diff(result.expected, result.actual)
       else:
-        sys.stderr.write('Command line: {}\n'.format(' '.join(result.cmd)))
+        write_cmdlines()
 
       sys.stderr.write('[     FAIL ] {} {}\n'.format(
           os.path.basename(test.query_path_or_metric),
@@ -381,7 +390,10 @@
       trace_processor_dir = os.path.join(test_dir, 'trace_processor')
 
       metrics = []
-      for perf_args in sorted(perf_data):
+      sorted_data = sorted(
+          perf_data,
+          key=lambda x: (x.test_type, x.trace_path, x.query_path_or_metric))
+      for perf_args in sorted_data:
         trace_short_path = os.path.relpath(perf_args.trace_path, test_dir)
 
         query_short_path_or_metric = perf_args.query_path_or_metric
diff --git a/tools/proto_utils.py b/tools/proto_utils.py
index f8a9e50..455f15e 100644
--- a/tools/proto_utils.py
+++ b/tools/proto_utils.py
@@ -22,6 +22,9 @@
 from google.protobuf import reflection, text_format
 
 
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
 def create_message_factory(descriptor_file_path, proto_type):
   with open(descriptor_file_path, 'rb') as descriptor_file:
     descriptor_content = descriptor_file.read()
@@ -56,5 +59,13 @@
 
 def serialize_python_trace(trace_descriptor_path, python_trace_path,
                            out_stream):
-  python_cmd = ['python', python_trace_path, trace_descriptor_path]
-  subprocess.check_call(python_cmd, stdout=out_stream)
+  python_cmd = ['python3', python_trace_path, trace_descriptor_path]
+
+  # Add the test dir to the PYTHONPATH to allow synth_common to be found.
+  env = os.environ.copy()
+  if 'PYTHONPATH' in env:
+    env['PYTHONPATH'] = "{}:{}".format(
+        os.path.join(ROOT_DIR, 'test'), env['PYTHONPATH'])
+  else:
+    env['PYTHONPATH'] = os.path.join(ROOT_DIR, 'test')
+  subprocess.check_call(python_cmd, env=env, stdout=out_stream)
diff --git a/tools/serialize_test_trace.py b/tools/serialize_test_trace.py
index 9a0aab4..cf8257f 100755
--- a/tools/serialize_test_trace.py
+++ b/tools/serialize_test_trace.py
@@ -29,14 +29,20 @@
   parser.add_argument(
       '--out',
       type=str,
-      required=True,
       help='out directory to search for trace descriptor')
+  parser.add_argument(
+      '--descriptor', type=str, help='path to the trace descriptor')
   parser.add_argument('trace_path', type=str, help='path of trace to serialize')
   args = parser.parse_args()
 
-  trace_protos_path = os.path.join(args.out, 'gen', 'protos', 'perfetto',
-                                   'trace')
-  trace_descriptor_path = os.path.join(trace_protos_path, 'trace.descriptor')
+  if args.out and not args.descriptor:
+    trace_protos_path = os.path.join(args.out, 'gen', 'protos', 'perfetto',
+                                     'trace')
+    trace_descriptor_path = os.path.join(trace_protos_path, 'trace.descriptor')
+  elif args.descriptor and not args.out:
+    trace_descriptor_path = args.descriptor
+  else:
+    raise RuntimeError('Exactly one of --out and --descriptor should be provided')
 
   trace_path = args.trace_path