Add slice name translation

This is similar to args translation, but for slices.

Bug: 223172259
Change-Id: Ib2440bd61439345a9324da256698e22bf44d29dd
diff --git a/Android.bp b/Android.bp
index 033a182..da066bb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8197,6 +8197,7 @@
         "src/trace_processor/importers/common/global_args_tracker.cc",
         "src/trace_processor/importers/common/process_tracker.cc",
         "src/trace_processor/importers/common/slice_tracker.cc",
+        "src/trace_processor/importers/common/slice_translation_table.cc",
         "src/trace_processor/importers/common/system_info_tracker.cc",
         "src/trace_processor/importers/common/track_tracker.cc",
     ],
@@ -8212,6 +8213,7 @@
         "src/trace_processor/importers/common/flow_tracker_unittest.cc",
         "src/trace_processor/importers/common/process_tracker_unittest.cc",
         "src/trace_processor/importers/common/slice_tracker_unittest.cc",
+        "src/trace_processor/importers/common/slice_translation_table_unittest.cc",
     ],
 }
 
diff --git a/BUILD b/BUILD
index 7bd6250..17d5a15 100644
--- a/BUILD
+++ b/BUILD
@@ -995,6 +995,8 @@
         "src/trace_processor/importers/common/process_tracker.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",
+        "src/trace_processor/importers/common/slice_translation_table.h",
         "src/trace_processor/importers/common/system_info_tracker.cc",
         "src/trace_processor/importers/common/system_info_tracker.h",
         "src/trace_processor/importers/common/trace_parser.h",
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index d683c97..9dd1cc3 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -9873,6 +9873,7 @@
     ChromeHistorgramTranslationTable chrome_histogram = 1;
     ChromeUserEventTranslationTable chrome_user_event = 2;
     ChromePerformanceMarkTranslationTable chrome_performance_mark = 3;
+    SliceNameTranslationTable slice_name = 4;
   }
 }
 
@@ -9892,6 +9893,11 @@
   map<uint32, string> mark_hash_to_name = 2;
 };
 
+// Raw -> deobfuscated slice name translation rules.
+message SliceNameTranslationTable {
+  map<string, string> raw_to_deobfuscated_name = 1;
+};
+
 // End of protos/perfetto/trace/translation/translation_table.proto
 
 // Begin of protos/perfetto/trace/trigger.proto
diff --git a/protos/perfetto/trace/translation/translation_table.proto b/protos/perfetto/trace/translation/translation_table.proto
index 6daf54b..06cef31 100644
--- a/protos/perfetto/trace/translation/translation_table.proto
+++ b/protos/perfetto/trace/translation/translation_table.proto
@@ -25,6 +25,7 @@
     ChromeHistorgramTranslationTable chrome_histogram = 1;
     ChromeUserEventTranslationTable chrome_user_event = 2;
     ChromePerformanceMarkTranslationTable chrome_performance_mark = 3;
+    SliceNameTranslationTable slice_name = 4;
   }
 }
 
@@ -43,3 +44,8 @@
   map<uint32, string> site_hash_to_name = 1;
   map<uint32, string> mark_hash_to_name = 2;
 };
+
+// Raw -> deobfuscated slice name translation rules.
+message SliceNameTranslationTable {
+  map<string, string> raw_to_deobfuscated_name = 1;
+};
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index 7048b96..5d19218 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -33,6 +33,8 @@
     "process_tracker.h",
     "slice_tracker.cc",
     "slice_tracker.h",
+    "slice_translation_table.cc",
+    "slice_translation_table.h",
     "system_info_tracker.cc",
     "system_info_tracker.h",
     "trace_parser.h",
@@ -65,6 +67,7 @@
     "flow_tracker_unittest.cc",
     "process_tracker_unittest.cc",
     "slice_tracker_unittest.cc",
