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 #ifndef SRC_TRACE_REDACTION_PROCESS_THREAD_TIMELINE_H_ 18 #define SRC_TRACE_REDACTION_PROCESS_THREAD_TIMELINE_H_ 19 20 #include <cstdint> 21 #include <limits> 22 #include <vector> 23 24 namespace perfetto::trace_redaction { 25 26 class ProcessThreadTimeline { 27 public: 28 // Opened and closed events are used to mark the start and end of lifespans. 29 struct Event { 30 public: 31 static constexpr auto kUnknownPid = std::numeric_limits<int32_t>::max(); 32 static constexpr auto kUnknownUid = std::numeric_limits<uint64_t>::max(); 33 34 enum class Type { kInvalid, kOpen, kClose }; 35 36 bool operator==(const Event& o) const { 37 switch (type) { 38 case Type::kOpen: 39 return o.type == Type::kOpen && ts == o.ts && pid == o.pid && 40 ppid == o.ppid && uid == o.uid; 41 42 case Type::kClose: 43 return o.type == Type::kClose && ts == o.ts && pid == o.pid; 44 45 case Type::kInvalid: 46 return o.type == Type::kInvalid; 47 } 48 49 return false; 50 } 51 52 bool operator!=(const Event& o) const { return !(*this == o); } 53 validEvent54 bool valid() const { return type != Type::kInvalid; } 55 OpenEvent56 static Event Open(uint64_t ts, int32_t pid, int32_t ppid, uint64_t uid) { 57 return {Type::kOpen, ts, pid, ppid, uid}; 58 } 59 OpenEvent60 static Event Open(uint64_t ts, int32_t pid, int32_t ppid) { 61 return {Type::kOpen, ts, pid, ppid, kUnknownUid}; 62 } 63 CloseEvent64 static Event Close(uint64_t ts, int32_t pid) { 65 return {Type::kClose, ts, pid, kUnknownPid, kUnknownUid}; 66 } 67 68 Type type = Type::kInvalid; 69 70 // The time when the event occured. Undefined when type is kInvalid. 71 uint64_t ts = 0; 72 73 // The subject of the event. Undefined when type is kInvalid. 74 int32_t pid = kUnknownPid; 75 76 // The parent of the subject. kUnknownPid if the parent is unknown. 77 // Undefined when type is kClose or kInvalid. 78 int32_t ppid = kUnknownPid; 79 80 // The package containing the subject. kUnknownUid if the package is 81 // unknown. Undefined when type is kClose or kInvalid. 82 uint64_t uid = kUnknownUid; 83 }; 84 85 ProcessThreadTimeline() = default; 86 87 ProcessThreadTimeline(const ProcessThreadTimeline&) = delete; 88 ProcessThreadTimeline& operator=(const ProcessThreadTimeline&) = delete; 89 ProcessThreadTimeline(ProcessThreadTimeline&&) = delete; 90 ProcessThreadTimeline& operator=(ProcessThreadTimeline&&) = delete; 91 92 void Append(const Event& event); 93 94 // REQUIRED: Sorts all events by pid, making it possible to locate the subset 95 // of events connected to a pid. Events are not sorted by time because the 96 // subset of events will, on average, be trivally small. 97 void Sort(); 98 99 // Returns true if a process/thread is connected to a package. 100 bool PidConnectsToUid(uint64_t ts, int32_t pid, uint64_t uid) const; 101 102 // Get the opening event for a pid. If pid ends at ts, an opening event will 103 // still be returned. 104 const Event* GetOpeningEvent(uint64_t ts, int32_t pid) const; 105 106 // SELECT MAX(ts), * FROM events WHERE pid=@pid AND type=@type AND ts<=@ts 107 const Event* QueryLeftMax(uint64_t ts, 108 int32_t pid, 109 ProcessThreadTimeline::Event::Type type) const; 110 111 private: 112 enum class Mode { 113 // The timeline can safely be queried. If the timeline is in read mode, and 114 // a user writes to the timeline, the timeline will change to write mode. 115 kRead, 116 117 // The timeline change be changed. If the timeline is not in write mode, 118 // reading from the timeline will throw an error. Sort() must be called to 119 // change the timeline from write to read mode. 120 kWrite 121 }; 122 123 std::vector<Event> events_; 124 125 Mode mode_ = Mode::kRead; 126 }; 127 128 } // namespace perfetto::trace_redaction 129 130 #endif // SRC_TRACE_REDACTION_PROCESS_THREAD_TIMELINE_H_ 131