Add suport for TAR files

Changes in this cl:

* Tar file reader
* Move all archive related importers to a common dir
* Tar files also need to sort trace files prior to sendind data to the
  sorting stage (same as ZIP) so this cl extracts that logic to its own
  class: CombinedTraceParser
* Simplified a bit the tracking of trace_files
* The TraceFileTable now tracks all files detected during parsing and
  explicitly shows the order in which they were parsed.
* Add an efficient way of extracting multiple TraceBlobView spans from a
  TraceBlobViewReader (avoiding the copy to a contiguous buffer).

Change-Id: I09f32c9304fcfec4853d0c3e8cb1d955df3a641a
diff --git a/Android.bp b/Android.bp
index 4db773b..d0729b4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2467,6 +2467,7 @@
         ":perfetto_src_trace_processor_export_json",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_bugreport",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_log_event",
+        ":perfetto_src_trace_processor_importers_archive_archive",
         ":perfetto_src_trace_processor_importers_art_method_art_method",
         ":perfetto_src_trace_processor_importers_art_method_art_method_event",
         ":perfetto_src_trace_processor_importers_common_common",
@@ -2481,7 +2482,6 @@
         ":perfetto_src_trace_processor_importers_fuchsia_full",
         ":perfetto_src_trace_processor_importers_fuchsia_minimal",
         ":perfetto_src_trace_processor_importers_gecko_gecko_event",
-        ":perfetto_src_trace_processor_importers_gzip_full",
         ":perfetto_src_trace_processor_importers_i2c_full",
         ":perfetto_src_trace_processor_importers_instruments_instruments",
         ":perfetto_src_trace_processor_importers_instruments_row",
@@ -2504,7 +2504,6 @@
         ":perfetto_src_trace_processor_importers_systrace_full",
         ":perfetto_src_trace_processor_importers_systrace_systrace_line",
         ":perfetto_src_trace_processor_importers_systrace_systrace_parser",
-        ":perfetto_src_trace_processor_importers_zip_full",
         ":perfetto_src_trace_processor_lib",
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
@@ -12399,6 +12398,17 @@
     ],
 }
 
+// GN: //src/trace_processor/importers/archive:archive
+filegroup {
+    name: "perfetto_src_trace_processor_importers_archive_archive",
+    srcs: [
+        "src/trace_processor/importers/archive/archive_entry.cc",
+        "src/trace_processor/importers/archive/gzip_trace_parser.cc",
+        "src/trace_processor/importers/archive/tar_trace_reader.cc",
+        "src/trace_processor/importers/archive/zip_trace_reader.cc",
+    ],
+}
+
 // GN: //src/trace_processor/importers/art_method:art_method
 filegroup {
     name: "perfetto_src_trace_processor_importers_art_method_art_method",
@@ -12435,7 +12445,6 @@
         "src/trace_processor/importers/common/process_track_translation_table.cc",
         "src/trace_processor/importers/common/process_tracker.cc",
         "src/trace_processor/importers/common/sched_event_tracker.cc",
-        "src/trace_processor/importers/common/scoped_active_trace_file.cc",
         "src/trace_processor/importers/common/slice_tracker.cc",
         "src/trace_processor/importers/common/slice_translation_table.cc",
         "src/trace_processor/importers/common/stack_profile_tracker.cc",
@@ -12581,14 +12590,6 @@
     name: "perfetto_src_trace_processor_importers_gecko_gecko_event",
 }
 
-// GN: //src/trace_processor/importers/gzip:full
-filegroup {
-    name: "perfetto_src_trace_processor_importers_gzip_full",
-    srcs: [
-        "src/trace_processor/importers/gzip/gzip_trace_parser.cc",
-    ],
-}
-
 // GN: //src/trace_processor/importers/i2c:full
 filegroup {
     name: "perfetto_src_trace_processor_importers_i2c_full",
@@ -12996,14 +12997,6 @@
     ],
 }
 
-// GN: //src/trace_processor/importers/zip:full
-filegroup {
-    name: "perfetto_src_trace_processor_importers_zip_full",
-    srcs: [
-        "src/trace_processor/importers/zip/zip_trace_reader.cc",
-    ],
-}
-
 // GN: //src/trace_processor:lib
 filegroup {
     name: "perfetto_src_trace_processor_lib",
@@ -15626,6 +15619,7 @@
         ":perfetto_src_trace_processor_importers_android_bugreport_android_bugreport",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_log_event",
         ":perfetto_src_trace_processor_importers_android_bugreport_unittests",
+        ":perfetto_src_trace_processor_importers_archive_archive",
         ":perfetto_src_trace_processor_importers_art_method_art_method",
         ":perfetto_src_trace_processor_importers_art_method_art_method_event",
         ":perfetto_src_trace_processor_importers_common_common",
@@ -15643,7 +15637,6 @@
         ":perfetto_src_trace_processor_importers_fuchsia_minimal",
         ":perfetto_src_trace_processor_importers_fuchsia_unittests",
         ":perfetto_src_trace_processor_importers_gecko_gecko_event",
-        ":perfetto_src_trace_processor_importers_gzip_full",
         ":perfetto_src_trace_processor_importers_i2c_full",
         ":perfetto_src_trace_processor_importers_instruments_instruments",
         ":perfetto_src_trace_processor_importers_instruments_row",
@@ -15671,7 +15664,6 @@
         ":perfetto_src_trace_processor_importers_systrace_systrace_line",
         ":perfetto_src_trace_processor_importers_systrace_systrace_parser",
         ":perfetto_src_trace_processor_importers_systrace_unittests",
-        ":perfetto_src_trace_processor_importers_zip_full",
         ":perfetto_src_trace_processor_lib",
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
@@ -16701,6 +16693,7 @@
         ":perfetto_src_trace_processor_export_json",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_bugreport",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_log_event",
+        ":perfetto_src_trace_processor_importers_archive_archive",
         ":perfetto_src_trace_processor_importers_art_method_art_method",
         ":perfetto_src_trace_processor_importers_art_method_art_method_event",
         ":perfetto_src_trace_processor_importers_common_common",
@@ -16715,7 +16708,6 @@
         ":perfetto_src_trace_processor_importers_fuchsia_full",
         ":perfetto_src_trace_processor_importers_fuchsia_minimal",
         ":perfetto_src_trace_processor_importers_gecko_gecko_event",
-        ":perfetto_src_trace_processor_importers_gzip_full",
         ":perfetto_src_trace_processor_importers_i2c_full",
         ":perfetto_src_trace_processor_importers_instruments_instruments",
         ":perfetto_src_trace_processor_importers_instruments_row",
@@ -16738,7 +16730,6 @@
         ":perfetto_src_trace_processor_importers_systrace_full",
         ":perfetto_src_trace_processor_importers_systrace_systrace_line",
         ":perfetto_src_trace_processor_importers_systrace_systrace_parser",
-        ":perfetto_src_trace_processor_importers_zip_full",
         ":perfetto_src_trace_processor_lib",
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
@@ -17128,6 +17119,7 @@
         ":perfetto_src_trace_processor_export_json",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_bugreport",
         ":perfetto_src_trace_processor_importers_android_bugreport_android_log_event",
+        ":perfetto_src_trace_processor_importers_archive_archive",
         ":perfetto_src_trace_processor_importers_art_method_art_method",
         ":perfetto_src_trace_processor_importers_art_method_art_method_event",
         ":perfetto_src_trace_processor_importers_common_common",
@@ -17142,7 +17134,6 @@
         ":perfetto_src_trace_processor_importers_fuchsia_full",
         ":perfetto_src_trace_processor_importers_fuchsia_minimal",
         ":perfetto_src_trace_processor_importers_gecko_gecko_event",
-        ":perfetto_src_trace_processor_importers_gzip_full",
         ":perfetto_src_trace_processor_importers_i2c_full",
         ":perfetto_src_trace_processor_importers_instruments_instruments",
         ":perfetto_src_trace_processor_importers_instruments_row",
@@ -17165,7 +17156,6 @@
         ":perfetto_src_trace_processor_importers_systrace_full",
         ":perfetto_src_trace_processor_importers_systrace_systrace_line",
         ":perfetto_src_trace_processor_importers_systrace_systrace_parser",
-        ":perfetto_src_trace_processor_importers_zip_full",
         ":perfetto_src_trace_processor_lib",
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
diff --git a/BUILD b/BUILD
index e03af4f..9201633 100644
--- a/BUILD
+++ b/BUILD
@@ -223,6 +223,7 @@
         ":src_trace_processor_export_json",
         ":src_trace_processor_importers_android_bugreport_android_bugreport",
         ":src_trace_processor_importers_android_bugreport_android_log_event",
+        ":src_trace_processor_importers_archive_archive",
         ":src_trace_processor_importers_art_method_art_method",
         ":src_trace_processor_importers_art_method_art_method_event",
         ":src_trace_processor_importers_common_common",
@@ -238,7 +239,6 @@
         ":src_trace_processor_importers_fuchsia_minimal",
         ":src_trace_processor_importers_gecko_gecko",
         ":src_trace_processor_importers_gecko_gecko_event",
-        ":src_trace_processor_importers_gzip_full",
         ":src_trace_processor_importers_i2c_full",
         ":src_trace_processor_importers_instruments_instruments",
         ":src_trace_processor_importers_instruments_row",
@@ -261,7 +261,6 @@
         ":src_trace_processor_importers_systrace_full",
         ":src_trace_processor_importers_systrace_systrace_line",
         ":src_trace_processor_importers_systrace_systrace_parser",
-        ":src_trace_processor_importers_zip_full",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
@@ -1520,6 +1519,21 @@
     ],
 )
 
+# GN target: //src/trace_processor/importers/archive:archive
+perfetto_filegroup(
+    name = "src_trace_processor_importers_archive_archive",
+    srcs = [
+        "src/trace_processor/importers/archive/archive_entry.cc",
+        "src/trace_processor/importers/archive/archive_entry.h",
+        "src/trace_processor/importers/archive/gzip_trace_parser.cc",
+        "src/trace_processor/importers/archive/gzip_trace_parser.h",
+        "src/trace_processor/importers/archive/tar_trace_reader.cc",
+        "src/trace_processor/importers/archive/tar_trace_reader.h",
+        "src/trace_processor/importers/archive/zip_trace_reader.cc",
+        "src/trace_processor/importers/archive/zip_trace_reader.h",
+    ],
+)
+
 # GN target: //src/trace_processor/importers/art_method:art_method
 perfetto_filegroup(
     name = "src_trace_processor_importers_art_method_art_method",
@@ -1583,8 +1597,6 @@
         "src/trace_processor/importers/common/sched_event_state.h",
         "src/trace_processor/importers/common/sched_event_tracker.cc",
         "src/trace_processor/importers/common/sched_event_tracker.h",
-        "src/trace_processor/importers/common/scoped_active_trace_file.cc",
-        "src/trace_processor/importers/common/scoped_active_trace_file.h",
         "src/trace_processor/importers/common/slice_tracker.cc",
         "src/trace_processor/importers/common/slice_tracker.h",
         "src/trace_processor/importers/common/slice_translation_table.cc",
@@ -1748,15 +1760,6 @@
     ],
 )
 
