1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_redaction/scrub_process_stats.h"
18
19 #include <string>
20
21 #include "perfetto/base/status.h"
22 #include "perfetto/protozero/field.h"
23 #include "perfetto/protozero/scattered_heap_buffer.h"
24 #include "src/trace_processor/util/status_macros.h"
25 #include "src/trace_redaction/proto_util.h"
26 #include "src/trace_redaction/trace_redaction_framework.h"
27
28 #include "protos/perfetto/trace/ps/process_stats.pbzero.h"
29
30 namespace perfetto::trace_redaction {
31
Transform(const Context & context,std::string * packet) const32 base::Status ScrubProcessStats::Transform(const Context& context,
33 std::string* packet) const {
34 if (!context.package_uid.has_value()) {
35 return base::ErrStatus("FilterProcessStats: missing package uid.");
36 }
37
38 if (!context.timeline) {
39 return base::ErrStatus("FilterProcessStats: missing timeline.");
40 }
41
42 protozero::ProtoDecoder packet_decoder(*packet);
43
44 // Very few packets will have process stats. It's best to avoid
45 // reserialization whenever possible.
46 if (!packet_decoder
47 .FindField(protos::pbzero::TracePacket::kProcessStatsFieldNumber)
48 .valid()) {
49 return base::OkStatus();
50 }
51
52 protozero::HeapBuffered<protos::pbzero::TracePacket> message;
53
54 // Not all packets will have a top-level timestamp, but for process stats, the
55 // timestamp is located at the trace packet.
56 auto time_field = packet_decoder.FindField(
57 protos::pbzero::TracePacket::kTimestampFieldNumber);
58 PERFETTO_DCHECK(time_field.valid());
59
60 auto ts = time_field.as_uint64();
61
62 for (auto field = packet_decoder.ReadField(); field.valid();
63 field = packet_decoder.ReadField()) {
64 if (field.id() == protos::pbzero::TracePacket::kProcessStatsFieldNumber) {
65 RETURN_IF_ERROR(OnProcessStats(context, ts, field.as_bytes(),
66 message->set_process_stats()));
67 } else {
68 proto_util::AppendField(field, message.get());
69 }
70 }
71
72 packet->assign(message.SerializeAsString());
73
74 return base::OkStatus();
75 }
76
OnProcessStats(const Context & context,uint64_t ts,protozero::ConstBytes bytes,protos::pbzero::ProcessStats * message) const77 base::Status ScrubProcessStats::OnProcessStats(
78 const Context& context,
79 uint64_t ts,
80 protozero::ConstBytes bytes,
81 protos::pbzero::ProcessStats* message) const {
82 protozero::ProtoDecoder decoder(bytes);
83
84 for (auto field = decoder.ReadField(); field.valid();
85 field = decoder.ReadField()) {
86 if (field.id() == protos::pbzero::ProcessStats::kProcessesFieldNumber) {
87 RETURN_IF_ERROR(OnProcess(context, ts, field, message));
88 } else {
89 proto_util::AppendField(field, message);
90 }
91 }
92
93 return base::OkStatus();
94 }
95
OnProcess(const Context & context,uint64_t ts,protozero::Field field,protos::pbzero::ProcessStats * message) const96 base::Status ScrubProcessStats::OnProcess(
97 const Context& context,
98 uint64_t ts,
99 protozero::Field field,
100 protos::pbzero::ProcessStats* message) const {
101 PERFETTO_DCHECK(field.id() ==
102 protos::pbzero::ProcessStats::kProcessesFieldNumber);
103
104 protozero::ProtoDecoder decoder(field.as_bytes());
105 auto pid =
106 decoder.FindField(protos::pbzero::ProcessStats::Process::kPidFieldNumber);
107 PERFETTO_DCHECK(pid.valid());
108
109 PERFETTO_DCHECK(filter_);
110 if (filter_->Includes(context, ts, pid.as_int32())) {
111 proto_util::AppendField(field, message);
112 }
113
114 return base::OkStatus();
115 }
116
117 } // namespace perfetto::trace_redaction
118