| /* |
| * 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_TRACE_REDACTION_FRAMEWORK_H_ |
| #define SRC_TRACE_REDACTION_TRACE_REDACTION_FRAMEWORK_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "perfetto/ext/base/status_or.h" |
| #include "protos/perfetto/trace/trace_packet.gen.h" |
| #include "protos/perfetto/trace/trace_packet.pbzero.h" |
| |
| namespace perfetto::trace_redaction { |
| |
| // Multiple packages can share the same name. This is common when a device has |
| // multiple users. When this happens, each instance shares the 5 least |
| // significant digits. |
| constexpr uint64_t NormalizeUid(uint64_t uid) { |
| return uid % 1000000; |
| } |
| |
| // Primitives should be stateless. All state should be stored in the context. |
| // Primitives should depend on data in the context, not the origin of the data. |
| // This allows primitives to be swapped out or work together to populate data |
| // needed by another primitive. |
| // |
| // For this to work, primitives are divided into three types: |
| // |
| // `CollectPrimitive` : Reads data from trace packets and saves low-level data |
| // in the context. |
| // |
| // `BuildPrimitive` : Reads low-level data from the context and builds |
| // high-level (read-optimized) data structures. |
| // |
| // `TransformPrimitive`: Reads high-level data from the context and modifies |
| // trace packets. |
| class Context { |
| public: |
| // The package that should not be redacted. This must be populated before |
| // running any primitives. |
| std::string package_name; |
| |
| // The package list maps a package name to a uid. It is possible for multiple |
| // package names to map to the same uid, for example: |
| // |
| // packages { |
| // name: "com.google.android.gms" |
| // uid: 10113 |
| // debuggable: false |
| // profileable_from_shell: false |
| // version_code: 235013038 |
| // } |
| // packages { |
| // name: "com.google.android.gsf" |
| // uid: 10113 |
| // debuggable: false |
| // profileable_from_shell: false |
| // version_code: 34 |
| // } |
| // |
| // The process tree maps processes to packages via the uid value. However |
| // multiple processes can map to the same uid, only differed by some multiple |
| // of 100000, for example: |
| // |
| // processes { |
| // pid: 18176 |
| // ppid: 904 |
| // cmdline: "com.google.android.gms.persistent" |
| // uid: 10113 |
| // } |
| // processes { |
| // pid: 21388 |
| // ppid: 904 |
| // cmdline: "com.google.android.gms.persistent" |
| // uid: 1010113 |
| // } |
| std::optional<uint64_t> package_uid; |
| }; |
| |
| // Responsible for extracting low-level data from the trace and storing it in |
| // the context. |
| class CollectPrimitive { |
| public: |
| // When a collect primitive has collected all necessary information, it can |
| // stop processing packets by returning kRetire. If the primitives wants to |
| // continue processing packets, it will return kNextPacket. |
| // |
| // If a collector encounters an unrecoverable error, base::ErrStatus() is |
| // returned. |
| enum class ContinueCollection : bool { kRetire = false, kNextPacket = true }; |
| |
| virtual ~CollectPrimitive(); |
| |
| // Processes a packet and writes low-level data to the context. Returns |
| // kContinue if the primitive wants more data (i.e. next packet). |
| virtual base::StatusOr<ContinueCollection> Collect( |
| const protos::pbzero::TracePacket::Decoder& packet, |
| Context* context) const = 0; |
| }; |
| |
| // Responsible for converting low-level data from the context and storing it in |
| // the context (high-level data). |
| class BuildPrimitive { |
| public: |
| virtual ~BuildPrimitive(); |
| |
| // Reads low-level data from the context and writes high-level data to the |
| // context. |
| virtual base::Status Build(Context* context) const = 0; |
| }; |
| |
| // Responsible for modifying trace packets using data from the context. |
| class TransformPrimitive { |
| public: |
| virtual ~TransformPrimitive(); |
| |
| // Modifies a packet using data from the context. |
| virtual base::Status Transform(const Context& context, |
| std::string* packet) const = 0; |
| }; |
| |
| } // namespace perfetto::trace_redaction |
| |
| #endif // SRC_TRACE_REDACTION_TRACE_REDACTION_FRAMEWORK_H_ |