-# GN target: //src/trace_processor/importers/gzip:full
-perfetto_filegroup(
-    name = "src_trace_processor_importers_gzip_full",
-    srcs = [
-        "src/trace_processor/importers/gzip/gzip_trace_parser.cc",
-        "src/trace_processor/importers/gzip/gzip_trace_parser.h",
-    ],
-)
-
 # GN target: //src/trace_processor/importers/i2c:full
 perfetto_filegroup(
     name = "src_trace_processor_importers_i2c_full",
@@ -2200,15 +2203,6 @@
     ],
 )
 
-# GN target: //src/trace_processor/importers/zip:full
-perfetto_filegroup(
-    name = "src_trace_processor_importers_zip_full",
-    srcs = [
-        "src/trace_processor/importers/zip/zip_trace_reader.cc",
-        "src/trace_processor/importers/zip/zip_trace_reader.h",
-    ],
-)
-
 # GN target: //src/trace_processor/metrics/sql/android:android
 perfetto_filegroup(
     name = "src_trace_processor_metrics_sql_android_android",
@@ -6410,6 +6404,7 @@
         ":src_trace_processor_export_json",
         ":src_trace_processor_importers_android_bugreport_android_bugreport",
         ":src_trace_processor_importers_android_bugreport_android_log_event",
+        ":src_trace_processor_importers_archive_archive",
         ":src_trace_processor_importers_art_method_art_method",
         ":src_trace_processor_importers_art_method_art_method_event",
         ":src_trace_processor_importers_common_common",
@@ -6425,7 +6420,6 @@
         ":src_trace_processor_importers_fuchsia_minimal",
         ":src_trace_processor_importers_gecko_gecko",
         ":src_trace_processor_importers_gecko_gecko_event",
-        ":src_trace_processor_importers_gzip_full",
         ":src_trace_processor_importers_i2c_full",
         ":src_trace_processor_importers_instruments_instruments",
         ":src_trace_processor_importers_instruments_row",
@@ -6448,7 +6442,6 @@
         ":src_trace_processor_importers_systrace_full",
         ":src_trace_processor_importers_systrace_systrace_line",
         ":src_trace_processor_importers_systrace_systrace_parser",
-        ":src_trace_processor_importers_zip_full",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
@@ -6614,6 +6607,7 @@
         ":src_trace_processor_export_json",
         ":src_trace_processor_importers_android_bugreport_android_bugreport",
         ":src_trace_processor_importers_android_bugreport_android_log_event",
+        ":src_trace_processor_importers_archive_archive",
         ":src_trace_processor_importers_art_method_art_method",
         ":src_trace_processor_importers_art_method_art_method_event",
         ":src_trace_processor_importers_common_common",
@@ -6629,7 +6623,6 @@
         ":src_trace_processor_importers_fuchsia_minimal",
         ":src_trace_processor_importers_gecko_gecko",
         ":src_trace_processor_importers_gecko_gecko_event",
-        ":src_trace_processor_importers_gzip_full",
         ":src_trace_processor_importers_i2c_full",
         ":src_trace_processor_importers_instruments_instruments",
         ":src_trace_processor_importers_instruments_row",
@@ -6652,7 +6645,6 @@
         ":src_trace_processor_importers_systrace_full",
         ":src_trace_processor_importers_systrace_systrace_line",
         ":src_trace_processor_importers_systrace_systrace_parser",
-        ":src_trace_processor_importers_zip_full",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
@@ -6875,6 +6867,7 @@
         ":src_trace_processor_export_json",
         ":src_trace_processor_importers_android_bugreport_android_bugreport",
         ":src_trace_processor_importers_android_bugreport_android_log_event",
+        ":src_trace_processor_importers_archive_archive",
         ":src_trace_processor_importers_art_method_art_method",
         ":src_trace_processor_importers_art_method_art_method_event",
         ":src_trace_processor_importers_common_common",
@@ -6890,7 +6883,6 @@
         ":src_trace_processor_importers_fuchsia_minimal",
         ":src_trace_processor_importers_gecko_gecko",
         ":src_trace_processor_importers_gecko_gecko_event",
-        ":src_trace_processor_importers_gzip_full",
         ":src_trace_processor_importers_i2c_full",
         ":src_trace_processor_importers_instruments_instruments",
         ":src_trace_processor_importers_instruments_row",
@@ -6913,7 +6905,6 @@
         ":src_trace_processor_importers_systrace_full",
         ":src_trace_processor_importers_systrace_systrace_line",
         ":src_trace_processor_importers_systrace_systrace_parser",
-        ":src_trace_processor_importers_zip_full",
         ":src_trace_processor_lib",
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index a6bff20..0e99a43 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -168,12 +168,12 @@
       "../protozero",
       "db",
       "importers/android_bugreport",
+      "importers/archive",
       "importers/art_method",
       "importers/common",
       "importers/etw:full",
       "importers/ftrace:full",
       "importers/fuchsia:full",
-      "importers/gzip:full",
       "importers/json:full",
       "importers/json:minimal",
       "importers/ninja",
@@ -182,7 +182,6 @@
       "importers/proto:full",
       "importers/proto:minimal",
       "importers/systrace:full",
-      "importers/zip:full",
       "metrics",
       "perfetto_sql/engine",
       "perfetto_sql/intrinsics/functions",
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
index bc9f044..23b32b1 100644
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -26,9 +26,11 @@
 #include "perfetto/trace_processor/basic_types.h"
 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/trace_file_tracker.h"
 #include "src/trace_processor/importers/proto/proto_trace_reader.h"
 #include "src/trace_processor/sorter/trace_sorter.h"
 #include "src/trace_processor/storage/stats.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
 #include "src/trace_processor/trace_reader_registry.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 #include "src/trace_processor/util/status_macros.h"
@@ -65,6 +67,7 @@
     case kJsonTraceType:
     case kFuchsiaTraceType:
     case kZipFile:
+    case kTarTraceType:
     case kAndroidLogcatTraceType:
     case kGeckoTraceType:
     case kArtMethodTraceType:
@@ -85,8 +88,9 @@
 
 }  // namespace
 
-ForwardingTraceParser::ForwardingTraceParser(TraceProcessorContext* context)
-    : context_(context) {}
+ForwardingTraceParser::ForwardingTraceParser(TraceProcessorContext* context,
+                                             tables::TraceFileTable::Id id)
+    : context_(context), file_id_(id) {}
 
 ForwardingTraceParser::~ForwardingTraceParser() {}
 
@@ -104,6 +108,8 @@
     return base::ErrStatus("Unknown trace type provided (ERR:fmt)");
   }
 
+  context_->trace_file_tracker->StartParsing(file_id_, trace_type_);
+
   base::StatusOr<std::unique_ptr<ChunkedTraceReader>> reader_or =
       context_->reader_registry->CreateTraceReader(trace_type_);
   if (!reader_or.ok()) {
@@ -151,11 +157,17 @@
   if (!reader_) {
     RETURN_IF_ERROR(Init(blob));
   }
+  trace_size_ += blob.size();
   return reader_->Parse(std::move(blob));
 }
 
 base::Status ForwardingTraceParser::NotifyEndOfFile() {
-  return reader_ ? reader_->NotifyEndOfFile() : base::OkStatus();
+  base::Status status = base::OkStatus();
+  if (reader_) {
+    status = reader_->NotifyEndOfFile();
+  }
+  context_->trace_file_tracker->DoneParsing(file_id_, trace_size_);
+  return status;
 }
 
 }  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/forwarding_trace_parser.h b/src/trace_processor/forwarding_trace_parser.h
index fa90279..1f4858a 100644
--- a/src/trace_processor/forwarding_trace_parser.h
+++ b/src/trace_processor/forwarding_trace_parser.h
@@ -22,6 +22,7 @@
 #include "perfetto/base/status.h"
 #include "perfetto/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
 #include "src/trace_processor/util/trace_type.h"
 
 namespace perfetto::trace_processor {
@@ -30,7 +31,8 @@
 
 class ForwardingTraceParser : public ChunkedTraceReader {
  public:
-  explicit ForwardingTraceParser(TraceProcessorContext*);
+  explicit ForwardingTraceParser(TraceProcessorContext*,
+                                 tables::TraceFileTable::Id);
   ~ForwardingTraceParser() override;
 
   // ChunkedTraceReader implementation
@@ -43,6 +45,8 @@
   base::Status Init(const TraceBlobView&);
   void UpdateSorterForTraceType(TraceType trace_type);
   TraceProcessorContext* const context_;
+  tables::TraceFileTable::Id file_id_;
+  size_t trace_size_ = 0;
   std::unique_ptr<ChunkedTraceReader> reader_;
   TraceType trace_type_ = kUnknownTraceType;
 };
diff --git a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc
index fee307f..07c8434 100644
--- a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc
+++ b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc
@@ -104,17 +104,21 @@
 
   // Move the file to the end move it out of the list and pop the back.
   std::swap(files[res->file_index], files.back());
-  BugReportFile bug_report{res->year, std::move(files.back())};
+  auto id = context->trace_file_tracker->AddFile(files.back().name());
+  BugReportFile bug_report{id, res->year, std::move(files.back())};
   files.pop_back();
 
   std::set<LogFile> ordered_log_files;
   for (size_t i = 0; i < files.size(); ++i) {
+    id = context->trace_file_tracker->AddFile(files[i].name());
+    // Set size in case we end up not parsing this file.
+    context->trace_file_tracker->SetSize(id, files[i].compressed_size());
     if (!IsLogFile(files[i])) {
       continue;
     }
 
     int64_t timestamp = files[i].GetDatetime();
-    ordered_log_files.insert(LogFile{timestamp, std::move(files[i])});
+    ordered_log_files.insert(LogFile{id, timestamp, std::move(files[i])});
   }
 
   return AndroidBugreportReader(context, std::move(bug_report),
@@ -146,9 +150,8 @@
 
 base::Status AndroidBugreportReader::ParseDumpstateTxt(
     std::vector<TimestampedAndroidLogEvent> logcat_events) {
-  ScopedActiveTraceFile trace_file = context_->trace_file_tracker->StartNewFile(
-      bug_report_.file.name(), kAndroidDumpstateTraceType,
-      bug_report_.file.uncompressed_size());
+  context_->trace_file_tracker->StartParsing(bug_report_.id,
+                                             kAndroidDumpstateTraceType);
   AndroidDumpstateReader reader(context_, bug_report_.year,
                                 std::move(logcat_events));
   base::Status status = bug_report_.file.DecompressLines(
@@ -157,6 +160,8 @@
           reader.ParseLine(line);
         }
       });
+  context_->trace_file_tracker->DoneParsing(
+      bug_report_.id, bug_report_.file.uncompressed_size());
   return status;
 }
 
