Trace Redaction - Combine process event redactions
Outside of scheduling information, there are three events that must
be redacted: new task, process free, and task rename.
Each event can be redacted using the scheduling filter and modifier
handlers, making it easier for the scheduling and event redaction
to share redaction logic.
This moves the different redactions into one class. This was
previously avoided in an effort to make the system more modular.
However, to avoid issues around thread merging, this change should
decrease risk, improve readibility, and decrease computational the
number of packets decoded and encoded.
Bug: 318576499
Change-Id: I919266e02d250cf64154fd9c110d197d4d385cbc
diff --git a/Android.bp b/Android.bp
index 925e592..d807b27 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13610,7 +13610,6 @@
"src/trace_redaction/filter_ftrace_using_allowlist.cc",
"src/trace_redaction/filter_packet_using_allowlist.cc",
"src/trace_redaction/filter_print_events.cc",
- "src/trace_redaction/filter_task_rename.cc",
"src/trace_redaction/find_package_uid.cc",
"src/trace_redaction/modify_process_trees.cc",
"src/trace_redaction/populate_allow_lists.cc",
@@ -13618,10 +13617,9 @@
"src/trace_redaction/proto_util.cc",
"src/trace_redaction/prune_package_list.cc",
"src/trace_redaction/redact_ftrace_event.cc",
+ "src/trace_redaction/redact_process_events.cc",
"src/trace_redaction/redact_sched_events.cc",
- "src/trace_redaction/redact_task_newtask.cc",
"src/trace_redaction/remap_scheduling_events.cc",
- "src/trace_redaction/remove_process_free_comm.cc",
"src/trace_redaction/scrub_ftrace_events.cc",
"src/trace_redaction/scrub_process_stats.cc",
"src/trace_redaction/scrub_process_trees.cc",
@@ -13643,15 +13641,13 @@
"src/trace_redaction/filter_ftrace_using_allowlist_unittest.cc",
"src/trace_redaction/filter_packet_using_allowlist_unittest.cc",
"src/trace_redaction/filter_sched_waking_events_unittest.cc",
- "src/trace_redaction/filter_task_rename_unittest.cc",
"src/trace_redaction/find_package_uid_unittest.cc",
"src/trace_redaction/process_thread_timeline_unittest.cc",
"src/trace_redaction/proto_util_unittest.cc",
"src/trace_redaction/prune_package_list_unittest.cc",
+ "src/trace_redaction/redact_process_events_unittest.cc",
"src/trace_redaction/redact_sched_events_unittest.cc",
- "src/trace_redaction/redact_task_newtask_unittest.cc",
"src/trace_redaction/remap_scheduling_events_unittest.cc",
- "src/trace_redaction/remove_process_free_comm_unittest.cc",
"src/trace_redaction/suspend_resume_unittest.cc",
"src/trace_redaction/verify_integrity_unittest.cc",
],
diff --git a/src/trace_redaction/BUILD.gn b/src/trace_redaction/BUILD.gn
index c5af11a..fdff971 100644
--- a/src/trace_redaction/BUILD.gn
+++ b/src/trace_redaction/BUILD.gn
@@ -40,8 +40,6 @@
"filter_packet_using_allowlist.h",
"filter_print_events.cc",
"filter_print_events.h",
- "filter_task_rename.cc",
- "filter_task_rename.h",
"find_package_uid.cc",
"find_package_uid.h",
"frame_cookie.h",
@@ -57,14 +55,12 @@
"prune_package_list.h",
"redact_ftrace_event.cc",
"redact_ftrace_event.h",
+ "redact_process_events.cc",
+ "redact_process_events.h",
"redact_sched_events.cc",
"redact_sched_events.h",
- "redact_task_newtask.cc",
- "redact_task_newtask.h",
"remap_scheduling_events.cc",
"remap_scheduling_events.h",
- "remove_process_free_comm.cc",
- "remove_process_free_comm.h",
"scrub_ftrace_events.cc",
"scrub_ftrace_events.h",
"scrub_process_stats.cc",
@@ -137,15 +133,13 @@
"filter_ftrace_using_allowlist_unittest.cc",
"filter_packet_using_allowlist_unittest.cc",
"filter_sched_waking_events_unittest.cc",
- "filter_task_rename_unittest.cc",
"find_package_uid_unittest.cc",
"process_thread_timeline_unittest.cc",
"proto_util_unittest.cc",
"prune_package_list_unittest.cc",
+ "redact_process_events_unittest.cc",
"redact_sched_events_unittest.cc",
- "redact_task_newtask_unittest.cc",
"remap_scheduling_events_unittest.cc",
- "remove_process_free_comm_unittest.cc",
"suspend_resume_unittest.cc",
"verify_integrity_unittest.cc",
]
diff --git a/src/trace_redaction/filter_task_rename.cc b/src/trace_redaction/filter_task_rename.cc
deleted file mode 100644
index 467e5b5..0000000
--- a/src/trace_redaction/filter_task_rename.cc
+++ /dev/null
@@ -1,74 +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_redaction/filter_task_rename.h"
-
-#include "perfetto/base/status.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-
-namespace perfetto::trace_redaction {
-
-base::Status FilterTaskRename::VerifyContext(const Context& context) const {
- if (!context.package_uid.has_value()) {
- return base::ErrStatus("FilterTaskRename: missing package uid.");
- }
-
- if (!context.timeline) {
- return base::ErrStatus("FilterTaskRename: missing timeline.");
- }
-
- return base::OkStatus();
-}
-
-bool FilterTaskRename::KeepEvent(const Context& context,
- protozero::ConstBytes bytes) const {
- PERFETTO_DCHECK(context.package_uid.has_value());
- PERFETTO_DCHECK(context.timeline);
-
- protozero::ProtoDecoder event_decoder(bytes);
-
- auto rename = event_decoder.FindField(
- protos::pbzero::FtraceEvent::kTaskRenameFieldNumber);
-
- // Likely - most events will not have a rename event (that's okay).
- if (!rename.valid()) {
- return true;
- }
-
- auto pid =
- event_decoder.FindField(protos::pbzero::FtraceEvent::kPidFieldNumber);
-
- // Unlikely - all events should have a pid.
- if (!pid.valid()) {
- return false;
- }
-
- auto timestamp = event_decoder.FindField(
- protos::pbzero::FtraceEvent::kTimestampFieldNumber);
-
- // Unlikely - all events should have a timestamp.
- if (!timestamp.valid()) {
- return false;
- }
-
- return context.timeline->PidConnectsToUid(
- timestamp.as_uint64(), pid.as_int32(), *context.package_uid);
-}
-
-} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/filter_task_rename.h b/src/trace_redaction/filter_task_rename.h
deleted file mode 100644
index ab0dd7f..0000000
--- a/src/trace_redaction/filter_task_rename.h
+++ /dev/null
@@ -1,37 +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_REDACTION_FILTER_TASK_RENAME_H_
-#define SRC_TRACE_REDACTION_FILTER_TASK_RENAME_H_
-
-#include "perfetto/base/status.h"
-#include "src/trace_redaction/scrub_ftrace_events.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-
-namespace perfetto::trace_redaction {
-
-// Reject rename events that don't belong to the target package.
-class FilterTaskRename final : public FtraceEventFilter {
- public:
- base::Status VerifyContext(const Context& context) const override;
-
- bool KeepEvent(const Context& context,
- protozero::ConstBytes bytes) const override;
-};
-
-} // namespace perfetto::trace_redaction
-
-#endif // SRC_TRACE_REDACTION_FILTER_TASK_RENAME_H_
diff --git a/src/trace_redaction/filter_task_rename_integrationtest.cc b/src/trace_redaction/filter_task_rename_integrationtest.cc
index f080fe7..e2675e2 100644
--- a/src/trace_redaction/filter_task_rename_integrationtest.cc
+++ b/src/trace_redaction/filter_task_rename_integrationtest.cc
@@ -16,14 +16,12 @@
#include <cstdint>
#include <string>
-#include <string_view>
#include <vector>
-#include "perfetto/base/status.h"
#include "src/base/test/status_matchers.h"
#include "src/trace_redaction/collect_timeline_events.h"
-#include "src/trace_redaction/filter_task_rename.h"
#include "src/trace_redaction/find_package_uid.h"
+#include "src/trace_redaction/redact_process_events.h"
#include "src/trace_redaction/trace_redaction_framework.h"
#include "src/trace_redaction/trace_redaction_integration_fixture.h"
#include "src/trace_redaction/trace_redactor.h"
@@ -36,17 +34,6 @@
namespace perfetto::trace_redaction {
-namespace {
-
-using FtraceEvent = protos::pbzero::FtraceEvent;
-
-// Set the package name to "just some package name". If a specific package name
-// is needed, the test it should overwrite this value.
-constexpr std::string_view kPackageName =
- "com.Unity.com.unity.multiplayer.samples.coop";
-
-} // namespace
-
class RenameEventsTraceRedactorIntegrationTest
: public testing::Test,
protected TraceRedactionIntegrationFixure {
@@ -57,33 +44,39 @@
trace_redactor()->emplace_collect<FindPackageUid>();
trace_redactor()->emplace_collect<CollectTimelineEvents>();
- auto scrub_ftrace_events =
- trace_redactor()->emplace_transform<ScrubFtraceEvents>();
- scrub_ftrace_events->emplace_back<FilterTaskRename>();
+ // Configure the system to drop every rename event not connected to the
+ // package.
+ auto* redact = trace_redactor()->emplace_transform<RedactProcessEvents>();
+ redact->emplace_filter<ConnectedToPackage>();
+ redact->emplace_modifier<DoNothing>();
- context()->package_name = kPackageName;
+ context()->package_name = "com.Unity.com.unity.multiplayer.samples.coop";
}
- std::vector<uint32_t> GetAllRenamedPids(
- protos::pbzero::Trace::Decoder trace) const {
+ void GetRenamedPids(
+ const protos::pbzero::FtraceEventBundle::Decoder& ftrace_events,
+ std::vector<uint32_t>* pids) const {
+ for (auto event_it = ftrace_events.event(); event_it; ++event_it) {
+ protos::pbzero::FtraceEvent::Decoder event(*event_it);
+
+ if (event.has_task_rename()) {
+ pids->push_back(event.pid());
+ }
+ }
+ }
+
+ std::vector<uint32_t> GetRenamedPids(const std::string bytes) const {
std::vector<uint32_t> renamed_pids;
+ protos::pbzero::Trace::Decoder trace(bytes);
+
for (auto packet_it = trace.packet(); packet_it; ++packet_it) {
protos::pbzero::TracePacket::Decoder packet_decoder(*packet_it);
- if (!packet_decoder.has_ftrace_events()) {
- continue;
- }
-
- protos::pbzero::FtraceEventBundle::Decoder bundle_decoder(
- packet_decoder.ftrace_events());
-
- for (auto event_it = bundle_decoder.event(); event_it; ++event_it) {
- protos::pbzero::FtraceEvent::Decoder event(*event_it);
-
- if (event.has_task_rename()) {
- renamed_pids.push_back(event.pid());
- }
+ if (packet_decoder.has_ftrace_events()) {
+ protos::pbzero::FtraceEventBundle::Decoder ftrace_events(
+ packet_decoder.ftrace_events());
+ GetRenamedPids(ftrace_events, &renamed_pids);
}
}
@@ -92,30 +85,25 @@
};
TEST_F(RenameEventsTraceRedactorIntegrationTest, RemovesUnwantedRenameTasks) {
- auto result = Redact();
- ASSERT_OK(result) << result.c_message();
+ ASSERT_OK(Redact());
auto original = LoadOriginal();
- ASSERT_OK(original) << original.status().c_message();
+ ASSERT_OK(original);
auto redacted = LoadRedacted();
- ASSERT_OK(redacted) << redacted.status().c_message();
+ ASSERT_OK(redacted);
- auto original_rename_pids =
- GetAllRenamedPids(protos::pbzero::Trace::Decoder(*original));
- std::sort(original_rename_pids.begin(), original_rename_pids.end());
+ auto pids_before = GetRenamedPids(*original);
+ std::sort(pids_before.begin(), pids_before.end());
- // The test trace has found rename events. This assert is just to document
- // theme.
- ASSERT_EQ(original_rename_pids.size(), 4u);
- ASSERT_EQ(original_rename_pids[0], 7971u);
- ASSERT_EQ(original_rename_pids[1], 7972u);
- ASSERT_EQ(original_rename_pids[2], 7973u);
- ASSERT_EQ(original_rename_pids[3], 7974u);
+ ASSERT_EQ(pids_before.size(), 4u);
+ ASSERT_EQ(pids_before[0], 7971u);
+ ASSERT_EQ(pids_before[1], 7972u);
+ ASSERT_EQ(pids_before[2], 7973u);
+ ASSERT_EQ(pids_before[3], 7974u);
- auto redacted_rename_pids =
- GetAllRenamedPids(protos::pbzero::Trace::Decoder(*redacted));
- ASSERT_TRUE(redacted_rename_pids.empty());
+ auto pids_after = GetRenamedPids(*redacted);
+ ASSERT_TRUE(pids_after.empty());
}
} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/filter_task_rename_unittest.cc b/src/trace_redaction/filter_task_rename_unittest.cc
deleted file mode 100644
index c11111f..0000000
--- a/src/trace_redaction/filter_task_rename_unittest.cc
+++ /dev/null
@@ -1,155 +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 <string>
-
-#include "src/trace_redaction/filter_task_rename.h"
-#include "src/trace_redaction/process_thread_timeline.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
-#include "protos/perfetto/trace/ftrace/sched.gen.h"
-#include "protos/perfetto/trace/ftrace/task.gen.h"
-#include "protos/perfetto/trace/trace_packet.gen.h"
-
-namespace perfetto::trace_redaction {
-
-namespace {
-
-// Used when a single pid is needed.
-constexpr uint32_t kPid = 7971;
-
-constexpr uint64_t kUid = 27;
-
-constexpr uint64_t kJustSomeTime = 6702094131629195;
-
-} // namespace
-
-class ScrubRenameTaskTest : public testing::Test {
- protected:
- // event {
- // timestamp: 6702094131629195
- // pid: 7971
- // task_rename {
- // pid: 7971
- // oldcomm: "adbd"
- // newcomm: "sh"
- // oom_score_adj: -950
- // }
- // }
- protos::gen::FtraceEvent CreateRenameEvent(uint64_t ts, uint32_t pid) {
- protos::gen::FtraceEvent event;
- event.set_timestamp(ts);
- event.set_pid(pid);
-
- auto* rename = event.mutable_task_rename();
- rename->set_pid(static_cast<int32_t>(pid));
- rename->set_oldcomm("adbd");
- rename->set_newcomm("sh");
- rename->set_oom_score_adj(-950);
-
- return event;
- }
-
- // event {
- // timestamp: 6702094034179654
- // pid: 7145
- // sched_switch {
- // prev_comm: "Job.worker 3"
- // prev_pid: 7145
- // prev_prio: 120
- // prev_state: 1
- // next_comm: "swapper/1"
- // next_pid: 0
- // next_prio: 120
- // }
- // }
- protos::gen::FtraceEvent CreateSomeEvent(uint64_t ts, uint32_t pid) {
- protos::gen::FtraceEvent event;
- event.set_timestamp(ts);
- event.set_pid(pid);
-
- auto* sched = event.mutable_sched_switch();
- sched->set_prev_comm("Job.worker 3");
- sched->set_prev_pid(static_cast<int32_t>(pid));
- sched->set_prev_prio(120);
- sched->set_prev_state(1);
- sched->set_next_comm("swapper/1");
- sched->set_next_pid(0);
- sched->set_next_prio(120);
-
- return event;
- }
-
- const FilterTaskRename& filter() const { return filter_; }
-
- Context* context() { return &context_; }
-
- private:
- Context context_;
- FilterTaskRename filter_;
-};
-
-TEST_F(ScrubRenameTaskTest, ReturnErrorForNoPackage) {
- context()->timeline.reset(new ProcessThreadTimeline());
-
- ASSERT_FALSE(filter().VerifyContext(*context()).ok());
-}
-
-TEST_F(ScrubRenameTaskTest, ReturnErrorForNoTimeline) {
- context()->package_name = "package name";
- context()->package_uid = kUid;
-
- ASSERT_FALSE(filter().VerifyContext(*context()).ok());
-}
-
-TEST_F(ScrubRenameTaskTest, KeepsNonRenameEvent) {
- context()->package_name = "package name";
- context()->package_uid = kUid;
-
- context()->timeline.reset(new ProcessThreadTimeline());
-
- auto event = CreateSomeEvent(kJustSomeTime, kPid).SerializeAsArray();
- ASSERT_TRUE(filter().KeepEvent(*context(), {event.data(), event.size()}));
-}
-
-TEST_F(ScrubRenameTaskTest, RejectsRenameEventOutsidePackage) {
- context()->package_name = "package name";
- context()->package_uid = kUid;
-
- // There's no connection between kPid and kUid. This means the rename packet
- // should be dropped.
- context()->timeline.reset(new ProcessThreadTimeline());
-
- auto event = CreateRenameEvent(kJustSomeTime, kPid).SerializeAsArray();
- ASSERT_FALSE(filter().KeepEvent(*context(), {event.data(), event.size()}));
-}
-
-TEST_F(ScrubRenameTaskTest, AcceptsRenameEventInPackage) {
- context()->package_name = "package name";
- context()->package_uid = kUid;
-
- context()->timeline.reset(new ProcessThreadTimeline());
- context()->timeline->Append(
- ProcessThreadTimeline::Event::Open(0, kPid, 0, kUid));
- context()->timeline->Sort();
-
- auto bytes = CreateRenameEvent(kJustSomeTime, kPid).SerializeAsArray();
- ASSERT_TRUE(filter().KeepEvent(*context(), {bytes.data(), bytes.size()}));
-}
-
-} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/main.cc b/src/trace_redaction/main.cc
index dc5d8bc..3707be1 100644
--- a/src/trace_redaction/main.cc
+++ b/src/trace_redaction/main.cc
@@ -22,15 +22,13 @@
#include "src/trace_redaction/filter_ftrace_using_allowlist.h"
#include "src/trace_redaction/filter_packet_using_allowlist.h"
#include "src/trace_redaction/filter_print_events.h"
-#include "src/trace_redaction/filter_task_rename.h"
#include "src/trace_redaction/find_package_uid.h"
#include "src/trace_redaction/populate_allow_lists.h"
#include "src/trace_redaction/prune_package_list.h"
#include "src/trace_redaction/redact_ftrace_event.h"
+#include "src/trace_redaction/redact_process_events.h"
#include "src/trace_redaction/redact_sched_events.h"
-#include "src/trace_redaction/redact_task_newtask.h"
#include "src/trace_redaction/remap_scheduling_events.h"
-#include "src/trace_redaction/remove_process_free_comm.h"
#include "src/trace_redaction/scrub_ftrace_events.h"
#include "src/trace_redaction/scrub_process_stats.h"
#include "src/trace_redaction/scrub_process_trees.h"
@@ -74,7 +72,6 @@
auto* scrub_ftrace_events = redactor.emplace_transform<ScrubFtraceEvents>();
scrub_ftrace_events->emplace_back<FilterFtraceUsingAllowlist>();
scrub_ftrace_events->emplace_back<FilterPrintEvents>();
- scrub_ftrace_events->emplace_back<FilterTaskRename>();
scrub_ftrace_events->emplace_back<FilterSuspendResume>();
// Scrub packets and ftrace events first as they will remove the largest
@@ -84,15 +81,22 @@
redactor.emplace_transform<PrunePackageList>();
redactor.emplace_transform<ScrubProcessStats>();
+ // Redacts all switch and waking events. This should use the same modifier and
+ // filter as the process events (see below).
auto* redact_sched_events = redactor.emplace_transform<RedactSchedEvents>();
redact_sched_events->emplace_modifier<ClearComms>();
redact_sched_events->emplace_filter<ConnectedToPackage>();
+ // Redacts all new task, rename task, process free events. This should use the
+ // same modifier and filter as the schedule events (see above).
+ auto* redact_process_events =
+ redactor.emplace_transform<RedactProcessEvents>();
+ redact_process_events->emplace_modifier<ClearComms>();
+ redact_process_events->emplace_filter<ConnectedToPackage>();
+
// TODO(vaage): The primitives used to implement thread merging do not work
// correctly with other primitives.
//
- // - RemoveProcessFreeComm
- // - RedactTaskNewTask
// - ThreadMergeRemapFtraceEventPid
// - ThreadMergeRemapSchedSwitchPid
// - ThreadMergeRemapSchedWakingPid
diff --git a/src/trace_redaction/redact_process_events.cc b/src/trace_redaction/redact_process_events.cc
new file mode 100644
index 0000000..8bbae7c
--- /dev/null
+++ b/src/trace_redaction/redact_process_events.cc
@@ -0,0 +1,323 @@
+/*
+ * 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_redaction/redact_process_events.h"
+
+#include <string>
+
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
+#include "protos/perfetto/trace/ftrace/task.pbzero.h"
+#include "src/trace_processor/util/status_macros.h"
+#include "src/trace_redaction/proto_util.h"
+
+namespace perfetto::trace_redaction {
+
+base::Status RedactProcessEvents::Transform(const Context& context,
+ std::string* packet) const {
+ PERFETTO_DCHECK(modifier_);
+ PERFETTO_DCHECK(filter_);
+
+ if (!context.timeline) {
+ return base::ErrStatus("RedactProcessEvents: missing timeline.");
+ }
+
+ if (!context.package_uid.has_value()) {
+ return base::ErrStatus("RedactProcessEvents: missing package uid.");
+ }
+
+ if (!packet || packet->empty()) {
+ return base::ErrStatus("RedactProcessEvents: null or empty packet.");
+ }
+
+ protozero::ProtoDecoder packet_decoder(*packet);
+
+ protozero::HeapBuffered<protos::pbzero::TracePacket> message;
+
+ for (auto it = packet_decoder.ReadField(); it.valid();
+ it = packet_decoder.ReadField()) {
+ if (it.id() == protos::pbzero::TracePacket::kFtraceEventsFieldNumber) {
+ RETURN_IF_ERROR(
+ OnFtraceEvents(context, it.as_bytes(), message->set_ftrace_events()));
+ } else {
+ proto_util::AppendField(it, message.get());
+ }
+ }
+
+ packet->assign(message.SerializeAsString());
+ return base::OkStatus();
+}
+
+base::Status RedactProcessEvents::OnFtraceEvents(
+ const Context& context,
+ protozero::ConstBytes bytes,
+ protos::pbzero::FtraceEventBundle* message) const {
+ protozero::ProtoDecoder decoder(bytes);
+
+ auto cpu =
+ decoder.FindField(protos::pbzero::FtraceEventBundle::kCpuFieldNumber);
+
+ std::string shared_comm;
+
+ for (auto it = decoder.ReadField(); it.valid(); it = decoder.ReadField()) {
+ if (it.id() == protos::pbzero::FtraceEventBundle::kEventFieldNumber) {
+ OnFtraceEvent(context, cpu.as_int32(), it.as_bytes(), &shared_comm,
+ message->add_event());
+ } else {
+ proto_util::AppendField(it, message);
+ }
+ }
+
+ return base::OkStatus();
+}
+
+// TODO(b/336807771): There is a pid on the ftrace event. This is the
+// process/thread invoking the action. In the case of a new task, its the
+// process/thread forking and starting the task. Becuase this case is so
+// common, if it needs to be modified (e.g. thread merging), it will behandled
+// there.
+base::Status RedactProcessEvents::OnFtraceEvent(
+ const Context& context,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* message) const {
+ PERFETTO_DCHECK(shared_comm);
+ PERFETTO_DCHECK(message);
+
+ protozero::ProtoDecoder decoder(bytes);
+
+ auto ts =
+ decoder.FindField(protos::pbzero::FtraceEvent::kTimestampFieldNumber);
+
+ if (!ts.valid()) {
+ return base::ErrStatus("RedactProcessEvents: missing FtraceEvent %d",
+ protos::pbzero::FtraceEvent::kTimestampFieldNumber);
+ }
+
+ for (auto it = decoder.ReadField(); it.valid(); it = decoder.ReadField()) {
+ switch (it.id()) {
+ case protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber:
+ OnProcessFree(context, ts.as_uint64(), cpu, it.as_bytes(), shared_comm,
+ message);
+ break;
+ case protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber:
+ OnNewTask(context, ts.as_uint64(), cpu, it.as_bytes(), shared_comm,
+ message);
+ break;
+ case protos::pbzero::FtraceEvent::kTaskRenameFieldNumber:
+ OnProcessRename(context, ts.as_uint64(), cpu, it.as_bytes(),
+ shared_comm, message);
+ break;
+ default:
+ proto_util::AppendField(it, message);
+ break;
+ }
+ }
+
+ return base::OkStatus();
+}
+
+base::Status RedactProcessEvents::OnProcessFree(
+ const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const {
+ PERFETTO_DCHECK(shared_comm);
+ PERFETTO_DCHECK(parent_message);
+
+ protos::pbzero::SchedProcessFreeFtraceEvent::Decoder decoder(bytes);
+
+ if (!decoder.has_pid()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing SchedProcessFreeFtraceEvent %d",
+ protos::pbzero::SchedProcessFreeFtraceEvent::kPidFieldNumber);
+ }
+
+ if (!decoder.has_comm()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing SchedProcessFreeFtraceEvent %d",
+ protos::pbzero::SchedProcessFreeFtraceEvent::kCommFieldNumber);
+ }
+
+ if (!decoder.has_prio()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing SchedProcessFreeFtraceEvent %d",
+ protos::pbzero::SchedProcessFreeFtraceEvent::kPrioFieldNumber);
+ }
+
+ auto pid = decoder.pid();
+ auto comm = decoder.comm();
+ auto prio = decoder.prio();
+
+ PERFETTO_DCHECK(filter_);
+ if (!filter_->Includes(context, ts, pid)) {
+ return base::OkStatus();
+ }
+
+ shared_comm->assign(comm.data, comm.size);
+
+ PERFETTO_DCHECK(modifier_);
+ RETURN_IF_ERROR(modifier_->Modify(context, ts, cpu, &pid, shared_comm));
+
+ auto* message = parent_message->set_sched_process_free();
+ message->set_pid(pid);
+ message->set_comm(*shared_comm);
+ message->set_prio(prio);
+
+ return base::OkStatus();
+}
+
+base::Status RedactProcessEvents::OnNewTask(
+ const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const {
+ PERFETTO_DCHECK(shared_comm);
+ PERFETTO_DCHECK(parent_message);
+
+ protos::pbzero::TaskNewtaskFtraceEvent::Decoder decoder(bytes);
+
+ if (!decoder.has_clone_flags()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskNewtaskFtraceEvent %d",
+ protos::pbzero::TaskNewtaskFtraceEvent::kCloneFlagsFieldNumber);
+ }
+
+ if (!decoder.has_comm()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskNewtaskFtraceEvent %d",
+ protos::pbzero::TaskNewtaskFtraceEvent::kCommFieldNumber);
+ }
+
+ if (!decoder.has_oom_score_adj()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskNewtaskFtraceEvent %d",
+ protos::pbzero::TaskNewtaskFtraceEvent::kOomScoreAdjFieldNumber);
+ }
+
+ if (!decoder.has_pid()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskNewtaskFtraceEvent %d",
+ protos::pbzero::TaskNewtaskFtraceEvent::kPidFieldNumber);
+ }
+
+ auto clone_flags = decoder.has_clone_flags();
+ auto comm = decoder.comm();
+ auto omm_score_adj = decoder.has_oom_score_adj();
+ auto pid = decoder.pid();
+
+ PERFETTO_DCHECK(filter_);
+ if (!filter_->Includes(context, ts, pid)) {
+ return base::OkStatus();
+ }
+
+ shared_comm->assign(comm.data, comm.size);
+
+ PERFETTO_DCHECK(modifier_);
+ RETURN_IF_ERROR(modifier_->Modify(context, ts, cpu, &pid, shared_comm));
+
+ auto* message = parent_message->set_task_newtask();
+ message->set_clone_flags(clone_flags);
+ message->set_comm(*shared_comm);
+ message->set_oom_score_adj(omm_score_adj);
+ message->set_pid(pid);
+
+ return base::OkStatus();
+}
+
+base::Status RedactProcessEvents::OnProcessRename(
+ const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const {
+ PERFETTO_DCHECK(shared_comm);
+ PERFETTO_DCHECK(parent_message);
+
+ protos::pbzero::TaskRenameFtraceEvent::Decoder decoder(bytes);
+
+ if (!decoder.has_pid()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskRenameFtraceEvent %d",
+ protos::pbzero::TaskRenameFtraceEvent::kPidFieldNumber);
+ }
+
+ if (!decoder.has_newcomm()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskRenameFtraceEvent %d",
+ protos::pbzero::TaskRenameFtraceEvent::kNewcommFieldNumber);
+ }
+
+ if (!decoder.has_oldcomm()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskRenameFtraceEvent %d",
+ protos::pbzero::TaskRenameFtraceEvent::kOldcommFieldNumber);
+ }
+
+ if (!decoder.has_oom_score_adj()) {
+ return base::ErrStatus(
+ "RedactProcessEvents: missing TaskRenameFtraceEvent %d",
+ protos::pbzero::TaskRenameFtraceEvent::kOomScoreAdjFieldNumber);
+ }
+
+ auto pid = decoder.pid();
+ auto new_comm = decoder.newcomm();
+ auto old_comm = decoder.oldcomm();
+ auto oom_score_adj = decoder.oom_score_adj();
+
+ PERFETTO_DCHECK(filter_);
+ if (!filter_->Includes(context, ts, pid)) {
+ return base::OkStatus();
+ }
+
+ auto* message = parent_message->set_task_rename();
+
+ auto noop_pid = pid;
+
+ shared_comm->assign(old_comm.data, old_comm.size);
+
+ PERFETTO_DCHECK(modifier_);
+ RETURN_IF_ERROR(modifier_->Modify(context, ts, cpu, &noop_pid, shared_comm));
+
+ // Write the old-comm now so shared_comm can be used new-comm.
+ message->set_oldcomm(*shared_comm);
+
+ shared_comm->assign(new_comm.data, new_comm.size);
+
+ PERFETTO_DCHECK(modifier_);
+ RETURN_IF_ERROR(modifier_->Modify(context, ts, cpu, &pid, shared_comm));
+
+ message->set_newcomm(*shared_comm);
+
+ // Because the same modification is used for each comm, the resulting pids
+ // should be the same.
+ PERFETTO_DCHECK(noop_pid == pid);
+
+ message->set_pid(pid);
+ message->set_oom_score_adj(oom_score_adj);
+
+ return base::OkStatus();
+}
+
+} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/redact_process_events.h b/src/trace_redaction/redact_process_events.h
new file mode 100644
index 0000000..ce4009f
--- /dev/null
+++ b/src/trace_redaction/redact_process_events.h
@@ -0,0 +1,90 @@
+/*
+ * 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_REDACTION_REDACT_PROCESS_EVENTS_H_
+#define SRC_TRACE_REDACTION_REDACT_PROCESS_EVENTS_H_
+
+#include <memory>
+
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "src/trace_redaction/redact_sched_events.h"
+#include "src/trace_redaction/trace_redaction_framework.h"
+
+namespace perfetto::trace_redaction {
+
+// Goes through a trace packet and removes tasks (i.e. task_rename,
+// task_newtask, sched_process_free), change a tasks pid, and/or change a tasks
+// comm value.
+//
+// These operations are separate from the scheduling events in an effort to make
+// the code easier to understand, however they use the same filter and modifier
+// types and should have the same values when used together.
+class RedactProcessEvents : public TransformPrimitive {
+ public:
+ base::Status Transform(const Context& context,
+ std::string* packet) const override;
+
+ template <class Modifier>
+ void emplace_modifier() {
+ modifier_ = std::make_unique<Modifier>();
+ }
+
+ template <class Filter>
+ void emplace_filter() {
+ filter_ = std::make_unique<Filter>();
+ }
+
+ private:
+ base::Status OnFtraceEvents(const Context& context,
+ protozero::ConstBytes bytes,
+ protos::pbzero::FtraceEventBundle* message) const;
+
+ base::Status OnFtraceEvent(const Context& context,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* message) const;
+
+ base::Status OnProcessFree(const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const;
+
+ base::Status OnNewTask(const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const;
+
+ base::Status OnProcessRename(
+ const Context& context,
+ uint64_t ts,
+ int32_t cpu,
+ protozero::ConstBytes bytes,
+ std::string* shared_comm,
+ protos::pbzero::FtraceEvent* parent_message) const;
+
+ std::unique_ptr<SchedEventModifier> modifier_;
+
+ std::unique_ptr<SchedEventFilter> filter_;
+};
+
+} // namespace perfetto::trace_redaction
+
+#endif // SRC_TRACE_REDACTION_REDACT_PROCESS_EVENTS_H_
diff --git a/src/trace_redaction/redact_process_events_unittest.cc b/src/trace_redaction/redact_process_events_unittest.cc
new file mode 100644
index 0000000..846b084
--- /dev/null
+++ b/src/trace_redaction/redact_process_events_unittest.cc
@@ -0,0 +1,547 @@
+/*
+ * 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_redaction/redact_process_events.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/trace/ftrace/ftrace.gen.h"
+#include "protos/perfetto/trace/ftrace/sched.gen.h"
+#include "src/base/test/status_matchers.h"
+#include "test/gtest_and_gmock.h"
+
+#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
+#include "protos/perfetto/trace/ftrace/task.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+
+namespace perfetto::trace_redaction {
+
+namespace {
+constexpr uint64_t kCpu = 1;
+
+constexpr uint64_t kUidA = 1;
+constexpr uint64_t kUidB = 2;
+
+constexpr int32_t kNoParent = 10;
+constexpr int32_t kPidA = 11;
+constexpr int32_t kPidB = 12;
+
+constexpr uint64_t kTimeA = 0;
+constexpr uint64_t kTimeB = 1000;
+
+constexpr std::string_view kCommA = "comm-a";
+constexpr std::string_view kCommB = "comm-b";
+} // namespace
+
+class RedactProcessEventsTest : public testing::Test {
+ protected:
+ void SetUp() {
+ redact_.emplace_modifier<DoNothing>();
+ redact_.emplace_filter<AllowAll>();
+ }
+
+ RedactProcessEvents redact_;
+};
+
+TEST_F(RedactProcessEventsTest, RejectMissingPackageUid) {
+ Context context;
+ context.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ protos::gen::TracePacket packet;
+ auto packet_str = packet.SerializeAsString();
+
+ ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
+}
+
+TEST_F(RedactProcessEventsTest, RejectMissingTimeline) {
+ Context context;
+ context.package_uid = kUidA;
+
+ protos::gen::TracePacket packet;
+ auto packet_str = packet.SerializeAsString();
+
+ ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
+}
+
+TEST_F(RedactProcessEventsTest, RejectMissingPacket) {
+ Context context;
+ context.package_uid = kUidA;
+ context.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ ASSERT_FALSE(redact_.Transform(context, nullptr).ok());
+}
+
+TEST_F(RedactProcessEventsTest, EmptyMissingPacket) {
+ Context context;
+ context.package_uid = kUidA;
+ context.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ std::string packet_str;
+
+ ASSERT_FALSE(redact_.Transform(context, &packet_str).ok());
+}
+
+// Tests which nested messages and fields are removed.
+class RedactNewTaskTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ auto* events = packet_.mutable_ftrace_events();
+ events->set_cpu(kCpu);
+
+ auto* event = events->add_event();
+ event->set_timestamp(kTimeB);
+ event->set_pid(kPidA);
+
+ auto* new_task = event->mutable_task_newtask();
+ new_task->set_clone_flags(0);
+ new_task->set_comm(std::string(kCommA));
+ new_task->set_oom_score_adj(0);
+ new_task->set_pid(kPidA);
+
+ // This test breaks the rules for task_newtask and the timeline. The
+ // timeline will report the task existing before the new task event. This
+ // should not happen in the field, but it makes the test more robust.
+
+ context_.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
+ context_.timeline->Sort();
+
+ redact_.emplace_modifier<DoNothing>();
+ redact_.emplace_filter<AllowAll>();
+ }
+
+ RedactProcessEvents redact_;
+ protos::gen::TracePacket packet_;
+ Context context_;
+};
+
+TEST_F(RedactNewTaskTest, KeepCommInPackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
+ // task.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_newtask());
+
+ const auto& new_task = event.task_newtask();
+
+ ASSERT_TRUE(new_task.has_pid());
+ ASSERT_EQ(new_task.pid(), kPidA);
+
+ ASSERT_TRUE(new_task.has_comm());
+ ASSERT_EQ(new_task.comm(), kCommA);
+}
+
+TEST_F(RedactNewTaskTest, ClearCommOutsidePackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; clear the
+ // comm.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_newtask());
+
+ const auto& new_task = event.task_newtask();
+
+ ASSERT_TRUE(new_task.has_pid());
+ ASSERT_EQ(new_task.pid(), kPidA);
+
+ ASSERT_TRUE(new_task.has_comm());
+ ASSERT_TRUE(new_task.comm().empty());
+}
+
+TEST_F(RedactNewTaskTest, KeepTaskInPackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
+ // task.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_newtask());
+
+ const auto& new_task = event.task_newtask();
+
+ ASSERT_TRUE(new_task.has_pid());
+ ASSERT_EQ(new_task.pid(), kPidA);
+}
+
+TEST_F(RedactNewTaskTest, DropTaskOutsidePackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop new
+ // task event.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ // The task should have been removed, but the event will still remain.
+ ASSERT_FALSE(packet.ftrace_events().event().at(0).has_task_newtask());
+}
+
+class RedactProcessFree : public testing::Test {
+ protected:
+ void SetUp() override {
+ auto* events = packet_.mutable_ftrace_events();
+ events->set_cpu(kCpu);
+
+ auto* event = events->add_event();
+ event->set_timestamp(kTimeB);
+ event->set_pid(kPidA);
+
+ auto* process_free = event->mutable_sched_process_free();
+ process_free->set_comm(std::string(kCommA));
+ process_free->set_pid(kPidA);
+ process_free->set_prio(0);
+
+ // By default, this timeline is invalid. sched_process_free would insert
+ // close events. If sched_process_free appended at time B a close event
+ // would be created at time B.
+ //
+ // Timeline spans are inclusive-start but exclusive-end, so a
+ // sched_process_free will never pass a "connected to package" test. The
+ // timeline is created to make testing easier.
+ //
+ // If a test wants a "valid" timeline, it should add a close event at
+ // sched_process_free.
+
+ context_.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
+ context_.timeline->Sort();
+
+ redact_.emplace_modifier<DoNothing>();
+ redact_.emplace_filter<AllowAll>();
+ }
+
+ RedactProcessEvents redact_;
+ protos::gen::TracePacket packet_;
+ Context context_;
+};
+
+TEST_F(RedactProcessFree, KeepsCommInPackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep comm.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_sched_process_free());
+
+ const auto& process_free = event.sched_process_free();
+
+ ASSERT_TRUE(process_free.has_pid());
+ ASSERT_EQ(process_free.pid(), kPidA);
+
+ ASSERT_TRUE(process_free.has_comm());
+ ASSERT_EQ(process_free.comm(), kCommA);
+}
+
+TEST_F(RedactProcessFree, DropsCommOutsidePackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop comm.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_sched_process_free());
+
+ const auto& process_free = event.sched_process_free();
+
+ ASSERT_TRUE(process_free.has_pid());
+ ASSERT_EQ(process_free.pid(), kPidA);
+
+ ASSERT_TRUE(process_free.has_comm());
+ ASSERT_TRUE(process_free.comm().empty());
+}
+
+TEST_F(RedactProcessFree, DropsCommAtProcessFree) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; But, Pid A
+ // ends at kTimeB (that's when the free event occurs). Drop comm.
+ context_.package_uid = kUidA;
+
+ context_.timeline->Append(ProcessThreadTimeline::Event::Close(kTimeB, kPidA));
+ context_.timeline->Sort();
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_sched_process_free());
+
+ const auto& process_free = event.sched_process_free();
+
+ ASSERT_TRUE(process_free.has_pid());
+ ASSERT_EQ(process_free.pid(), kPidA);
+
+ ASSERT_TRUE(process_free.has_comm());
+ ASSERT_TRUE(process_free.comm().empty());
+}
+
+TEST_F(RedactProcessFree, KeepTaskInPackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep new
+ // task.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_sched_process_free());
+
+ const auto& process_free = event.sched_process_free();
+
+ ASSERT_TRUE(process_free.has_pid());
+ ASSERT_EQ(process_free.pid(), kPidA);
+}
+
+TEST_F(RedactProcessFree, DropTaskOutsidePackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The new task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop new
+ // task event.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ // The task should have been removed, but the event will still remain.
+ ASSERT_FALSE(packet.ftrace_events().event().at(0).has_sched_process_free());
+}
+
+class RedactRenameTest : public testing::Test {
+ protected:
+ void SetUp() {
+ auto* events = packet_.mutable_ftrace_events();
+ events->set_cpu(kCpu);
+
+ auto* event = events->add_event();
+ event->set_timestamp(kTimeB);
+ event->set_pid(kPidA);
+
+ // The rename event pid will match the ftrace event pid.
+ auto* rename = event->mutable_task_rename();
+ rename->set_newcomm(std::string(kCommB));
+ rename->set_oldcomm(std::string(kCommA));
+ rename->set_pid(kPidA);
+ rename->set_oom_score_adj(0);
+
+ context_.timeline = std::make_unique<ProcessThreadTimeline>();
+
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidA, kNoParent, kUidA));
+ context_.timeline->Append(
+ ProcessThreadTimeline::Event::Open(kTimeA, kPidB, kNoParent, kUidB));
+ context_.timeline->Sort();
+
+ redact_.emplace_modifier<DoNothing>();
+ redact_.emplace_filter<AllowAll>();
+ }
+
+ RedactProcessEvents redact_;
+ protos::gen::TracePacket packet_;
+ Context context_;
+};
+
+TEST_F(RedactRenameTest, KeepCommInsidePackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep
+ // comm.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_rename());
+
+ const auto& task_rename = event.task_rename();
+
+ ASSERT_TRUE(task_rename.has_pid());
+ ASSERT_EQ(task_rename.pid(), kPidA);
+
+ ASSERT_TRUE(task_rename.has_oldcomm());
+ ASSERT_EQ(task_rename.oldcomm(), kCommA);
+
+ ASSERT_TRUE(task_rename.has_newcomm());
+ ASSERT_EQ(task_rename.newcomm(), kCommB);
+}
+
+TEST_F(RedactRenameTest, ClearCommOutsidePackage) {
+ redact_.emplace_modifier<ClearComms>();
+
+ // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop
+ // comm.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_rename());
+
+ const auto& task_rename = event.task_rename();
+
+ ASSERT_TRUE(task_rename.has_pid());
+ ASSERT_EQ(task_rename.pid(), kPidA);
+
+ ASSERT_TRUE(task_rename.has_oldcomm());
+ ASSERT_TRUE(task_rename.oldcomm().empty());
+
+ ASSERT_TRUE(task_rename.has_newcomm());
+ ASSERT_TRUE(task_rename.newcomm().empty());
+}
+
+TEST_F(RedactRenameTest, KeepTaskInsidePackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid A; keep
+ // comm.
+ context_.package_uid = kUidA;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_TRUE(event.has_task_rename());
+}
+
+TEST_F(RedactRenameTest, DropTaskOutsidePackage) {
+ redact_.emplace_filter<ConnectedToPackage>();
+
+ // The rename task is for Pid A. Pid A is part of Uid A. Keep Uid B; drop
+ // task.
+ context_.package_uid = kUidB;
+
+ auto packet_str = packet_.SerializeAsString();
+ ASSERT_OK(redact_.Transform(context_, &packet_str));
+
+ protos::gen::TracePacket packet;
+ ASSERT_TRUE(packet.ParseFromString(packet_str));
+
+ ASSERT_TRUE(packet.has_ftrace_events());
+ ASSERT_EQ(packet.ftrace_events().event().size(), 1u);
+
+ // The task should have been removed, but the event will still remain.
+ const auto& event = packet.ftrace_events().event().at(0);
+ ASSERT_FALSE(event.has_task_rename());
+}
+
+} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/redact_sched_events.h b/src/trace_redaction/redact_sched_events.h
index ace8219..d035fdd 100644
--- a/src/trace_redaction/redact_sched_events.h
+++ b/src/trace_redaction/redact_sched_events.h
@@ -64,7 +64,7 @@
// and easily implemented wrong.
virtual bool Includes(const Context& context,
uint64_t ts,
- int32_t wakee) const = 0;
+ int32_t target) const = 0;
};
class RedactSchedEvents : public TransformPrimitive {
diff --git a/src/trace_redaction/redact_task_newtask.cc b/src/trace_redaction/redact_task_newtask.cc
deleted file mode 100644
index 00c9d92..0000000
--- a/src/trace_redaction/redact_task_newtask.cc
+++ /dev/null
@@ -1,97 +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_redaction/redact_task_newtask.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/task.pbzero.h"
-#include "src/trace_processor/util/status_macros.h"
-
-namespace perfetto::trace_redaction {
-
-namespace {} // namespace
-// Redact sched switch trace events in an ftrace event bundle:
-//
-// event {
-// timestamp: 6702094133317685
-// pid: 6167
-// task_newtask {
-// pid: 7972
-// comm: "adbd"
-// clone_flags: 4001536
-// oom_score_adj: -1000
-// }
-// }
-//
-// In the above message, it should be noted that "event.pid" will never be
-// equal to "event.task_newtask.pid" (a thread cannot start itself).
-base::Status RedactTaskNewTask::Redact(
- const Context& context,
- const protos::pbzero::FtraceEventBundle::Decoder& bundle,
- protozero::ProtoDecoder& event,
- protos::pbzero::FtraceEvent* event_message) const {
- PERFETTO_DCHECK(modifier_);
-
- if (!context.package_uid.has_value()) {
- return base::ErrStatus("RedactTaskNewTask: missing package uid");
- }
-
- if (!context.timeline) {
- return base::ErrStatus("RedactTaskNewTask: missing timeline");
- }
-
- // The timestamp is needed to do the timeline look-up. If the packet has no
- // timestamp, don't add the sched switch event.
- auto timestamp_field =
- event.FindField(protos::pbzero::FtraceEvent::kTimestampFieldNumber);
- auto new_task_field =
- event.FindField(protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber);
-
- if (!timestamp_field.valid() || !new_task_field.valid()) {
- return base::ErrStatus(
- "RedactTaskNewTask: missing required FtraceEvent field.");
- }
-
- protos::pbzero::TaskNewtaskFtraceEvent::Decoder new_task(
- new_task_field.as_bytes());
-
- // There are only four fields in a new task event. Since two of them can
- // change, it is easier to work with them directly.
- if (!new_task.has_pid() || !new_task.has_comm() ||
- !new_task.has_clone_flags() || !new_task.has_oom_score_adj()) {
- return base::ErrStatus(
- "RedactTaskNewTask: missing required TaskNewtaskFtraceEvent field.");
- }
-
- auto pid = new_task.pid();
- auto comm = new_task.comm().ToStdString();
-
- auto cpu = static_cast<int32_t>(bundle.cpu());
-
- RETURN_IF_ERROR(modifier_->Modify(context, timestamp_field.as_uint64(), cpu,
- &pid, &comm));
-
- auto* new_task_message = event_message->set_task_newtask();
- new_task_message->set_pid(pid);
- new_task_message->set_comm(comm);
- new_task_message->set_clone_flags(new_task.clone_flags());
- new_task_message->set_oom_score_adj(new_task.oom_score_adj());
-
- return base::OkStatus();
-}
-
-} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/redact_task_newtask.h b/src/trace_redaction/redact_task_newtask.h
deleted file mode 100644
index b162a9b..0000000
--- a/src/trace_redaction/redact_task_newtask.h
+++ /dev/null
@@ -1,50 +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_REDACTION_REDACT_TASK_NEWTASK_H_
-#define SRC_TRACE_REDACTION_REDACT_TASK_NEWTASK_H_
-
-#include "src/trace_redaction/redact_ftrace_event.h"
-#include "src/trace_redaction/redact_sched_events.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-
-namespace perfetto::trace_redaction {
-
-// Goes through ftrace events and conditonally removes the comm values from
-// task_newtask events.
-class RedactTaskNewTask : public FtraceEventRedaction {
- public:
- static constexpr auto kFieldId =
- protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber;
-
- base::Status Redact(
- const Context& context,
- const protos::pbzero::FtraceEventBundle::Decoder& bundle,
- protozero::ProtoDecoder& event,
- protos::pbzero::FtraceEvent* event_message) const override;
-
- template <class Modifier>
- void emplace_back() {
- modifier_ = std::make_unique<Modifier>();
- }
-
- public:
- std::unique_ptr<SchedEventModifier> modifier_;
-};
-
-} // namespace perfetto::trace_redaction
-
-#endif // SRC_TRACE_REDACTION_REDACT_TASK_NEWTASK_H_
diff --git a/src/trace_redaction/redact_task_newtask_unittest.cc b/src/trace_redaction/redact_task_newtask_unittest.cc
deleted file mode 100644
index 11b1405..0000000
--- a/src/trace_redaction/redact_task_newtask_unittest.cc
+++ /dev/null
@@ -1,163 +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_redaction/redact_task_newtask.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/base/test/status_matchers.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
-#include "protos/perfetto/trace/ftrace/task.gen.h"
-#include "protos/perfetto/trace/trace.gen.h"
-#include "protos/perfetto/trace/trace_packet.gen.h"
-
-namespace perfetto::trace_redaction {
-
-namespace {
-constexpr uint64_t kCpu = 1;
-
-constexpr uint64_t kUidA = 1;
-constexpr uint64_t kUidB = 2;
-
-constexpr int32_t kNoParent = 10;
-constexpr int32_t kPidA = 11;
-constexpr int32_t kPidB = 12;
-
-constexpr std::string_view kCommA = "comm-a";
-
-} // namespace
-
-// Tests which nested messages and fields are removed.
-class RedactTaskNewTaskTest : public testing::Test {
- protected:
- void SetUp() override {
- bundle_.set_cpu(kCpu);
-
- auto* event = bundle_.add_event();
- event->set_timestamp(123456789);
- event->set_pid(kPidA);
-
- auto* new_task = event->mutable_task_newtask();
- new_task->set_clone_flags(0);
- new_task->set_comm(std::string(kCommA));
- new_task->set_oom_score_adj(0);
- new_task->set_pid(kPidA);
- }
-
- base::Status Redact(const Context& context,
- protos::pbzero::FtraceEvent* event_message) {
- RedactTaskNewTask redact;
- redact.emplace_back<ClearComms>();
-
- auto bundle_str = bundle_.SerializeAsString();
- protos::pbzero::FtraceEventBundle::Decoder bundle_decoder(bundle_str);
-
- auto event_str = bundle_.event().back().SerializeAsString();
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_str);
-
- return redact.Redact(context, bundle_decoder, event_decoder, event_message);
- }
-
- const std::string& event_string() const { return event_string_; }
-
- // This test breaks the rules for task_newtask and the timeline. The
- // timeline will report the task existing before the new task event. This
- // should not happen in the field, but it makes the test more robust.
- std::unique_ptr<ProcessThreadTimeline> CreatePopulatedTimeline() {
- auto timeline = std::make_unique<ProcessThreadTimeline>();
-
- timeline->Append(
- ProcessThreadTimeline::Event::Open(0, kPidA, kNoParent, kUidA));
- timeline->Append(
- ProcessThreadTimeline::Event::Open(0, kPidB, kNoParent, kUidB));
- timeline->Sort();
-
- return timeline;
- }
-
- private:
- std::string event_string_;
-
- std::unique_ptr<ProcessThreadTimeline> timeline_;
-
- protos::gen::FtraceEventBundle bundle_;
-};
-
-TEST_F(RedactTaskNewTaskTest, RejectMissingPackageUid) {
- Context context;
- context.timeline = std::make_unique<ProcessThreadTimeline>();
-
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_string());
- protozero::HeapBuffered<protos::pbzero::FtraceEvent> event_message;
-
- auto result = Redact(context, event_message.get());
- ASSERT_FALSE(result.ok());
-}
-
-TEST_F(RedactTaskNewTaskTest, RejectMissingTimeline) {
- Context context;
- context.package_uid = kUidA;
-
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_string());
- protozero::HeapBuffered<protos::pbzero::FtraceEvent> event_message;
-
- auto result = Redact(context, event_message.get());
- ASSERT_FALSE(result.ok());
-}
-
-TEST_F(RedactTaskNewTaskTest, PidInPackageKeepsComm) {
- // Because Uid A is the target, when Pid A starts (new task event), it should
- // keep its comm value.
- Context context;
- context.package_uid = kUidA;
- context.timeline = CreatePopulatedTimeline();
-
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_string());
- protozero::HeapBuffered<protos::pbzero::FtraceEvent> event_message;
-
- ASSERT_OK(Redact(context, event_message.get()));
-
- protos::gen::FtraceEvent redacted_event;
- redacted_event.ParseFromString(event_message.SerializeAsString());
-
- ASSERT_TRUE(redacted_event.has_task_newtask());
- ASSERT_TRUE(redacted_event.task_newtask().has_comm());
- ASSERT_EQ(redacted_event.task_newtask().comm(), kCommA);
-}
-
-TEST_F(RedactTaskNewTaskTest, PidOutsidePackageLosesComm) {
- // Because Uid B is the target, when Pid A starts (new task event), it should
- // lose its comm value.
- Context context;
- context.package_uid = kUidB;
- context.timeline = CreatePopulatedTimeline();
-
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_string());
- protozero::HeapBuffered<protos::pbzero::FtraceEvent> event_message;
-
- ASSERT_OK(Redact(context, event_message.get()));
-
- protos::gen::FtraceEvent redacted_event;
- redacted_event.ParseFromString(event_message.SerializeAsString());
-
- ASSERT_TRUE(redacted_event.has_task_newtask());
- ASSERT_TRUE(redacted_event.task_newtask().has_comm());
- ASSERT_TRUE(redacted_event.task_newtask().comm().empty());
-}
-
-} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/remove_process_free_comm.cc b/src/trace_redaction/remove_process_free_comm.cc
deleted file mode 100644
index 88ed22a..0000000
--- a/src/trace_redaction/remove_process_free_comm.cc
+++ /dev/null
@@ -1,59 +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_redaction/remove_process_free_comm.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-
-namespace perfetto::trace_redaction {
-
-base::Status RemoveProcessFreeComm::Redact(
- const Context&,
- const protos::pbzero::FtraceEventBundle::Decoder&,
- protozero::ProtoDecoder& event,
- protos::pbzero::FtraceEvent* event_message) const {
- auto sched_process_free = event.FindField(
- protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber);
- if (!sched_process_free.valid()) {
- return base::ErrStatus("RemoveProcessFreeComm: missing required field.");
- }
-
- // SchedProcessFreeFtraceEvent
- protozero::ProtoDecoder decoder(sched_process_free.as_bytes());
-
- auto pid_field = decoder.FindField(
- protos::pbzero::SchedProcessFreeFtraceEvent::kPidFieldNumber);
- auto prio_field = decoder.FindField(
- protos::pbzero::SchedProcessFreeFtraceEvent::kPrioFieldNumber);
-
- if (!pid_field.valid() || !prio_field.valid()) {
- return base::ErrStatus("RemoveProcessFreeComm: missing required field.");
- }
-
- auto* message = event_message->set_sched_process_free();
-
- // Replace the comm with an empty string instead of dropping the comm field.
- // The perfetto UI doesn't render things correctly if comm values are missing.
- message->set_comm("");
- message->set_pid(pid_field.as_int32());
- message->set_prio(prio_field.as_int32());
-
- return base::OkStatus();
-}
-
-} // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/remove_process_free_comm.h b/src/trace_redaction/remove_process_free_comm.h
deleted file mode 100644
index f3dc0d9..0000000
--- a/src/trace_redaction/remove_process_free_comm.h
+++ /dev/null
@@ -1,44 +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_REDACTION_REMOVE_PROCESS_FREE_COMM_H_
-#define SRC_TRACE_REDACTION_REMOVE_PROCESS_FREE_COMM_H_
-
-#include "src/trace_redaction/redact_ftrace_event.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-
-namespace perfetto::trace_redaction {
-
-// Process free events will always end up testing positive for "remove comm
-// value", so instead of running the test, always remove the comm value. We know
-// it would fail the test because process free events create close events on the
-// timeline. Because the timeline uses exclusive ends, the event's time will
-// never call within the range it belongs to.
-class RemoveProcessFreeComm : public FtraceEventRedaction {
- public:
- static constexpr auto kFieldId =
- protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber;
-
- base::Status Redact(
- const Context& context,
- const protos::pbzero::FtraceEventBundle::Decoder& bundle,
- protozero::ProtoDecoder& event,
- protos::pbzero::FtraceEvent* event_message) const override;
-};
-
-} // namespace perfetto::trace_redaction
-
-#endif // SRC_TRACE_REDACTION_REMOVE_PROCESS_FREE_COMM_H_
diff --git a/src/trace_redaction/remove_process_free_comm_unittest.cc b/src/trace_redaction/remove_process_free_comm_unittest.cc
deleted file mode 100644
index 5999a4a..0000000
--- a/src/trace_redaction/remove_process_free_comm_unittest.cc
+++ /dev/null
@@ -1,80 +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_redaction/remove_process_free_comm.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/base/test/status_matchers.h"
-#include "src/trace_redaction/trace_redaction_framework.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
-#include "protos/perfetto/trace/ftrace/sched.gen.h"
-#include "protos/perfetto/trace/trace.gen.h"
-#include "protos/perfetto/trace/trace_packet.gen.h"
-
-namespace perfetto::trace_redaction {
-
-class RemoveProcessFreeCommTest : public testing::Test {
- protected:
- void SetUp() override {
- auto* source_event = bundle.add_event();
- source_event->set_timestamp(123456789);
- source_event->set_pid(10);
-
- process_free = source_event->mutable_sched_process_free();
- }
-
- base::Status Redact(protos::pbzero::FtraceEvent* event_message) {
- RemoveProcessFreeComm redact;
- Context context;
-
- auto bundle_str = bundle.SerializeAsString();
- protos::pbzero::FtraceEventBundle::Decoder bundle_decoder(bundle_str);
-
- auto event_str = bundle.event().back().SerializeAsString();
- protos::pbzero::FtraceEvent::Decoder event_decoder(event_str);
-
- return redact.Redact(context, bundle_decoder, event_decoder, event_message);
- }
-
- protos::gen::FtraceEventBundle bundle;
- protos::gen::SchedProcessFreeFtraceEvent* process_free;
-};
-
-// A free event will always test as "not active". So the comm value should
-// always be replaced with an empty string.
-TEST_F(RemoveProcessFreeCommTest, ClearsCommValue) {
- process_free->set_comm("comm-a");
- process_free->set_pid(11);
- process_free->set_prio(0);
-
- protozero::HeapBuffered<protos::pbzero::FtraceEvent> event_message;
-
- ASSERT_OK(Redact(event_message.get()));
-
- protos::gen::FtraceEvent redacted_event;
- redacted_event.ParseFromString(event_message.SerializeAsString());
-
- // No process free event should have been added to the ftrace event.
- ASSERT_TRUE(redacted_event.has_sched_process_free());
- ASSERT_TRUE(redacted_event.sched_process_free().has_comm());
- ASSERT_TRUE(redacted_event.sched_process_free().comm().empty());
-}
-
-} // namespace perfetto::trace_redaction