xref: /aosp_15_r20/external/perfetto/src/trace_redaction/scrub_process_stats.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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