@@ -167,16 +172,16 @@
   // Push all events into the AndroidLogParser. It will take care of string
   // interning into the pool. Appends entries into `log_events`.
   for (const auto& log_file : ordered_log_files_) {
-    ScopedActiveTraceFile trace_file =
-        context_->trace_file_tracker->StartNewFile(
-            log_file.file.name(), kAndroidLogcatTraceType,
-            log_file.file.uncompressed_size());
+    context_->trace_file_tracker->StartParsing(log_file.id,
+                                               kAndroidLogcatTraceType);
     RETURN_IF_ERROR(log_file.file.DecompressLines(
         [&](const std::vector<base::StringView>& lines) {
           for (const auto& line : lines) {
             log_reader.ParseLine(line);
           }
         }));
+    context_->trace_file_tracker->DoneParsing(
+        log_file.id, log_file.file.uncompressed_size());
   }
 
   return std::move(log_reader).ConsumeBufferedEvents();
diff --git a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.h b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.h
index e0fe4fe..b36c45c 100644
--- a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.h
+++ b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.h
@@ -26,6 +26,7 @@
 #include "perfetto/ext/base/status_or.h"
 #include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/importers/android_bugreport/android_log_reader.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
 #include "src/trace_processor/util/zip_reader.h"
 
 namespace perfetto ::trace_processor {
@@ -46,10 +47,12 @@
 
  private:
   struct BugReportFile {
+    tables::TraceFileTable::Id id;
     int32_t year;
     util::ZipFile file;
   };
   struct LogFile {
+    tables::TraceFileTable::Id id;
     int64_t timestamp;
     util::ZipFile file;
     // Sort files to ease the job of the line-based sort. Unfortunately
diff --git a/src/trace_processor/importers/zip/BUILD.gn b/src/trace_processor/importers/archive/BUILD.gn
similarity index 66%
rename from src/trace_processor/importers/zip/BUILD.gn
rename to src/trace_processor/importers/archive/BUILD.gn
index 0262e02..4f092ad 100644
--- a/src/trace_processor/importers/zip/BUILD.gn
+++ b/src/trace_processor/importers/archive/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Android Open Source Project
+# Copyright (C) 2024 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.
@@ -12,18 +12,31 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-source_set("full") {
+source_set("archive") {
   sources = [
+    "archive_entry.cc",
+    "archive_entry.h",
+    "gzip_trace_parser.cc",
+    "gzip_trace_parser.h",
+    "tar_trace_reader.cc",
+    "tar_trace_reader.h",
     "zip_trace_reader.cc",
     "zip_trace_reader.h",
   ]
   deps = [
+    "../..:storage_minimal",
     "../../../../gn:default_deps",
+    "../../../../include/perfetto/base:base",
     "../../../../include/perfetto/ext/base:base",
+    "../../../base",
     "../../../trace_processor:storage_minimal",
+    "../../storage",
+    "../../tables:tables_python",
     "../../types",
+    "../../util",
+    "../../util:gzip",
+    "../../util:trace_blob_view_reader",
     "../../util:trace_type",
-    "../../util:util",
     "../../util:zip_reader",
     "../android_bugreport",
     "../common",
diff --git a/src/trace_processor/importers/archive/archive_entry.cc b/src/trace_processor/importers/archive/archive_entry.cc
new file mode 100644
index 0000000..1d187df
--- /dev/null
+++ b/src/trace_processor/importers/archive/archive_entry.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include "src/trace_processor/importers/archive/archive_entry.h"
+
+#include <tuple>
+
+namespace perfetto::trace_processor {
+
+bool ArchiveEntry::operator<(const ArchiveEntry& rhs) const {
+  // Traces with symbols should be the last ones to be read.
+  // TODO(carlscab): Proto traces with just ModuleSymbols packets should be an
+  // exception. We actually need those are the very end (once whe have all the
+  // Frames). Alternatively we could build a map address -> symbol during
+  // tokenization and use this during parsing to resolve symbols.
+  if (trace_type == kSymbolsTraceType) {
+    return false;
+  }
+  if (rhs.trace_type == kSymbolsTraceType) {
+    return true;
+  }
+
+  // Proto traces should always parsed first as they might contains clock sync
+  // data needed to correctly parse other traces.
+  if (rhs.trace_type == TraceType::kProtoTraceType) {
+    return false;
+  }
+  if (trace_type == TraceType::kProtoTraceType) {
+    return true;
+  }
+
+  if (rhs.trace_type == TraceType::kGzipTraceType) {
+    return false;
+  }
+  if (trace_type == TraceType::kGzipTraceType) {
+    return true;
+  }
+
+  return std::tie(name, index) < std::tie(rhs.name, rhs.index);
+}
+
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/archive/archive_entry.h b/src/trace_processor/importers/archive/archive_entry.h
new file mode 100644
index 0000000..ae13cf7
--- /dev/null
+++ b/src/trace_processor/importers/archive/archive_entry.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ARCHIVE_ENTRY_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ARCHIVE_ENTRY_H_
+
+#include <string>
+
+#include "src/trace_processor/util/trace_type.h"
+
+namespace perfetto::trace_processor {
+
+// Helper class to determine a proper tokenization. This class can be used as
+// a key of a std::map to automatically sort files before sending them in proper
+// order for tokenization.
+struct ArchiveEntry {
+  // File name. Used to break ties.
+  std::string name;
+  // Position. Used to break ties.
+  size_t index;
+  // Trace type. This is the main attribute traces are ordered by. Proto
+  // traces are always parsed first as they might contains clock sync
+  // data needed to correctly parse other traces.
+  TraceType trace_type;
+  // Comparator used to determine the order in which files in the ZIP will be
+  // read.
+  bool operator<(const ArchiveEntry& rhs) const;
+};
+}  // namespace perfetto::trace_processor
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ARCHIVE_ENTRY_H_
diff --git a/src/trace_processor/importers/gzip/gzip_trace_parser.cc b/src/trace_processor/importers/archive/gzip_trace_parser.cc
similarity index 93%
rename from src/trace_processor/importers/gzip/gzip_trace_parser.cc
rename to src/trace_processor/importers/archive/gzip_trace_parser.cc
index d133b2c..bc4074a 100644
--- a/src/trace_processor/importers/gzip/gzip_trace_parser.cc
+++ b/src/trace_processor/importers/archive/gzip_trace_parser.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
+#include "src/trace_processor/importers/archive/gzip_trace_parser.h"
 
 #include <cstdint>
 #include <cstring>
@@ -30,6 +30,8 @@
 #include "perfetto/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/importers/common/trace_file_tracker.h"
+#include "src/trace_processor/types/trace_processor_context.h"
 #include "src/trace_processor/util/gzip_utils.h"
 #include "src/trace_processor/util/status_macros.h"
 
@@ -59,7 +61,8 @@
 
   if (!inner_) {
     PERFETTO_CHECK(context_);
-    inner_.reset(new ForwardingTraceParser(context_));
+    inner_.reset(new ForwardingTraceParser(
+        context_, context_->trace_file_tracker->AddFile("")));
   }
 
   if (!first_chunk_parsed_) {
diff --git a/src/trace_processor/importers/gzip/gzip_trace_parser.h b/src/trace_processor/importers/archive/gzip_trace_parser.h
similarity index 88%
rename from src/trace_processor/importers/gzip/gzip_trace_parser.h
rename to src/trace_processor/importers/archive/gzip_trace_parser.h
index 4a565e6..17fdc4c 100644
--- a/src/trace_processor/importers/gzip/gzip_trace_parser.h
+++ b/src/trace_processor/importers/archive/gzip_trace_parser.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_GZIP_GZIP_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_GZIP_GZIP_TRACE_PARSER_H_
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_GZIP_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_GZIP_TRACE_PARSER_H_
 
 #include <cstddef>
 #include <cstdint>
@@ -55,4 +55,4 @@
 
 }  // namespace perfetto::trace_processor
 
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_GZIP_GZIP_TRACE_PARSER_H_
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_GZIP_TRACE_PARSER_H_
diff --git a/src/trace_processor/importers/archive/tar_trace_reader.cc b/src/trace_processor/importers/archive/tar_trace_reader.cc
new file mode 100644
index 0000000..d0cf11f
--- /dev/null
+++ b/src/trace_processor/importers/archive/tar_trace_reader.cc
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include "src/trace_processor/importers/archive/tar_trace_reader.h"
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/forwarding_trace_parser.h"
+#include "src/trace_processor/importers/archive/archive_entry.h"
+#include "src/trace_processor/importers/common/trace_file_tracker.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/status_macros.h"
+#include "src/trace_processor/util/trace_type.h"
+
+namespace perfetto::trace_processor {
+namespace {
+
+constexpr char kUstarMagic[] = {'u', 's', 't', 'a', 'r', '\0'};
+constexpr char kGnuMagic[] = {'u', 's', 't', 'a', 'r', ' ', ' ', '\0'};
+
+constexpr char TYPE_FLAG_REGULAR = '0';
+constexpr char TYPE_FLAG_AREGULAR = '\0';
+constexpr char TYPE_FLAG_GNU_LONG_NAME = 'L';
+
+template <size_t Size>
+std::optional<uint64_t> ExtractUint64(const char (&ptr)[Size]) {
+  static_assert(Size <= 64 / 3);
+  if (*ptr == 0) {
+    return std::nullopt;
+  }
+  uint64_t value = 0;
+  for (size_t i = 0; i < Size && ptr[i] != 0; ++i) {
+    if (ptr[i] > '7' || ptr[i] < '0') {
+      return std::nullopt;
+    }
+    value <<= 3;
+    value += static_cast<uint64_t>(ptr[i] - '0');
+  }
+  return value;
+}
+
+enum class TarType { kUnknown, kUstar, kGnu };
+
+struct alignas(1) Header {
+  char name[100];
+  char mode[8];
+  char uid[8];
+  char gid[8];
+  char size[12];
+  char mtime[12];
+  char checksum[8];
+  char type_flag[1];
+  char link_name[100];
+  union {
+    struct UstarMagic {
+      char magic[6];
+      char version[2];
+    } ustar;
+    char gnu[8];
+  } magic;
+  char user_name[32];
+  char group_name[32];
+  char dev_major[8];
+  char dev_minor[8];
+  char prefix[155];
+  char padding[12];
+
+  TarType GetTarFileType() const {
+    if (memcmp(magic.gnu, kGnuMagic, sizeof(kGnuMagic)) == 0) {
+      return TarType::kGnu;
+    }
+    if (memcmp(magic.ustar.magic, kUstarMagic, sizeof(kUstarMagic)) == 0) {
+      return TarType::kUstar;
+    }
+    return TarType::kUnknown;
+  }
+};
+
+constexpr size_t kHeaderSize = 512;
+static_assert(sizeof(Header) == kHeaderSize);
+
+bool IsAllZeros(const TraceBlobView& data) {
+  const uint8_t* start = data.data();
+  const uint8_t* end = data.data() + data.size();
+  return std::find_if(start, end, [](uint8_t v) { return v != 0; }) == end;
+}
+
+template <size_t Size>
+std::string ExtractString(const char (&start)[Size]) {
+  const char* end = start + Size;
+  end = std::find(start, end, 0);
+  return std::string(start, end);
+}
+
+}  // namespace
+
+TarTraceReader::TarTraceReader(TraceProcessorContext* context)
+    : context_(context) {}
+
+TarTraceReader::~TarTraceReader() = default;
+
+util::Status TarTraceReader::Parse(TraceBlobView blob) {
+  ParseResult result = ParseResult::kOk;
+  buffer_.PushBack(std::move(blob));
+  while (!buffer_.empty() && result == ParseResult::kOk) {
+    switch (state_) {
+      case State::kMetadata:
+      case State::kZeroMetadata: {
+        ASSIGN_OR_RETURN(result, ParseMetadata());
+        break;
+      }
+      case State::kContent: {
+        ASSIGN_OR_RETURN(result, ParseContent());
+        break;
+      }
+      case State::kDone:
+        // We are done, ignore any more data
+        buffer_.PopFrontUntil(buffer_.end_offset());
+    }
+  }
+  return base::OkStatus();
+}
+
+base::Status TarTraceReader::NotifyEndOfFile() {
+  if (state_ != State::kDone) {
+    return base::ErrStatus("Premature end of TAR file");
+  }
+
+  for (auto& file : ordered_files_) {
+    auto chunk_reader =
+        std::make_unique<ForwardingTraceParser>(context_, file.second.id);
+    auto& parser = *chunk_reader;
+    context_->chunk_readers.push_back(std::move(chunk_reader));
+
+    for (auto& data : file.second.data) {
+      RETURN_IF_ERROR(parser.Parse(std::move(data)));
+    }
+    RETURN_IF_ERROR(parser.NotifyEndOfFile());
+    // Make sure the ForwardingTraceParser determined the same trace type as we
+    // did.
+    PERFETTO_CHECK(parser.trace_type() == file.first.trace_type);
+  }
+
+  return base::OkStatus();
+}
+
+base::StatusOr<TarTraceReader::ParseResult> TarTraceReader::ParseMetadata() {
+  PERFETTO_CHECK(!metadata_.has_value());
+  auto blob = buffer_.SliceOff(buffer_.start_offset(), kHeaderSize);
+  if (!blob) {
+    return ParseResult::kNeedsMoreData;
+  }
+  buffer_.PopFrontBytes(kHeaderSize);
+  const Header& header = *reinterpret_cast<const Header*>(blob->data());
+
+  TarType type = header.GetTarFileType();
+
+  if (type == TarType::kUnknown) {
+    if (!IsAllZeros(*blob)) {
+      return base::ErrStatus("Invalid magic value");
+    }
+    // EOF is signaled by two consecutive zero headers.
+    if (state_ == State::kMetadata) {
+      // Fist time we see all zeros. NExt parser loop will enter ParseMetadata
+      // again and decide whether it is the real end or maybe a ral header
+      // comes.
+      state_ = State::kZeroMetadata;
+    } else {
+      // Previous header was zeros, thus we are done.
+      PERFETTO_CHECK(state_ == State::kZeroMetadata);
+      state_ = State::kDone;
+    }
+    return ParseResult::kOk;
+  }
+
+  if (type == TarType::kUstar && (header.magic.ustar.version[0] != '0' ||
+                                  header.magic.ustar.version[1] != '0')) {
+    return base::ErrStatus("Invalid version: %c%c",
+                           header.magic.ustar.version[0],
+                           header.magic.ustar.version[1]);
+  }
+
+  std::optional<uint64_t> size = ExtractUint64(header.size);
+  if (!size.has_value()) {
+    return base::ErrStatus("Failed to parse octal size field.");
+  }
+
+  metadata_.emplace();
+  metadata_->size = *size;
+  metadata_->type_flag = *header.type_flag;
+
+  if (long_name_) {
+    metadata_->name = std::move(*long_name_);
+    long_name_.reset();
+  } else {
+    metadata_->name =
+        ExtractString(header.prefix) + "/" + ExtractString(header.name);
+  }
+
+  switch (metadata_->type_flag) {
+    case TYPE_FLAG_REGULAR:
+    case TYPE_FLAG_AREGULAR:
+    case TYPE_FLAG_GNU_LONG_NAME:
+      state_ = State::kContent;
+      break;
+
+    default:
+      if (metadata_->size != 0) {
+        return base::ErrStatus("Unsupported file type: 0x%02x",
+                               metadata_->type_flag);
+      }
+      state_ = State::kMetadata;
+      break;
+  }
+
+  return ParseResult::kOk;
+}
+
+base::StatusOr<TarTraceReader::ParseResult> TarTraceReader::ParseContent() {
+  PERFETTO_CHECK(metadata_.has_value());
+
+  size_t data_and_padding_size = base::AlignUp(metadata_->size, kHeaderSize);
+  if (buffer_.avail() < data_and_padding_size) {
+    return ParseResult::kNeedsMoreData;
+  }
+
+  if (metadata_->type_flag == TYPE_FLAG_GNU_LONG_NAME) {
+    TraceBlobView data =
+        *buffer_.SliceOff(buffer_.start_offset(), metadata_->size);
+    long_name_ = std::string(reinterpret_cast<const char*>(data.data()),
+                             metadata_->size);
+  } else {
+    AddFile(*metadata_,
+            *buffer_.SliceOff(
+                buffer_.start_offset(),
+                std::min(static_cast<uint64_t>(512), metadata_->size)),
+            buffer_.MultiSliceOff(buffer_.start_offset(), metadata_->size));
+  }
+
+  buffer_.PopFrontBytes(data_and_padding_size);
+
+  metadata_.reset();
+  state_ = State::kMetadata;
+  return ParseResult::kOk;
+}
+
+void TarTraceReader::AddFile(const Metadata& metadata,
+                             TraceBlobView header,
+                             std::vector<TraceBlobView> data) {
+  auto file_id = context_->trace_file_tracker->AddFile(metadata.name);
+  context_->trace_file_tracker->SetSize(file_id, metadata.size);
+  ordered_files_.emplace(
+      ArchiveEntry{metadata.name, ordered_files_.size(),
+                   GuessTraceType(header.data(), header.size())},
+      File{file_id, std::move(data)});
+}
+
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/archive/tar_trace_reader.h b/src/trace_processor/importers/archive/tar_trace_reader.h
new file mode 100644
index 0000000..6760774
--- /dev/null
+++ b/src/trace_processor/importers/archive/tar_trace_reader.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_TAR_TRACE_READER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_TAR_TRACE_READER_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <map>
+
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/importers/archive/archive_entry.h"
+#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
+#include "src/trace_processor/util/trace_blob_view_reader.h"
+
+namespace perfetto::trace_processor {
+
+class TraceProcessorContext;
+
+class TarTraceReader : public ChunkedTraceReader {
+ public:
+  explicit TarTraceReader(TraceProcessorContext*);
+  ~TarTraceReader() override;
+
+  // ChunkedTraceReader implementation
+  base::Status Parse(TraceBlobView) override;
+  base::Status NotifyEndOfFile() override;
+
+ private:
+  struct Metadata {
+    std::string name;
+    uint64_t size;
+    char type_flag;
+  };
+  enum class ParseResult {
+    kOk,
+    kNeedsMoreData,
+  };
+
+  struct File {
+    tables::TraceFileTable::Id id;
+    std::vector<TraceBlobView> data;
+  };
+
+  enum class State { kMetadata, kContent, kZeroMetadata, kDone };
+
+  base::StatusOr<ParseResult> ParseMetadata();
+  base::StatusOr<ParseResult> ParseContent();
+  base::StatusOr<ParseResult> ParseLongName();
+  base::StatusOr<ParseResult> ParsePadding();
+
+  void AddFile(const Metadata& metadata,
+               TraceBlobView header,
+               std::vector<TraceBlobView> data);
+
+  TraceProcessorContext* const context_;
+  State state_{State::kMetadata};
+  util::TraceBlobViewReader buffer_;
+  std::optional<Metadata> metadata_;
+  std::optional<std::string> long_name_;
+  std::map<ArchiveEntry, File> ordered_files_;
+};
+
+}  // namespace perfetto::trace_processor
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_TAR_TRACE_READER_H_
diff --git a/src/trace_processor/importers/archive/zip_trace_reader.cc b/src/trace_processor/importers/archive/zip_trace_reader.cc
new file mode 100644
index 0000000..6077d00
--- /dev/null
+++ b/src/trace_processor/importers/archive/zip_trace_reader.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include "src/trace_processor/importers/archive/zip_trace_reader.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/trace_blob.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/forwarding_trace_parser.h"
+#include "src/trace_processor/importers/android_bugreport/android_bugreport_reader.h"
+#include "src/trace_processor/importers/archive/archive_entry.h"
+#include "src/trace_processor/importers/common/trace_file_tracker.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/status_macros.h"
+#include "src/trace_processor/util/trace_type.h"
+#include "src/trace_processor/util/zip_reader.h"
+
+namespace perfetto::trace_processor {
+
+ZipTraceReader::ZipTraceReader(TraceProcessorContext* context)
+    : context_(context) {}
+ZipTraceReader::~ZipTraceReader() = default;
+
+base::Status ZipTraceReader::Parse(TraceBlobView blob) {
+  return zip_reader_.Parse(std::move(blob));
+}
+
+base::Status ZipTraceReader::NotifyEndOfFile() {
+  std::vector<util::ZipFile> files = zip_reader_.TakeFiles();
+
+  // Android bug reports are ZIP files and its files do not get handled
+  // separately.
+  if (AndroidBugreportReader::IsAndroidBugReport(files)) {
+    return AndroidBugreportReader::Parse(context_, std::move(files));
+  }
+
+  // TODO(carlscab): There is a lot of unnecessary copying going on here.
+  // ZipTraceReader can directly parse the ZIP file and given that we know the
+  // decompressed size we could directly decompress into TraceBlob chunks and
+  // send them to the tokenizer.
+  std::vector<uint8_t> buffer;
+  std::map<ArchiveEntry, File> ordered_files;
+  for (size_t i = 0; i < files.size(); ++i) {
+    util::ZipFile& zip_file = files[i];
+    auto id = context_->trace_file_tracker->AddFile(zip_file.name());
+    context_->trace_file_tracker->SetSize(id, zip_file.compressed_size());
+    RETURN_IF_ERROR(files[i].Decompress(&buffer));
+    TraceBlobView data(TraceBlob::CopyFrom(buffer.data(), buffer.size()));
+    ArchiveEntry entry{zip_file.name(), i,
+                       GuessTraceType(data.data(), data.size())};
+    ordered_files.emplace(entry, File{id, std::move(data)});
+  }
+
+  for (auto& file : ordered_files) {
+    auto chunk_reader =
+        std::make_unique<ForwardingTraceParser>(context_, file.second.id);
+    auto& parser = *chunk_reader;
+    context_->chunk_readers.push_back(std::move(chunk_reader));
+
+    RETURN_IF_ERROR(parser.Parse(std::move(file.second.data)));
+    RETURN_IF_ERROR(parser.NotifyEndOfFile());
+    // Make sure the ForwardingTraceParser determined the same trace type as we
+    // did.
+    PERFETTO_CHECK(parser.trace_type() == file.first.trace_type);
+  }
+
+  return base::OkStatus();
+}
+
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/archive/zip_trace_reader.h b/src/trace_processor/importers/archive/zip_trace_reader.h
new file mode 100644
index 0000000..d36fd5c
--- /dev/null
+++ b/src/trace_processor/importers/archive/zip_trace_reader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ZIP_TRACE_READER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ZIP_TRACE_READER_H_
+
+#include <cstddef>
+#include <map>
+
+#include "perfetto/base/status.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/importers/archive/archive_entry.h"
+#include "src/trace_processor/importers/common/chunked_trace_reader.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
+#include "src/trace_processor/util/zip_reader.h"
+
+namespace perfetto::trace_processor {
+
+class ForwardingTraceParser;
+class TraceProcessorContext;
+
+// Forwards files contained in a ZIP to the appropiate ChunkedTraceReader. It is
+// guaranteed that proto traces will be parsed first.
+class ZipTraceReader : public ChunkedTraceReader {
+ public:
+  explicit ZipTraceReader(TraceProcessorContext* context);
+  ~ZipTraceReader() override;
+
+  // ChunkedTraceReader implementation
+  base::Status Parse(TraceBlobView) override;
+  base::Status NotifyEndOfFile() override;
+
+ private:
+  struct File {
+    tables::TraceFileTable::Id id;
+    TraceBlobView data;
+  };
+  TraceProcessorContext* const context_;
+  util::ZipReader zip_reader_;
+};
+
+}  // namespace perfetto::trace_processor
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ARCHIVE_ZIP_TRACE_READER_H_
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index a65d044..47c7521 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -56,8 +56,6 @@
     "sched_event_state.h",
     "sched_event_tracker.cc",
     "sched_event_tracker.h",
-    "scoped_active_trace_file.cc",
-    "scoped_active_trace_file.h",
     "slice_tracker.cc",
     "slice_tracker.h",
     "slice_translation_table.cc",
diff --git a/src/trace_processor/importers/common/scoped_active_trace_file.cc b/src/trace_processor/importers/common/scoped_active_trace_file.cc
deleted file mode 100644
index 7249261..0000000
--- a/src/trace_processor/importers/common/scoped_active_trace_file.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#include "src/trace_processor/importers/common/scoped_active_trace_file.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <string>
-
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/trace_file_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/metadata_tables_py.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-
-namespace perfetto::trace_processor {
-ScopedActiveTraceFile::~ScopedActiveTraceFile() {
-  if (is_valid_) {
-    context_->trace_file_tracker->EndFile(row_);
-  }
-}
-
-void ScopedActiveTraceFile::SetName(const std::string& name) {
-  row_.set_name(context_->storage->InternString(base::StringView(name)));
-}
-
-void ScopedActiveTraceFile::SetTraceType(TraceType type) {
-  row_.set_trace_type(context_->storage->InternString(TraceTypeToString(type)));
-}
-
-void ScopedActiveTraceFile::SetSize(size_t size) {
-  row_.set_size(static_cast<int64_t>(size));
-}
-
-void ScopedActiveTraceFile::AddSize(size_t size) {
-  row_.set_size(static_cast<int64_t>(size) + row_.size());
-}
-
-}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/scoped_active_trace_file.h b/src/trace_processor/importers/common/scoped_active_trace_file.h
deleted file mode 100644
index 0006fcf..0000000
--- a/src/trace_processor/importers/common/scoped_active_trace_file.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_
-
-#include <string>
-
-#include "src/trace_processor/tables/metadata_tables_py.h"
-#include "src/trace_processor/util/trace_type.h"
-
-namespace perfetto::trace_processor {
-
-class TraceProcessorContext;
-
-// RAII like object that represents a file currently being parsed. When
-// instances of this object go out of scope they will notify the
-// TraceFileTracker that we are done parsing the file.
-// This class also acts a handler for setting file related properties.
-class ScopedActiveTraceFile {
- public:
-  ~ScopedActiveTraceFile();
-
-  ScopedActiveTraceFile(const ScopedActiveTraceFile&) = delete;
-  ScopedActiveTraceFile& operator=(const ScopedActiveTraceFile&) = delete;
-
-  ScopedActiveTraceFile(ScopedActiveTraceFile&& o)
-      : context_(o.context_), row_(o.row_), is_valid_(o.is_valid_) {
-    o.is_valid_ = false;
-  }
-
-  ScopedActiveTraceFile& operator=(ScopedActiveTraceFile&& o) {
-    context_ = o.context_;
-    row_ = o.row_;
-    is_valid_ = o.is_valid_;
-    o.is_valid_ = false;
-    return *this;
-  }
-
-  void SetTraceType(TraceType type);
-
-  // For streamed files this method can be called for each chunk to update the
-  // file size incrementally.
-  void AddSize(size_t delta);
-
- private:
-  friend class TraceFileTracker;
-  ScopedActiveTraceFile(TraceProcessorContext* context,
-                        tables::TraceFileTable::RowReference row)
-      : context_(context), row_(row), is_valid_(true) {}
-
-  // Sets the file name. If this method is not called (sometimes we do not know
-  // the file name, e.g. streaming data) the name is set to null.
-  void SetName(const std::string& name);
-  void SetSize(size_t size);
-
-  TraceProcessorContext* context_;
-  tables::TraceFileTable::RowReference row_;
-  bool is_valid_;
-};
-
-}  // namespace perfetto::trace_processor
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_
diff --git a/src/trace_processor/importers/common/trace_file_tracker.cc b/src/trace_processor/importers/common/trace_file_tracker.cc
index e51371a..2bf02b7 100644
--- a/src/trace_processor/importers/common/trace_file_tracker.cc
+++ b/src/trace_processor/importers/common/trace_file_tracker.cc
@@ -17,11 +17,14 @@
 #include "src/trace_processor/importers/common/trace_file_tracker.h"
 
 #include <cstddef>
+#include <cstdint>
+#include <optional>
 #include <string>
 #include <vector>
 
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_view.h"
 #include "src/trace_processor/importers/common/metadata_tracker.h"
-#include "src/trace_processor/storage/metadata.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/tables/metadata_tables_py.h"
 #include "src/trace_processor/types/trace_processor_context.h"
@@ -29,46 +32,49 @@
 
 namespace perfetto::trace_processor {
 
-ScopedActiveTraceFile TraceFileTracker::StartNewFile() {
-  tables::TraceFileTable::Row row;
-  if (!ancestors_.empty()) {
-    row.parent_id = ancestors_.back();
-  }
-
-  row.size = 0;
-  row.trace_type =
-      context_->storage->InternString(TraceTypeToString(kUnknownTraceType));
-
-  auto ref =
-      context_->storage->mutable_trace_file_table()->Insert(row).row_reference;
-
-  ancestors_.push_back(ref.id());
-  return ScopedActiveTraceFile(context_, std::move(ref));
+tables::TraceFileTable::Id TraceFileTracker::AddFile(const std::string& name) {
+  return AddFileImpl(context_->storage->InternString(base::StringView(name)));
 }
 
-ScopedActiveTraceFile TraceFileTracker::StartNewFile(const std::string& name,
-                                                     TraceType type,
-                                                     size_t size) {
-  auto file = StartNewFile();
-  file.SetName(name);
-  file.SetTraceType(type);
-  file.SetSize(size);
-  return file;
+tables::TraceFileTable::Id TraceFileTracker::AddFileImpl(StringId name) {
+  std::optional<tables::TraceFileTable::Id> parent =
+      parsing_stack_.empty() ? std::nullopt
+                             : std::make_optional(parsing_stack_.back());
+  return context_->storage->mutable_trace_file_table()
+      ->Insert({parent, name, 0,
+                context_->storage->InternString(
+                    TraceTypeToString(kUnknownTraceType)),
+                std::nullopt})
+      .id;
 }
 
-void TraceFileTracker::EndFile(
-    const tables::TraceFileTable::ConstRowReference& row) {
-  PERFETTO_CHECK(!ancestors_.empty());
-  PERFETTO_CHECK(ancestors_.back() == row.id());
+void TraceFileTracker::SetSize(tables::TraceFileTable::Id id, uint64_t size) {
+  auto row = *context_->storage->mutable_trace_file_table()->FindById(id);
+  row.set_size(static_cast<int64_t>(size));
+}
+
+void TraceFileTracker::StartParsing(tables::TraceFileTable::Id id,
+                                    TraceType trace_type) {
+  parsing_stack_.push_back(id);
+  auto row = *context_->storage->mutable_trace_file_table()->FindById(id);
+  row.set_trace_type(
+      context_->storage->InternString(TraceTypeToString(trace_type)));
+  row.set_processing_order(static_cast<int64_t>(processing_order_++));
+}
+
+void TraceFileTracker::DoneParsing(tables::TraceFileTable::Id id, size_t size) {
+  PERFETTO_CHECK(!parsing_stack_.empty() && parsing_stack_.back() == id);
+  parsing_stack_.pop_back();
+  auto row = *context_->storage->mutable_trace_file_table()->FindById(id);
+  row.set_size(static_cast<int64_t>(size));
 
   // First file (root)
-  if (row.id().value == 0) {
+  if (id.value == 0) {
     context_->metadata_tracker->SetMetadata(metadata::trace_size_bytes,
                                             Variadic::Integer(row.size()));
     context_->metadata_tracker->SetMetadata(metadata::trace_type,
                                             Variadic::String(row.trace_type()));
   }
-  ancestors_.pop_back();
 }
 
 }  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/trace_file_tracker.h b/src/trace_processor/importers/common/trace_file_tracker.h
index 0e2f5f9..4c6be5f 100644
--- a/src/trace_processor/importers/common/trace_file_tracker.h
+++ b/src/trace_processor/importers/common/trace_file_tracker.h
@@ -20,7 +20,7 @@
 #include <string>
 #include <vector>
 
-#include "src/trace_processor/importers/common/scoped_active_trace_file.h"
+#include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/tables/metadata_tables_py.h"
 #include "src/trace_processor/util/trace_type.h"
 
@@ -36,24 +36,18 @@
   explicit TraceFileTracker(TraceProcessorContext* context)
       : context_(context) {}
 
-  // Notifies the start of a new file that we are about to parse. It returns a
-  // RAII like object that will notify the end of processing when it goes out of
-  // scope.
-  // NOTE: Files must be ended in reverse order of being started.
-  ScopedActiveTraceFile StartNewFile();
-
-  // Convenience version of the above that should be used when all the file
-  // properties are known upfront.
-  ScopedActiveTraceFile StartNewFile(const std::string& name,
-                                     TraceType type,
-                                     size_t size);
+  tables::TraceFileTable::Id AddFile(const std::string& name);
+  tables::TraceFileTable::Id AddFile() { return AddFileImpl(kNullStringId); }
+  void SetSize(tables::TraceFileTable::Id id, uint64_t size);
+  void StartParsing(tables::TraceFileTable::Id id, TraceType trace_type);
+  void DoneParsing(tables::TraceFileTable::Id id, size_t size);
 
  private:
-  void EndFile(const tables::TraceFileTable::ConstRowReference& row);
+  tables::TraceFileTable::Id AddFileImpl(StringId name);
 
-  friend class ScopedActiveTraceFile;
   TraceProcessorContext* const context_;
-  std::vector<tables::TraceFileTable::Id> ancestors_;
+  size_t processing_order_ = 0;
+  std::vector<tables::TraceFileTable::Id> parsing_stack_;
 };
 
 }  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/gzip/BUILD.gn b/src/trace_processor/importers/gzip/BUILD.gn
deleted file mode 100644
index d2fad21..0000000
--- a/src/trace_processor/importers/gzip/BUILD.gn
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2022 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.
-
-source_set("full") {
-  sources = [
-    "gzip_trace_parser.cc",
-    "gzip_trace_parser.h",
-  ]
-  deps = [
-    "../..:storage_minimal",
-    "../../../../gn:default_deps",
-    "../../../base",
-    "../../util",
-    "../../util:gzip",
-    "../common",
-  ]
-}
diff --git a/src/trace_processor/importers/zip/zip_trace_reader.cc b/src/trace_processor/importers/zip/zip_trace_reader.cc
deleted file mode 100644
index 732559d..0000000
--- a/src/trace_processor/importers/zip/zip_trace_reader.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#include "src/trace_processor/importers/zip/zip_trace_reader.h"
-
-#include <algorithm>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/status.h"
-#include "perfetto/ext/base/status_or.h"
-#include "perfetto/trace_processor/trace_blob.h"
-#include "perfetto/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/importers/android_bugreport/android_bugreport_reader.h"
-#include "src/trace_processor/importers/common/trace_file_tracker.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/status_macros.h"
-#include "src/trace_processor/util/trace_type.h"
-#include "src/trace_processor/util/zip_reader.h"
-
-namespace perfetto::trace_processor {
-
-ZipTraceReader::ZipTraceReader(TraceProcessorContext* context)
-    : context_(context) {}
-ZipTraceReader::~ZipTraceReader() = default;
-
-bool ZipTraceReader::Entry::operator<(const Entry& rhs) const {
-  // Traces with symbols should be the last ones to be read.
-  // TODO(carlscab): Proto traces with just ModuleSymbols packets should be an
-  // exception. We actually need those are the very end (once whe have all the
-  // Frames). Alternatively we could build a map address -> symbol during
-  // tokenization and use this during parsing to resolve symbols.
-  if (trace_type == kSymbolsTraceType) {
-    return false;
-  }
-  if (rhs.trace_type == kSymbolsTraceType) {
-    return true;
-  }
-
-  // Proto traces should always parsed first as they might contains clock sync
-  // data needed to correctly parse other traces.
-  if (rhs.trace_type == TraceType::kProtoTraceType) {
-    return false;
-  }
-  if (trace_type == TraceType::kProtoTraceType) {
-    return true;
-  }
-
-  if (rhs.trace_type == TraceType::kGzipTraceType) {
-    return false;
-  }
-  if (trace_type == TraceType::kGzipTraceType) {
-    return true;
-  }
-
-  return std::tie(name, index) < std::tie(rhs.name, rhs.index);
-}
-
-base::Status ZipTraceReader::Parse(TraceBlobView blob) {
-  return zip_reader_.Parse(std::move(blob));
-}
-
-base::Status ZipTraceReader::NotifyEndOfFile() {
-  std::vector<util::ZipFile> files = zip_reader_.TakeFiles();
-
-  // Android bug reports are ZIP files and its files do not get handled
-  // separately.
-  if (AndroidBugreportReader::IsAndroidBugReport(files)) {
-    return AndroidBugreportReader::Parse(context_, std::move(files));
-  }
-
-  ASSIGN_OR_RETURN(std::vector<Entry> entries,
-                   ExtractEntries(std::move(files)));
-  std::sort(entries.begin(), entries.end());
-
-  for (Entry& e : entries) {
-    ScopedActiveTraceFile trace_file =
-        context_->trace_file_tracker->StartNewFile(e.name, e.trace_type,
-                                                   e.uncompressed_data.size());
-
-    auto chunk_reader = std::make_unique<ForwardingTraceParser>(context_);
-    auto& parser = *chunk_reader;
-    context_->chunk_readers.push_back(std::move(chunk_reader));
-
-    RETURN_IF_ERROR(parser.Parse(std::move(e.uncompressed_data)));
-    RETURN_IF_ERROR(parser.NotifyEndOfFile());
-
-    // Make sure the ForwardingTraceParser determined the same trace type as we
-    // did.
-    PERFETTO_CHECK(parser.trace_type() == e.trace_type);
-  }
-  return base::OkStatus();
-}
-
-base::StatusOr<std::vector<ZipTraceReader::Entry>>
-ZipTraceReader::ExtractEntries(std::vector<util::ZipFile> files) {
-  // TODO(carlsacab): There is a lot of unnecessary copying going on here.
-  // ZipTraceReader can directly parse the ZIP file and given that we know the
-  // decompressed size we could directly decompress into TraceBlob chunks and
-  // send them to the tokenizer.
-  std::vector<Entry> entries;
-  std::vector<uint8_t> buffer;
-  for (size_t i = 0; i < files.size(); ++i) {
-    const util::ZipFile& zip_file = files[i];
-    Entry entry;
-    entry.name = zip_file.name();
-    entry.index = i;
-    RETURN_IF_ERROR(files[i].Decompress(&buffer));
-    entry.uncompressed_data =
-        TraceBlobView(TraceBlob::CopyFrom(buffer.data(), buffer.size()));
-    entry.trace_type = GuessTraceType(entry.uncompressed_data.data(),
-                                      entry.uncompressed_data.size());
-    entries.push_back(std::move(entry));
-  }
-  return std::move(entries);
-}
-
-}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/zip/zip_trace_reader.h b/src/trace_processor/importers/zip/zip_trace_reader.h
deleted file mode 100644
index b6620ae..0000000
--- a/src/trace_processor/importers/zip/zip_trace_reader.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ZIP_ZIP_TRACE_READER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_ZIP_ZIP_TRACE_READER_H_
-
-#include <cstddef>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/status.h"
-#include "perfetto/ext/base/status_or.h"
-#include "perfetto/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/util/trace_type.h"
-#include "src/trace_processor/util/zip_reader.h"
-
-namespace perfetto::trace_processor {
-
-class ForwardingTraceParser;
-class TraceProcessorContext;
-
-// Forwards files contained in a ZIP to the appropiate ChunkedTraceReader. It is
-// guaranteed that proto traces will be parsed first.
-class ZipTraceReader : public ChunkedTraceReader {
- public:
-  explicit ZipTraceReader(TraceProcessorContext* context);
-  ~ZipTraceReader() override;
-
-  // ChunkedTraceReader implementation
-  base::Status Parse(TraceBlobView) override;
-  base::Status NotifyEndOfFile() override;
-
- private:
-  // Represents a file in the ZIP file. Used to sort them before sending the
-  // files one by one to a `ForwardingTraceParser` instance.
-  struct Entry {
-    // File name. Used to break ties.
-    std::string name;
-    // Position in the zip file. Used to break ties.
-    size_t index;
-    // Trace type. This is the main attribute traces are ordered by. Proto
-    // traces are always parsed first as they might contains clock sync
-    // data needed to correctly parse other traces.
-    TraceType trace_type;
-    TraceBlobView uncompressed_data;
-    // Comparator used to determine the order in which files in the ZIP will be
-    // read.
-    bool operator<(const Entry& rhs) const;
-  };
-
-  static base::StatusOr<std::vector<Entry>> ExtractEntries(
-      std::vector<util::ZipFile> files);
-  base::Status ParseEntry(Entry entry);
-
-  TraceProcessorContext* const context_;
-  util::ZipReader zip_reader_;
-};
-
-}  // namespace perfetto::trace_processor
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ZIP_ZIP_TRACE_READER_H_
diff --git a/src/trace_processor/read_trace.cc b/src/trace_processor/read_trace.cc
index 91e784a..e9f8f8c 100644
--- a/src/trace_processor/read_trace.cc
+++ b/src/trace_processor/read_trace.cc
@@ -26,8 +26,8 @@
 #include "perfetto/protozero/proto_utils.h"
 #include "perfetto/trace_processor/trace_blob_view.h"
 #include "perfetto/trace_processor/trace_processor.h"
+#include "src/trace_processor/importers/archive/gzip_trace_parser.h"
 #include "src/trace_processor/importers/common/chunked_trace_reader.h"
-#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
 #include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/read_trace_internal.h"
 #include "src/trace_processor/util/gzip_utils.h"
diff --git a/src/trace_processor/read_trace_internal.cc b/src/trace_processor/read_trace_internal.cc
index 3b537cd..f2b1a67 100644
--- a/src/trace_processor/read_trace_internal.cc
+++ b/src/trace_processor/read_trace_internal.cc
@@ -27,7 +27,6 @@
 #include "perfetto/trace_processor/trace_blob.h"
 #include "perfetto/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
 #include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/util/gzip_utils.h"
 #include "src/trace_processor/util/status_macros.h"
diff --git a/src/trace_processor/tables/metadata_tables.py b/src/trace_processor/tables/metadata_tables.py
index cb70e2a..10da09b 100644
--- a/src/trace_processor/tables/metadata_tables.py
+++ b/src/trace_processor/tables/metadata_tables.py
@@ -460,6 +460,7 @@
         C('name', CppOptional(CppString())),
         C('size', CppInt64()),
         C('trace_type', CppString()),
+        C('processing_order', CppOptional(CppInt64())),
     ],
     wrapping_sql_view=WrappingSqlView('trace_file'),
     tabledoc=TableDoc(
@@ -481,6 +482,8 @@
                 '''Size in bytes''',
             'trace_type':
                 '''Trace type''',
+            'processing_order':
+                '''In which order where the files were processed.''',
         }))
 
 # Keep this list sorted.
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index a8f1ffe..54436d3 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -46,6 +46,9 @@
 #include "perfetto/trace_processor/trace_processor.h"
 #include "src/trace_processor/importers/android_bugreport/android_log_event_parser_impl.h"
 #include "src/trace_processor/importers/android_bugreport/android_log_reader.h"
+#include "src/trace_processor/importers/archive/gzip_trace_parser.h"
+#include "src/trace_processor/importers/archive/tar_trace_reader.h"
+#include "src/trace_processor/importers/archive/zip_trace_reader.h"
 #include "src/trace_processor/importers/art_method/art_method_parser_impl.h"
 #include "src/trace_processor/importers/art_method/art_method_tokenizer.h"
 #include "src/trace_processor/importers/common/clock_tracker.h"
@@ -55,7 +58,6 @@
 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
 #include "src/trace_processor/importers/gecko/gecko_trace_parser_impl.h"
 #include "src/trace_processor/importers/gecko/gecko_trace_tokenizer.h"
-#include "src/trace_processor/importers/gzip/gzip_trace_parser.h"
 #include "src/trace_processor/importers/json/json_trace_parser_impl.h"
 #include "src/trace_processor/importers/json/json_trace_tokenizer.h"
 #include "src/trace_processor/importers/json/json_utils.h"
@@ -68,7 +70,6 @@
 #include "src/trace_processor/importers/proto/additional_modules.h"
 #include "src/trace_processor/importers/proto/content_analyzer.h"
 #include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
-#include "src/trace_processor/importers/zip/zip_trace_reader.h"
 #include "src/trace_processor/iterator_impl.h"
 #include "src/trace_processor/metrics/all_chrome_metrics.descriptor.h"
 #include "src/trace_processor/metrics/all_webview_metrics.descriptor.h"
@@ -457,6 +458,8 @@
   context_.perf_text_parser =
       std::make_unique<perf_text_importer::PerfTextTraceParserImpl>(&context_);
 
+  context_.reader_registry->RegisterTraceReader<TarTraceReader>(kTarTraceType);
+
   if (context_.config.analyze_trace_proto_content) {
     context_.content_analyzer =
         std::make_unique<ProtoContentAnalyzer>(&context_);
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index e93e0fe..1fe24c0 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <utility>
 
 #include "perfetto/base/logging.h"
@@ -76,8 +77,8 @@
     return base::ErrStatus(
         "Failed unrecoverably while parsing in a previous Parse call");
   if (!parser_) {
-    active_file_ = context_.trace_file_tracker->StartNewFile();
-    auto parser = std::make_unique<ForwardingTraceParser>(&context_);
+    auto parser = std::make_unique<ForwardingTraceParser>(
+        &context_, context_.trace_file_tracker->AddFile());
     parser_ = parser.get();
     context_.chunk_readers.push_back(std::move(parser));
   }
@@ -97,7 +98,6 @@
                                            Variadic::String(id_for_uuid));
   }
 
-  active_file_->AddSize(blob.size());
   base::Status status = parser_->Parse(std::move(blob));
   unrecoverable_parse_error_ |= !status.ok();
   return status;
@@ -121,9 +121,6 @@
   }
   Flush();
   RETURN_IF_ERROR(parser_->NotifyEndOfFile());
-  PERFETTO_CHECK(active_file_.has_value());
-  active_file_->SetTraceType(parser_->trace_type());
-  active_file_.reset();
   // NotifyEndOfFile might have pushed packets to the sorter.
   Flush();
   for (std::unique_ptr<ProtoImporterModule>& module : context_.modules) {
@@ -144,8 +141,6 @@
 }
 
 void TraceProcessorStorageImpl::DestroyContext() {
-  // End any active files. Eg. when NotifyEndOfFile is not called.
-  active_file_.reset();
   TraceProcessorContext context;
   context.storage = std::move(context_.storage);
 
diff --git a/src/trace_processor/trace_processor_storage_impl.h b/src/trace_processor/trace_processor_storage_impl.h
index bab8961..9198d2f 100644
--- a/src/trace_processor/trace_processor_storage_impl.h
+++ b/src/trace_processor/trace_processor_storage_impl.h
@@ -17,9 +17,6 @@
 #ifndef SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_
 #define SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_
 
-#include <memory>
-#include <optional>
-
 #include "perfetto/ext/base/hash.h"
 #include "perfetto/trace_processor/basic_types.h"
 #include "perfetto/trace_processor/status.h"
@@ -51,7 +48,6 @@
   bool unrecoverable_parse_error_ = false;
   size_t hash_input_size_remaining_ = 4096;
   ForwardingTraceParser* parser_ = nullptr;
-  std::optional<ScopedActiveTraceFile> active_file_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/trace_reader_registry.cc b/src/trace_processor/trace_reader_registry.cc
index 6301ced..fe108c8 100644
--- a/src/trace_processor/trace_reader_registry.cc
+++ b/src/trace_processor/trace_reader_registry.cc
@@ -54,6 +54,7 @@
     case kGeckoTraceType:
     case kArtMethodTraceType:
     case kPerfTextTraceType:
+    case kTarTraceType:
       return false;
   }
   PERFETTO_FATAL("For GCC");
diff --git a/src/trace_processor/util/trace_blob_view_reader.cc b/src/trace_processor/util/trace_blob_view_reader.cc
index 78a1e1f..acdc898 100644
--- a/src/trace_processor/util/trace_blob_view_reader.cc
+++ b/src/trace_processor/util/trace_blob_view_reader.cc
@@ -21,8 +21,10 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
+#include <iterator>
 #include <optional>
 #include <utility>
+#include <vector>
 
 #include "perfetto/base/logging.h"
 #include "perfetto/public/compiler.h"
@@ -59,12 +61,13 @@
   return target_offset == end_offset_;
 }
 
-std::optional<TraceBlobView> TraceBlobViewReader::SliceOff(
-    size_t offset,
-    size_t length) const {
-  // If the length is zero, then a zero-sized blob view is always approrpriate.
+template <typename Visitor>
+auto TraceBlobViewReader::SliceOffImpl(const size_t offset,
+                                       const size_t length,
+                                       Visitor& visitor) const {
+  // If the length is zero, then a zero-sized blob view is always appropiate.
   if (PERFETTO_UNLIKELY(length == 0)) {
-    return TraceBlobView();
+    return visitor.OneSlice(TraceBlobView());
   }
 
   PERFETTO_DCHECK(offset >= start_offset());
@@ -76,47 +79,105 @@
       !data_.empty() &&
       offset + length <= data_.front().start_offset + data_.front().data.size();
   if (PERFETTO_LIKELY(is_fast_path)) {
-    return data_.front().data.slice_off(offset - data_.front().start_offset,
-                                        length);
+    return visitor.OneSlice(data_.front().data.slice_off(
+        offset - data_.front().start_offset, length));
   }
 
   // If we don't have any TBVs or the end of the slice does not fit, then we
   // cannot possibly return a full slice.
   if (PERFETTO_UNLIKELY(data_.empty() || offset + length > end_offset_)) {
-    return std::nullopt;
+    return visitor.NoData();
   }
 
   // Find the first block finishes *after* start_offset i.e. there is at least
   // one byte in that block which will end up in the slice. We know this *must*
   // exist because of the above check.
-  auto rit = std::upper_bound(
+  auto it = std::upper_bound(
       data_.begin(), data_.end(), offset, [](size_t offset, const Entry& rhs) {
         return offset < rhs.start_offset + rhs.data.size();
       });
-  PERFETTO_CHECK(rit != data_.end());
+  PERFETTO_CHECK(it != data_.end());
 
   // If the slice fits entirely in the block we found, then just slice that
   // block avoiding any copies.
-  size_t rel_off = offset - rit->start_offset;
-  if (rel_off + length <= rit->data.size()) {
-    return rit->data.slice_off(rel_off, length);
+  size_t rel_off = offset - it->start_offset;
+  if (rel_off + length <= it->data.size()) {
+    return visitor.OneSlice(it->data.slice_off(rel_off, length));
   }
 
-  // Otherwise, allocate some memory and make a copy.
-  auto buffer = TraceBlob::Allocate(length);
-  uint8_t* ptr = buffer.data();
-  uint8_t* end = buffer.data() + buffer.size();
+  auto res = visitor.StartMultiSlice(length);
 
-  // Copy all bytes in this block which overlap with the slice.
-  memcpy(ptr, rit->data.data() + rel_off, rit->data.length() - rel_off);
-  ptr += rit->data.length() - rel_off;
+  size_t res_offset = 0;
+  size_t left = length;
 
-  for (auto it = rit + 1; ptr != end; ++it) {
-    auto len = std::min(static_cast<size_t>(end - ptr), it->data.size());
-    memcpy(ptr, it->data.data(), len);
-    ptr += len;
+  size_t size = it->data.length() - rel_off;
+  visitor.AddSlice(res, res_offset, it->data.slice_off(rel_off, size));
+  left -= size;
+  res_offset += size;
+
+  for (++it; left != 0; ++it) {
+    size = std::min(left, it->data.size());
+    visitor.AddSlice(res, res_offset, it->data.slice_off(0, size));
+    left -= size;
+    res_offset += size;
   }
-  return TraceBlobView(std::move(buffer));
+
+  return visitor.Finalize(std::move(res));
+}
+
+std::optional<TraceBlobView> TraceBlobViewReader::SliceOff(
+    size_t offset,
+    size_t length) const {
+  struct Visitor {
+    std::optional<TraceBlobView> NoData() { return std::nullopt; }
+
+    std::optional<TraceBlobView> OneSlice(TraceBlobView tbv) {
+      return std::move(tbv);
+    }
+
+    TraceBlob StartMultiSlice(size_t length) {
+      return TraceBlob::Allocate(length);
+    }
+
+    void AddSlice(TraceBlob& blob, size_t offset, TraceBlobView tbv) {
+      memcpy(blob.data() + offset, tbv.data(), tbv.size());
+    }
+
+    std::optional<TraceBlobView> Finalize(TraceBlob blob) {
+      return TraceBlobView(std::move(blob));
+    }
+
+  } visitor;
+
+  return SliceOffImpl(offset, length, visitor);
+}
+
+std::vector<TraceBlobView> TraceBlobViewReader::MultiSliceOff(
+    size_t offset,
+    size_t length) const {
+  struct Visitor {
+    std::vector<TraceBlobView> NoData() { return {}; }
+
+    std::vector<TraceBlobView> OneSlice(TraceBlobView tbv) {
+      std::vector<TraceBlobView> res;
+      res.reserve(1);
+      res.push_back(std::move(tbv));
+      return res;
+    }
+
+    std::vector<TraceBlobView> StartMultiSlice(size_t) { return {}; }
+
+    void AddSlice(std::vector<TraceBlobView>& vec, size_t, TraceBlobView tbv) {
+      vec.push_back(std::move(tbv));
+    }
+
+    std::vector<TraceBlobView> Finalize(std::vector<TraceBlobView> vec) {
+      return vec;
+    }
+
+  } visitor;
+
+  return SliceOffImpl(offset, length, visitor);
 }
 
 }  // namespace perfetto::trace_processor::util
diff --git a/src/trace_processor/util/trace_blob_view_reader.h b/src/trace_processor/util/trace_blob_view_reader.h
index f076d04..dd9a562 100644
--- a/src/trace_processor/util/trace_blob_view_reader.h
+++ b/src/trace_processor/util/trace_blob_view_reader.h
@@ -180,6 +180,11 @@
   // NOTE: If `offset` < 'file_offset()' this method will CHECK fail.
   std::optional<TraceBlobView> SliceOff(size_t offset, size_t length) const;
 
+  // Similar to SliceOff but this method will not combine slices but instead
+  // potentially return multiple chunks. Useful if we are extracting slices to
+  // forward them to a `ChunkedTraceReader`.
+  std::vector<TraceBlobView> MultiSliceOff(size_t offset, size_t length) const;
+
   // Returns the offset to the start of the available data.
   size_t start_offset() const {
     return data_.empty() ? end_offset_ : data_.front().start_offset;
@@ -194,6 +199,9 @@
   bool empty() const { return data_.empty(); }
 
  private:
+  template <typename Visitor>
+  auto SliceOffImpl(size_t offset, size_t length, Visitor& visitor) const;
+
   // CircularQueue has no const_iterator, so mutable is needed to access it from
   // const methods.
   mutable base::CircularQueue<Entry> data_;
diff --git a/src/trace_processor/util/trace_type.cc b/src/trace_processor/util/trace_type.cc
index 7c8d9e6..bec7279 100644
--- a/src/trace_processor/util/trace_type.cc
+++ b/src/trace_processor/util/trace_type.cc
@@ -41,6 +41,9 @@
 constexpr char kZipMagic[] = {'P', 'K', '\x03', '\x04'};
 constexpr char kGzipMagic[] = {'\x1f', '\x8b'};
 constexpr char kArtMethodStreamingMagic[] = {'S', 'L', 'O', 'W'};
+constexpr char kTarPosixMagic[] = {'u', 's', 't', 'a', 'r', '\0'};
+constexpr char kTarGnuMagic[] = {'u', 's', 't', 'a', 'r', ' ', ' ', '\0'};
+constexpr size_t kTarMagicOffset = 257;
 
 constexpr uint8_t kTracePacketTag =
     protozero::proto_utils::MakeTagLengthDelimited(
@@ -59,11 +62,15 @@
 }
 
 template <size_t N>
-bool MatchesMagic(const uint8_t* data, size_t size, const char (&magic)[N]) {
-  if (size < N) {
+bool MatchesMagic(const uint8_t* data,
+                  size_t size,
+                  const char (&magic)[N],
+                  size_t offset = 0) {
+  if (size < N + offset) {
     return false;
   }
-  return memcmp(data, magic, N) == 0;
+
+  return memcmp(data + offset, magic, N) == 0;
 }
 
 bool IsProtoTraceWithSymbols(const uint8_t* ptr, size_t size) {
@@ -136,6 +143,8 @@
       return "perf_text";
     case kUnknownTraceType:
       return "unknown";
+    case kTarTraceType:
+      return "tar";
   }
   PERFETTO_FATAL("For GCC");
 }
@@ -145,6 +154,14 @@
     return kUnknownTraceType;
   }
 
+  if (MatchesMagic(data, size, kTarPosixMagic, kTarMagicOffset)) {
+    return kTarTraceType;
+  }
+
+  if (MatchesMagic(data, size, kTarGnuMagic, kTarMagicOffset)) {
+    return kTarTraceType;
+  }
+
   if (MatchesMagic(data, size, kFuchsiaMagic)) {
     return kFuchsiaTraceType;
   }
diff --git a/src/trace_processor/util/trace_type.h b/src/trace_processor/util/trace_type.h
index 2e9d17d..80d8ff4 100644
--- a/src/trace_processor/util/trace_type.h
+++ b/src/trace_processor/util/trace_type.h
@@ -41,6 +41,7 @@
   kGeckoTraceType,
   kArtMethodTraceType,
   kPerfTextTraceType,
+  kTarTraceType,
 };
 
 constexpr size_t kGuessTraceMaxLookahead = 64;
diff --git a/test/data/perf_track_sym.tar.gz.sha256 b/test/data/perf_track_sym.tar.gz.sha256
new file mode 100644
index 0000000..edccf35
--- /dev/null
+++ b/test/data/perf_track_sym.tar.gz.sha256
@@ -0,0 +1 @@
+358db7f9628a9bb79d2dffa274c73c2894c3c7108b67bfb9f513bf4bac34acd6
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/parser/android/tests_bugreport.py b/test/trace_processor/diff_tests/parser/android/tests_bugreport.py
index d67867d..b52f5f8 100644
--- a/test/trace_processor/diff_tests/parser/android/tests_bugreport.py
+++ b/test/trace_processor/diff_tests/parser/android/tests_bugreport.py
@@ -60,18 +60,36 @@
         """,
         out=Path('android_bugreport_dumpsys_test.out'))
 
-  def test_android_bugreport_trace_types(self):
+  def test_android_bugreport_parse_order(self):
     return DiffTestBlueprint(
         trace=DataPath('bugreport-crosshatch-SPB5.zip'),
         query="""
         SELECT *
         FROM __intrinsic_trace_file
-        ORDER BY id
+        WHERE trace_type <> "unknown"
+        ORDER BY processing_order
         """,
         out=Csv("""
-        "id","type","parent_id","name","size","trace_type"
-        0,"__intrinsic_trace_file","[NULL]","[NULL]",6220586,"zip"
-        1,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat.01",2169697,"android_logcat"
-        2,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat",2152073,"android_logcat"
-        3,"__intrinsic_trace_file",0,"bugreport-crosshatch-SPB5.210812.002-2021-08-24-23-35-40.txt",43132864,"android_dumpstate"
-        """))
\ No newline at end of file
+        "id","type","parent_id","name","size","trace_type","processing_order"
+        0,"__intrinsic_trace_file","[NULL]","[NULL]",6220586,"zip",0
+        16,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat.01",2169697,"android_logcat",1
+        15,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat",2152073,"android_logcat",2
+        1,"__intrinsic_trace_file",0,"bugreport-crosshatch-SPB5.210812.002-2021-08-24-23-35-40.txt",43132864,"android_dumpstate",3
+        """))
+
+  def test_android_bugreport_trace_types(self):
+    return DiffTestBlueprint(
+        trace=DataPath('bugreport-crosshatch-SPB5.zip'),
+        query="""
+        SELECT trace_type, count(*) AS cnt, sum(size) AS total_size
+        FROM __intrinsic_trace_file
+        GROUP BY trace_type
+        ORDER BY trace_type
+        """,
+        out=Csv("""
+        "trace_type","cnt","total_size"
+        "android_dumpstate",1,43132864
+        "android_logcat",2,4321770
+        "unknown",2452,626115
+        "zip",1,6220586
+        """))
diff --git a/test/trace_processor/diff_tests/parser/zip/tests.py b/test/trace_processor/diff_tests/parser/zip/tests.py
index 660bdbe..4e46286 100644
--- a/test/trace_processor/diff_tests/parser/zip/tests.py
+++ b/test/trace_processor/diff_tests/parser/zip/tests.py
@@ -59,20 +59,37 @@
         "main,E"
         '''))
 
-  def test_tokenization_order(self):
+  def test_zip_tokenization_order(self):
     return DiffTestBlueprint(
         trace=DataPath('zip/perf_track_sym.zip'),
         query='''
         SELECT *
         FROM __intrinsic_trace_file
-        ORDER BY id
+        ORDER BY processing_order
         ''',
         out=Csv('''
-        "id","type","parent_id","name","size","trace_type"
-        0,"__intrinsic_trace_file","[NULL]","[NULL]",94651,"zip"
-        1,"__intrinsic_trace_file",0,"c.trace.pb",379760,"proto"
-        2,"__intrinsic_trace_file",0,"b.simpleperf.data",554911,"perf"
-        3,"__intrinsic_trace_file",0,"a.symbols.pb",186149,"symbols"
+        "id","type","parent_id","name","size","trace_type","processing_order"
+        0,"__intrinsic_trace_file","[NULL]","[NULL]",94651,"zip",0
+        3,"__intrinsic_trace_file",0,"c.trace.pb",379760,"proto",1
+        1,"__intrinsic_trace_file",0,"b.simpleperf.data",554911,"perf",2
+        2,"__intrinsic_trace_file",0,"a.symbols.pb",186149,"symbols",3
+        '''))
+
+  def test_tar_gz_tokenization_order(self):
+    return DiffTestBlueprint(
+        trace=DataPath('perf_track_sym.tar.gz'),
+        query='''
+        SELECT *
+        FROM __intrinsic_trace_file
+        ORDER BY processing_order
+        ''',
+        out=Csv('''
+        "id","type","parent_id","name","size","trace_type","processing_order"
+        0,"__intrinsic_trace_file","[NULL]","[NULL]",94091,"gzip",0
+        1,"__intrinsic_trace_file",0,"",1126400,"tar",1
+        4,"__intrinsic_trace_file",1,"/c.trace.pb",379760,"proto",2
+        3,"__intrinsic_trace_file",1,"/b.simpleperf.data",554911,"perf",3
+        2,"__intrinsic_trace_file",1,"/a.symbols.pb",186149,"symbols",4
         '''))
 
   # Make sure the logcat timestamps are correctly converted to trace ts. All