/* * Copyright (C) 2020 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. */ #include "perfetto/tracing/internal/interceptor_trace_writer.h" #include "perfetto/ext/tracing/core/trace_writer.h" namespace perfetto { namespace internal { // static std::atomic InterceptorTraceWriter::next_sequence_id_{}; InterceptorTraceWriter::InterceptorTraceWriter( std::unique_ptr tls, InterceptorBase::TracePacketCallback packet_callback, DataSourceStaticState* static_state, uint32_t instance_index) : tls_(std::move(tls)), packet_callback_(std::move(packet_callback)), static_state_(static_state), instance_index_(instance_index), sequence_id_(++next_sequence_id_) {} InterceptorTraceWriter::~InterceptorTraceWriter() = default; protozero::MessageHandle InterceptorTraceWriter::NewTracePacket() { Flush(); auto packet = TraceWriter::TracePacketHandle(cur_packet_.get()); packet->set_trusted_packet_sequence_id(sequence_id_); return packet; } void InterceptorTraceWriter::Flush(std::function callback) { if (!cur_packet_.empty()) { InterceptorBase::TracePacketCallbackArgs args{}; args.static_state = static_state_; args.instance_index = instance_index_; args.tls = tls_.get(); const auto& slices = cur_packet_.GetSlices(); if (slices.size() == 1) { // Fast path: the current packet fits into a single slice. auto slice_range = slices.begin()->GetUsedRange(); args.packet_data = protozero::ConstBytes{ slice_range.begin, static_cast(slice_range.end - slice_range.begin)}; bytes_written_ += static_cast(args.packet_data.size); packet_callback_(std::move(args)); } else { // Fallback: stitch together multiple slices. auto stitched_data = cur_packet_.SerializeAsArray(); args.packet_data = protozero::ConstBytes{stitched_data.data(), stitched_data.size()}; bytes_written_ += static_cast(stitched_data.size()); packet_callback_(std::move(args)); } cur_packet_.Reset(); } if (callback) callback(); } uint64_t InterceptorTraceWriter::written() const { return bytes_written_; } } // namespace internal } // namespace perfetto