1 /* 2 * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_ 18 #define INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_ 19 20 #include <stddef.h> 21 22 #include <memory> 23 #include <tuple> 24 25 #include "google/protobuf/io/zero_copy_stream.h" 26 #include "perfetto/base/export.h" 27 #include "perfetto/base/logging.h" 28 #include "perfetto/tracing/core/slice.h" 29 30 namespace perfetto { 31 32 namespace protos { 33 class TracePacket; // From protos/trace_packet.pb.h. 34 } // namespace protos 35 36 // A wrapper around a byte buffer that contains a protobuf-encoded TracePacket 37 // (see trace_packet.proto). The TracePacket is decoded only if the Consumer 38 // requests that. This is to allow Consumer(s) to just stream the packet over 39 // the network or save it to a file without wasting time decoding it and without 40 // needing to depend on libprotobuf or the trace_packet.pb.h header. 41 // If the packets are saved / streamed and not just consumed locally, consumers 42 // should ensure to preserve the unknown fields in the proto. A consumer, in 43 // fact, might have an older version .proto which is newer on the producer. 44 class PERFETTO_EXPORT TracePacket { 45 public: 46 using const_iterator = Slices::const_iterator; 47 using ZeroCopyInputStream = ::google::protobuf::io::ZeroCopyInputStream; 48 49 // The field id of protos::Trace::packet, static_assert()-ed in the unittest. 50 static constexpr uint32_t kPacketFieldNumber = 1; 51 52 TracePacket(); 53 ~TracePacket(); 54 TracePacket(TracePacket&&) noexcept; 55 TracePacket& operator=(TracePacket&&); 56 57 // Accesses all the raw slices in the packet, for saving them to file/network. slices()58 const Slices& slices() const { return slices_; } 59 60 // Decodes the packet. This function requires that the caller: 61 // 1) Does #include "perfetto/trace/trace_packet.pb.h" 62 // 2) Links against the //protos/trace:lite target. 63 // The core service code deliberately doesn't link against that in order to 64 // avoid binary bloat. This is the reason why this is a templated function. 65 // It doesn't need to be (i.e. the caller should not specify the template 66 // argument) but doing so prevents the compiler trying to resolve the 67 // TracePacket type until it's needed, in which case the caller needs (1). 68 template <typename TracePacketType = protos::TracePacket> Decode(TracePacketType * packet)69 bool Decode(TracePacketType* packet) const { 70 std::unique_ptr<ZeroCopyInputStream> istr = CreateSlicedInputStream(); 71 return packet->ParseFromZeroCopyStream(istr.get()); 72 } 73 74 // Mutator, used only by the service and tests. 75 void AddSlice(Slice); 76 77 // Does not copy / take ownership of the memory of the slice. The TracePacket 78 // will be valid only as long as the original buffer is valid. 79 void AddSlice(const void* start, size_t size); 80 81 // Total size of all slices. size()82 size_t size() const { return size_; } 83 84 // Generates a protobuf preamble suitable to represent this packet as a 85 // repeated field within a root trace.proto message. 86 // Returns a pointer to a buffer, owned by this class, containing the preamble 87 // and its size. 88 std::tuple<char*, size_t> GetProtoPreamble(); 89 90 private: 91 TracePacket(const TracePacket&) = delete; 92 TracePacket& operator=(const TracePacket&) = delete; 93 94 std::unique_ptr<ZeroCopyInputStream> CreateSlicedInputStream() const; 95 96 Slices slices_; // Not owned. 97 size_t size_ = 0; // SUM(slice.size for slice in slices_). 98 char preamble_[8]; // Deliberately not initialized. 99 100 // Remember to update the move operators and their unittest if adding new 101 // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on 102 // std::move(TracePacket) to clear up the moved-from instance. 103 }; 104 105 } // namespace perfetto 106 107 #endif // INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_ 108