+    "slice_translation_table_unittest.cc",
   ]
   testonly = true
   deps = [
diff --git a/src/trace_processor/importers/common/flow_tracker_unittest.cc b/src/trace_processor/importers/common/flow_tracker_unittest.cc
index d8af423..3ac912f 100644
--- a/src/trace_processor/importers/common/flow_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/flow_tracker_unittest.cc
@@ -18,6 +18,7 @@
 
 #include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 #include "test/gtest_and_gmock.h"
@@ -32,6 +33,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
@@ -64,6 +67,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
@@ -100,6 +105,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
@@ -135,6 +142,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
@@ -185,6 +194,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
@@ -235,6 +246,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.slice_tracker.reset(new SliceTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   auto& slice_tracker = context.slice_tracker;
   FlowTracker tracker(&context);
   slice_tracker->SetOnSliceBeginCallback(
diff --git a/src/trace_processor/importers/common/slice_tracker.cc b/src/trace_processor/importers/common/slice_tracker.cc
index 9396406..8bd2585 100644
--- a/src/trace_processor/importers/common/slice_tracker.cc
+++ b/src/trace_processor/importers/common/slice_tracker.cc
@@ -20,6 +20,7 @@
 
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
@@ -39,8 +40,10 @@
 base::Optional<SliceId> SliceTracker::Begin(int64_t timestamp,
                                             TrackId track_id,
                                             StringId category,
-                                            StringId name,
+                                            StringId raw_name,
                                             SetArgsCallback args_callback) {
+  const StringId name =
+      context_->slice_translation_table->TranslateName(raw_name);
   tables::SliceTable::Row row(timestamp, kPendingDuration, track_id, category,
                               name);
   return StartSlice(timestamp, track_id, args_callback, [this, &row]() {
@@ -50,6 +53,10 @@
 
 void SliceTracker::BeginLegacyUnnestable(tables::SliceTable::Row row,
                                          SetArgsCallback args_callback) {
+  if (row.name) {
+    row.name = context_->slice_translation_table->TranslateName(*row.name);
+  }
+
   // Ensure that the duration is pending for this row.
   // TODO(lalitm): change this to eventually use null instead of -1.
   row.dur = kPendingDuration;
@@ -72,11 +79,13 @@
 base::Optional<SliceId> SliceTracker::Scoped(int64_t timestamp,
                                              TrackId track_id,
                                              StringId category,
-                                             StringId name,
+                                             StringId raw_name,
                                              int64_t duration,
                                              SetArgsCallback args_callback) {
   PERFETTO_DCHECK(duration >= 0);
 
+  const StringId name =
+      context_->slice_translation_table->TranslateName(raw_name);
   tables::SliceTable::Row row(timestamp, duration, track_id, category, name);
   return StartSlice(timestamp, track_id, args_callback, [this, &row]() {
     return context_->storage->mutable_slice_table()->Insert(row).id;
@@ -86,8 +95,10 @@
 base::Optional<SliceId> SliceTracker::End(int64_t timestamp,
                                           TrackId track_id,
                                           StringId category,
-                                          StringId name,
+                                          StringId raw_name,
                                           SetArgsCallback args_callback) {
+  const StringId name =
+      context_->slice_translation_table->TranslateName(raw_name);
   auto finder = [this, category, name](const SlicesStack& stack) {
     return MatchingIncompleteSliceIndex(stack, name, category);
   };
diff --git a/src/trace_processor/importers/common/slice_tracker.h b/src/trace_processor/importers/common/slice_tracker.h
index 847bda6..3167ac0 100644
--- a/src/trace_processor/importers/common/slice_tracker.h
+++ b/src/trace_processor/importers/common/slice_tracker.h
@@ -42,7 +42,7 @@
       int64_t timestamp,
       TrackId track_id,
       StringId category,
-      StringId name,
+      StringId raw_name,
       SetArgsCallback args_callback = SetArgsCallback());
 
   // Unnestable slices are slices which do not have any concept of nesting so
@@ -70,7 +70,7 @@
       int64_t timestamp,
       TrackId track_id,
       StringId category,
-      StringId name,
+      StringId raw_name,
       int64_t duration,
       SetArgsCallback args_callback = SetArgsCallback());
 
@@ -89,7 +89,7 @@
       int64_t timestamp,
       TrackId track_id,
       StringId opt_category = {},
-      StringId opt_name = {},
+      StringId opt_raw_name = {},
       SetArgsCallback args_callback = SetArgsCallback());
 
   // Usually args should be added in the Begin or End args_callback but this
diff --git a/src/trace_processor/importers/common/slice_tracker_unittest.cc b/src/trace_processor/importers/common/slice_tracker_unittest.cc
index cb6e579..29e7489 100644
--- a/src/trace_processor/importers/common/slice_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/slice_tracker_unittest.cc
@@ -18,6 +18,7 @@
 
 #include "src/trace_processor/importers/common/args_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 #include "test/gtest_and_gmock.h"
@@ -53,6 +54,8 @@
 TEST(SliceTrackerTest, OneSliceDetailed) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -72,9 +75,39 @@
   EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
 }
 
+TEST(SliceTrackerTest, OneSliceDetailedWithTranslatedName) {
+  TraceProcessorContext context;
+  context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
+  SliceTracker tracker(&context);
+
+  const StringId raw_name = context.storage->InternString("raw_name");
+  const StringId mapped_name = context.storage->InternString("mapped_name");
+  context.slice_translation_table->AddNameTranslationRule("raw_name",
+                                                          "mapped_name");
+
+  constexpr TrackId track{22u};
+  tracker.Begin(2 /*ts*/, track, kNullStringId /*cat*/, raw_name /*name*/);
+  tracker.End(10 /*ts*/, track, kNullStringId /*cat*/, raw_name /*name*/);
+
+  const auto& slices = context.storage->slice_table();
+  EXPECT_EQ(slices.row_count(), 1u);
+  EXPECT_EQ(slices.ts()[0], 2);
+  EXPECT_EQ(slices.dur()[0], 8);
+  EXPECT_EQ(slices.track_id()[0], track);
+  EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
+  EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(),
+            mapped_name.raw_id());
+  EXPECT_EQ(slices.depth()[0], 0u);
+  EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
+}
+
 TEST(SliceTrackerTest, NegativeTimestamps) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -98,6 +131,8 @@
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
   context.global_args_tracker.reset(new GlobalArgsTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -137,9 +172,60 @@
   EXPECT_EQ(args.int_value()[1], 20);
 }
 
+TEST(SliceTrackerTest, OneSliceWithArgsWithTranslatedName) {
+  TraceProcessorContext context;
+  context.storage.reset(new TraceStorage());
+  context.global_args_tracker.reset(new GlobalArgsTracker(&context));
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
+  SliceTracker tracker(&context);
+
+  const StringId raw_name = context.storage->InternString("raw_name");
+  const StringId mapped_name = context.storage->InternString("mapped_name");
+  context.slice_translation_table->AddNameTranslationRule("raw_name",
+                                                          "mapped_name");
+
+  constexpr TrackId track{22u};
+  tracker.Begin(2 /*ts*/, track, kNullStringId /*cat*/, raw_name /*name*/,
+                [](ArgsTracker::BoundInserter* inserter) {
+                  inserter->AddArg(/*flat_key=*/StringId::Raw(1),
+                                   /*key=*/StringId::Raw(2),
+                                   /*value=*/Variadic::Integer(10));
+                });
+  tracker.End(10 /*ts*/, track, kNullStringId /*cat*/, raw_name /*name*/,
+              [](ArgsTracker::BoundInserter* inserter) {
+                inserter->AddArg(/*flat_key=*/StringId::Raw(3),
+                                 /*key=*/StringId::Raw(4),
+                                 /*value=*/Variadic::Integer(20));
+              });
+
+  const auto& slices = context.storage->slice_table();
+  EXPECT_EQ(slices.row_count(), 1u);
+  EXPECT_EQ(slices.ts()[0], 2);
+  EXPECT_EQ(slices.dur()[0], 8);
+  EXPECT_EQ(slices.track_id()[0], track);
+  EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
+  EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(),
+            mapped_name.raw_id());
+  EXPECT_EQ(slices.depth()[0], 0u);
+  auto set_id = slices.arg_set_id()[0];
+
+  const auto& args = context.storage->arg_table();
+  EXPECT_EQ(args.arg_set_id()[0], set_id);
+  EXPECT_EQ(args.flat_key()[0].raw_id(), 1u);
+  EXPECT_EQ(args.key()[0].raw_id(), 2u);
+  EXPECT_EQ(args.int_value()[0], 10);
+  EXPECT_EQ(args.arg_set_id()[1], set_id);
+  EXPECT_EQ(args.flat_key()[1].raw_id(), 3u);
+  EXPECT_EQ(args.key()[1].raw_id(), 4u);
+  EXPECT_EQ(args.int_value()[1], 20);
+}
+
 TEST(SliceTrackerTest, TwoSliceDetailed) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -177,6 +263,8 @@
 TEST(SliceTrackerTest, Scoped) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -191,9 +279,34 @@
               ElementsAre(SliceInfo{0, 10}, SliceInfo{1, 8}, SliceInfo{2, 6}));
 }
 
+TEST(SliceTrackerTest, ScopedWithTranslatedName) {
+  TraceProcessorContext context;
+  context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
+  SliceTracker tracker(&context);
+
+  const StringId raw_name = context.storage->InternString("raw_name");
+  context.slice_translation_table->AddNameTranslationRule("raw_name",
+                                                          "mapped_name");
+
+  constexpr TrackId track{22u};
+  tracker.Begin(0 /*ts*/, track, kNullStringId, raw_name);
+  tracker.Begin(1 /*ts*/, track, kNullStringId, raw_name);
+  tracker.Scoped(2 /*ts*/, track, kNullStringId, raw_name, 6);
+  tracker.End(9 /*ts*/, track);
+  tracker.End(10 /*ts*/, track);
+
+  auto slices = ToSliceInfo(context.storage->slice_table());
+  EXPECT_THAT(slices,
+              ElementsAre(SliceInfo{0, 10}, SliceInfo{1, 8}, SliceInfo{2, 6}));
+}
+
 TEST(SliceTrackerTest, ParentId) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -213,6 +326,8 @@
 TEST(SliceTrackerTest, IgnoreMismatchedEnds) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -232,6 +347,8 @@
 TEST(SliceTrackerTest, ZeroLengthScoped) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   // Bug scenario: the second zero-length scoped slice prevents the first slice
@@ -255,6 +372,8 @@
 TEST(SliceTrackerTest, DifferentTracks) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track_a{22u};
@@ -280,6 +399,8 @@
 TEST(SliceTrackerTest, EndEventOutOfOrder) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   constexpr TrackId track{22u};
@@ -330,6 +451,8 @@
 TEST(SliceTrackerTest, GetTopmostSliceOnTrack) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   TrackId track{1u};
@@ -361,6 +484,8 @@
 TEST(SliceTrackerTest, OnSliceBeginCallback) {
   TraceProcessorContext context;
   context.storage.reset(new TraceStorage());
+  context.slice_translation_table.reset(
+      new SliceTranslationTable(context.storage.get()));
   SliceTracker tracker(&context);
 
   TrackId track1{1u};
diff --git a/src/trace_processor/importers/common/slice_translation_table.cc b/src/trace_processor/importers/common/slice_translation_table.cc
new file mode 100644
index 0000000..8c34dc7
--- /dev/null
+++ b/src/trace_processor/importers/common/slice_translation_table.cc
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/importers/common/slice_translation_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+SliceTranslationTable::SliceTranslationTable(TraceStorage* storage)
+    : storage_(storage) {}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/common/slice_translation_table.h b/src/trace_processor/importers/common/slice_translation_table.h
new file mode 100644
index 0000000..bcbad16
--- /dev/null
+++ b/src/trace_processor/importers/common/slice_translation_table.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRANSLATION_TABLE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRANSLATION_TABLE_H_
+
+#include <cstdint>
+
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/storage/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Tracks and stores slice translation rules. It allows Trace Processor
+// to for example deobfuscate slice names.
+class SliceTranslationTable {
+ public:
+  SliceTranslationTable(TraceStorage* storage);
+
+  // If the name is not mapped to anything, assumes that no translation is
+  // necessry, and returns the raw_name.
+  StringId TranslateName(StringId raw_name) const {
+    const auto* mapped_name = raw_to_deobfuscated_name_.Find(raw_name);
+    return mapped_name ? *mapped_name : raw_name;
+  }
+
+  void AddNameTranslationRule(base::StringView raw,
+                              base::StringView deobfuscated) {
+    const StringId raw_id = storage_->InternString(raw);
+    const StringId deobfuscated_id = storage_->InternString(deobfuscated);
+    raw_to_deobfuscated_name_[raw_id] = deobfuscated_id;
+  }
+
+ private:
+  TraceStorage* storage_;
+  base::FlatHashMap<StringId, StringId> raw_to_deobfuscated_name_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRANSLATION_TABLE_H_
diff --git a/src/trace_processor/importers/common/slice_translation_table_unittest.cc b/src/trace_processor/importers/common/slice_translation_table_unittest.cc
new file mode 100644
index 0000000..11bb5e3
--- /dev/null
+++ b/src/trace_processor/importers/common/slice_translation_table_unittest.cc
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/importers/common/slice_translation_table.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(SliceTranslationTable, UnknownName) {
+  TraceStorage storage;
+  SliceTranslationTable table(&storage);
+  const StringId raw_name = storage.InternString("name1");
+  EXPECT_EQ(raw_name, table.TranslateName(raw_name));
+}
+
+TEST(SliceTranslationTable, MappedName) {
+  TraceStorage storage;
+  SliceTranslationTable table(&storage);
+  table.AddNameTranslationRule("raw_name1", "mapped_name1");
+  const StringId raw_name = storage.InternString("raw_name1");
+  const StringId mapped_name = storage.InternString("mapped_name1");
+  EXPECT_EQ(mapped_name, table.TranslateName(raw_name));
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
index 7f62c06..cb02520 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
@@ -22,6 +22,7 @@
 #include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/storage/trace_storage.h"
 #include "test/gtest_and_gmock.h"
@@ -38,6 +39,8 @@
     context.global_args_tracker.reset(new GlobalArgsTracker(&context));
     context.args_tracker.reset(new ArgsTracker(&context));
     context.slice_tracker.reset(new SliceTracker(&context));
+    context.slice_translation_table.reset(
+        new SliceTranslationTable(context.storage.get()));
     context.process_tracker.reset(new ProcessTracker(&context));
     context.track_tracker.reset(new TrackTracker(&context));
     context.flow_tracker.reset(new FlowTracker(&context));
diff --git a/src/trace_processor/importers/proto/translation_table_module.cc b/src/trace_processor/importers/proto/translation_table_module.cc
index 46cef11..bc3f6e2 100644
--- a/src/trace_processor/importers/proto/translation_table_module.cc
+++ b/src/trace_processor/importers/proto/translation_table_module.cc
@@ -16,6 +16,7 @@
 #include "src/trace_processor/importers/proto/translation_table_module.h"
 
 #include "src/trace_processor/importers/common/args_translation_table.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "protos/perfetto/trace/translation/translation_table.pbzero.h"
@@ -47,6 +48,8 @@
   } else if (translation_table.has_chrome_performance_mark()) {
     ParseChromePerformanceMarkRules(
         translation_table.chrome_performance_mark());
+  } else if (translation_table.has_slice_name()) {
+    ParseSliceNameRules(translation_table.slice_name());
   }
 }
 
@@ -94,5 +97,16 @@
   }
 }
 
+void TranslationTableModule::ParseSliceNameRules(protozero::ConstBytes bytes) {
+  const auto slice_name =
+      protos::pbzero::SliceNameTranslationTable::Decoder(bytes);
+  for (auto it = slice_name.raw_to_deobfuscated_name(); it; ++it) {
+    protos::pbzero::SliceNameTranslationTable::RawToDeobfuscatedNameEntry::
+        Decoder entry(*it);
+    context_->slice_translation_table->AddNameTranslationRule(entry.key(),
+                                                              entry.value());
+  }
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/translation_table_module.h b/src/trace_processor/importers/proto/translation_table_module.h
index 8d6fc68..73b1931 100644
--- a/src/trace_processor/importers/proto/translation_table_module.h
+++ b/src/trace_processor/importers/proto/translation_table_module.h
@@ -41,6 +41,7 @@
   void ParseChromeHistogramRules(protozero::ConstBytes bytes);
   void ParseChromeUserEventRules(protozero::ConstBytes bytes);
   void ParseChromePerformanceMarkRules(protozero::ConstBytes bytes);
+  void ParseSliceNameRules(protozero::ConstBytes bytes);
 
   TraceProcessorContext* context_;
 };
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 75800f3..a3392f2 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -26,6 +26,7 @@
 #include "src/trace_processor/importers/common/global_args_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/proto/async_track_set_tracker.h"
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 47693df..79f96dd 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -27,6 +27,7 @@
 #include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
 #include "src/trace_processor/importers/default_modules.h"
 #include "src/trace_processor/importers/proto/async_track_set_tracker.h"
@@ -53,6 +54,8 @@
   context_.args_translation_table.reset(
       new ArgsTranslationTable(context_.storage.get()));
   context_.slice_tracker.reset(new SliceTracker(&context_));
+  context_.slice_translation_table.reset(
+      new SliceTranslationTable(context_.storage.get()));
   context_.flow_tracker.reset(new FlowTracker(&context_));
   context_.event_tracker.reset(new EventTracker(&context_));
   context_.process_tracker.reset(new ProcessTracker(&context_));
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index 221c62b..7e34e1a 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -44,6 +44,7 @@
 class ProtoImporterModule;
 class ProcessTracker;
 class SliceTracker;
+class SliceTranslationTable;
 class FlowTracker;
 class TraceParser;
 class TraceSorter;
@@ -73,6 +74,7 @@
   std::unique_ptr<TrackTracker> track_tracker;
   std::unique_ptr<AsyncTrackSetTracker> async_track_set_tracker;
   std::unique_ptr<SliceTracker> slice_tracker;
+  std::unique_ptr<SliceTranslationTable> slice_translation_table;
   std::unique_ptr<FlowTracker> flow_tracker;
   std::unique_ptr<ProcessTracker> process_tracker;
   std::unique_ptr<EventTracker> event_tracker;
diff --git a/test/trace_processor/translation/index b/test/trace_processor/translation/index
index 1d5319d..2e4696c 100644
--- a/test/trace_processor/translation/index
+++ b/test/trace_processor/translation/index
@@ -1,3 +1,4 @@
 chrome_histogram.textproto chrome_args.sql chrome_histogram.out
 chrome_user_event.textproto chrome_args.sql chrome_user_event.out
 chrome_performance_mark.textproto chrome_args.sql chrome_performance_mark.out
+slice_name.textproto slice_name.sql slice_name.out
diff --git a/test/trace_processor/translation/slice_name.out b/test/trace_processor/translation/slice_name.out
new file mode 100644
index 0000000..5073cca
--- /dev/null
+++ b/test/trace_processor/translation/slice_name.out
@@ -0,0 +1,4 @@
+"name"
+"mapped_name1"
+"mapped_name2"
+"raw_name3"
diff --git a/test/trace_processor/translation/slice_name.sql b/test/trace_processor/translation/slice_name.sql
new file mode 100644
index 0000000..a3011a8
--- /dev/null
+++ b/test/trace_processor/translation/slice_name.sql
@@ -0,0 +1 @@
+SELECT name FROM slice ORDER BY name;
diff --git a/test/trace_processor/translation/slice_name.textproto b/test/trace_processor/translation/slice_name.textproto
new file mode 100644
index 0000000..095cbf4
--- /dev/null
+++ b/test/trace_processor/translation/slice_name.textproto
@@ -0,0 +1,35 @@
+packet {
+  translation_table {
+    slice_name {
+      raw_to_deobfuscated_name { key: "raw_name1" value: "mapped_name1" }
+      raw_to_deobfuscated_name { key: "raw_name2" value: "mapped_name2" }
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    categories: "cat"
+    name: "raw_name1"
+    type: 3
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    categories: "cat"
+    name: "raw_name2"
+    type: 3
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    categories: "cat"
+    name: "raw_name3"
+    type: 3
+  }
+}