blob: f013a2759c792a76abc7d20d8a2058032f47700f [file] [edit]
/*
* Copyright (C) 2025 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 "src/tracing/service/tracing_service_session.h"
#include "protos/perfetto/trace/perfetto/tracing_service_event.pbzero.h"
#include "src/protozero/filtering/message_filter.h"
#include "src/tracing/service/trace_buffer.h"
#include "src/tracing/service/tracing_service_endpoints_impl.h"
namespace perfetto::tracing_service {
TracingSession::TracingSession(TracingSessionID session_id,
ConsumerEndpointImpl* consumer,
const TraceConfig& new_config,
base::TaskRunner* task_runner)
: id(session_id),
consumer_maybe_null(consumer),
consumer_uid(consumer->uid_),
config(new_config),
snapshot_periodic_task(task_runner),
timed_stop_task(task_runner) {
// all_data_sources_flushed (and flush_started) is special because we store up
// to 64 events of this type. Other events will go through the default case in
// SnapshotLifecycleEvent() where they will be given a max history of 1.
lifecycle_events.emplace_back(
protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
64 /* max_size */);
lifecycle_events.emplace_back(
protos::pbzero::TracingServiceEvent::kFlushStartedFieldNumber,
64 /* max_size */);
}
bool TracingSession::IsCloneAllowed(uid_t clone_uid) const {
if (clone_uid == 0)
return true; // Root is always allowed to clone everything.
if (clone_uid == this->consumer_uid)
return true; // Allow cloning if the uids match.
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
// On Android allow shell to clone sessions marked as exported for bugreport.
// Dumpstate (invoked by adb bugreport) invokes commands as shell.
if (clone_uid == AID_SHELL && this->config.bugreport_score() > 0)
return true;
#endif
return false;
}
PacketSequenceID TracingSession::GetPacketSequenceID(MachineID machine_id,
ProducerID producer_id,
WriterID writer_id) {
auto key = std::make_tuple(machine_id, producer_id, writer_id);
auto it = packet_sequence_ids.find(key);
if (it != packet_sequence_ids.end())
return it->second;
// We shouldn't run out of sequence IDs (producer ID is 16 bit, writer IDs
// are limited to 1024).
static_assert(kMaxPacketSequenceID > kMaxProducerID * kMaxWriterID,
"PacketSequenceID value space doesn't cover service "
"sequence ID and all producer/writer ID combinations!");
PERFETTO_DCHECK(last_packet_sequence_id < kMaxPacketSequenceID);
PacketSequenceID sequence_id = ++last_packet_sequence_id;
packet_sequence_ids[key] = sequence_id;
return sequence_id;
}
DataSourceInstance* TracingSession::GetDataSourceInstance(
ProducerID producer_id,
DataSourceInstanceID instance_id) {
for (auto& inst_kv : data_source_instances) {
if (inst_kv.first != producer_id ||
inst_kv.second.instance_id != instance_id) {
continue;
}
return &inst_kv.second;
}
return nullptr;
}
bool TracingSession::AllDataSourceInstancesStarted() {
return std::all_of(data_source_instances.begin(), data_source_instances.end(),
[](decltype(data_source_instances)::const_reference x) {
return x.second.state == DataSourceInstance::STARTED;
});
}
bool TracingSession::AllDataSourceInstancesStopped() {
return std::all_of(data_source_instances.begin(), data_source_instances.end(),
[](decltype(data_source_instances)::const_reference x) {
return x.second.state == DataSourceInstance::STOPPED;
});
}
void TracingSession::AddConcurrentSessionEventWithLimit(
const TracingSession& src) {
static constexpr size_t kMaxConcurrentSessionEvents = 4096;
if (concurrent_session_events.size() >= kMaxConcurrentSessionEvents)
return;
ConcurrentSessionEvent event{};
event.timestamp = src.current_state_start_ns;
event.session_id = src.id;
event.state = src.state;
event.consumer_uid = src.consumer_uid;
event.num_data_sources =
static_cast<uint32_t>(src.data_source_instances.size());
event.name = src.config.unique_session_name();
concurrent_session_events.emplace_back(std::move(event));
}
} // namespace perfetto::tracing_service