blob: dcb2a911f7e5ba208735248696a6abdc009eb796 [file]
/*
* 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.
*/
#ifndef SRC_TRACING_SERVICE_TRACING_SERVICE_ENDPOINTS_IMPL_H_
#define SRC_TRACING_SERVICE_TRACING_SERVICE_ENDPOINTS_IMPL_H_
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "perfetto/ext/base/circular_queue.h"
#include "perfetto/ext/base/clock_snapshots.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_checker.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/base/weak_runner.h"
#include "perfetto/ext/tracing/core/client_identity.h"
#include "perfetto/ext/tracing/core/observable_events.h"
#include "perfetto/ext/tracing/core/shared_memory_abi.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
#include "perfetto/tracing/core/forward_decls.h"
// This header contains the declarations for the 3 abtract classes
// (ProducerEndpointImpl, ConsumerEndpointImpl, RelayEndpointImpl).
// These classes are the concrete implementation backed by TracingServiceImpl
// and override the base interfaces defined at the API level (other
// implementations exists in the various IPC layers to stub-out the calls).
namespace perfetto {
class SharedMemoryArbiterImpl;
namespace tracing_service {
class TracingServiceImpl;
struct DataSourceInstance;
struct TracingSession;
struct TriggerInfo;
// The implementation behind the service endpoint exposed to each producer.
class ProducerEndpointImpl : public TracingService::ProducerEndpoint {
public:
ProducerEndpointImpl(ProducerID,
const ClientIdentity& client_identity,
TracingServiceImpl*,
base::TaskRunner*,
Producer*,
const std::string& producer_name,
const std::string& machine_name,
const std::string& sdk_version,
bool in_process,
bool smb_scraping_enabled);
~ProducerEndpointImpl() override;
// TracingService::ProducerEndpoint implementation.
void Disconnect() override;
void RegisterDataSource(const DataSourceDescriptor&) override;
void UpdateDataSource(const DataSourceDescriptor&) override;
void UnregisterDataSource(const std::string& name) override;
void RegisterTraceWriter(uint32_t writer_id, uint32_t target_buffer) override;
void UnregisterTraceWriter(uint32_t writer_id) override;
void CommitData(const CommitDataRequest&, CommitDataCallback) override;
void SetupSharedMemory(std::unique_ptr<SharedMemory>,
size_t page_size_bytes,
bool provided_by_producer,
SharedMemoryABI::ShmemMode shmem_mode);
std::unique_ptr<TraceWriter> CreateTraceWriter(
BufferID,
BufferExhaustedPolicy) override;
SharedMemoryArbiter* MaybeSharedMemoryArbiter() override;
bool IsShmemProvidedByProducer() const override;
void NotifyFlushComplete(FlushRequestID) override;
void NotifyDataSourceStarted(DataSourceInstanceID) override;
void NotifyDataSourceStopped(DataSourceInstanceID) override;
SharedMemory* shared_memory() const override;
size_t shared_buffer_page_size_kb() const override;
void ActivateTriggers(const std::vector<std::string>&) override;
void Sync(std::function<void()> callback) override;
void OnTracingSetup();
void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&);
void StartDataSource(DataSourceInstanceID, const DataSourceConfig&);
void StopDataSource(DataSourceInstanceID);
void Flush(FlushRequestID,
const std::vector<DataSourceInstanceID>&,
FlushFlags);
void OnFreeBuffers(const std::vector<BufferID>& target_buffers);
void ClearIncrementalState(const std::vector<DataSourceInstanceID>&);
bool is_allowed_target_buffer(BufferID buffer_id) const {
return allowed_target_buffers_.count(buffer_id);
}
std::optional<BufferID> buffer_id_for_writer(WriterID writer_id) const {
const auto it = writers_.find(writer_id);
if (it != writers_.end())
return it->second;
return std::nullopt;
}
bool IsShmemEmulated() { return shmem_abi_.use_shmem_emulation(); }
bool IsAndroidProcessFrozen();
uid_t uid() const { return client_identity_.uid(); }
pid_t pid() const { return client_identity_.pid(); }
const ClientIdentity& client_identity() const { return client_identity_; }
private:
friend class TracingServiceImpl;
friend class ConsumerEndpointImpl;
ProducerEndpointImpl(const ProducerEndpointImpl&) = delete;
ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete;
ProducerID const id_;
ClientIdentity const client_identity_;
TracingServiceImpl* const service_;
Producer* producer_;
std::unique_ptr<SharedMemory> shared_memory_;
size_t shared_buffer_page_size_kb_ = 0;
SharedMemoryABI shmem_abi_;
size_t shmem_size_hint_bytes_ = 0;
size_t shmem_page_size_hint_bytes_ = 0;
bool is_shmem_provided_by_producer_ = false;
const std::string name_;
const std::string machine_name_;
std::string sdk_version_;
bool in_process_;
bool smb_scraping_enabled_;
// Set of the global target_buffer IDs that the producer is configured to
// write into in any active tracing session.
std::set<BufferID> allowed_target_buffers_;
// Maps registered TraceWriter IDs to their target buffers as registered by
// the producer. Note that producers aren't required to register their
// writers, so we may see commits of chunks with WriterIDs that aren't
// contained in this map. However, if a producer does register a writer, the
// service will prevent the writer from writing into any other buffer than
// the one associated with it here. The BufferIDs stored in this map are
// untrusted, so need to be verified against |allowed_target_buffers_|
// before use.
std::map<WriterID, BufferID> writers_;
// This is used only in in-process configurations.
// SharedMemoryArbiterImpl methods themselves are thread-safe.
std::unique_ptr<SharedMemoryArbiterImpl> inproc_shmem_arbiter_;
PERFETTO_THREAD_CHECKER(thread_checker_)
base::WeakRunner weak_runner_;
};
// The implementation behind the service endpoint exposed to each consumer.
class ConsumerEndpointImpl : public TracingService::ConsumerEndpoint {
public:
ConsumerEndpointImpl(TracingServiceImpl*,
base::TaskRunner*,
Consumer*,
uid_t uid);
~ConsumerEndpointImpl() override;
void NotifyOnTracingDisabled(const std::string& error);
// TracingService::ConsumerEndpoint implementation.
void EnableTracing(const TraceConfig&, base::ScopedFile) override;
void ChangeTraceConfig(const TraceConfig& cfg) override;
void StartTracing() override;
void DisableTracing() override;
void ReadBuffers() override;
void FreeBuffers() override;
void Flush(uint32_t timeout_ms, FlushCallback, FlushFlags) override;
void Detach(const std::string& key) override;
void Attach(const std::string& key) override;
void GetTraceStats() override;
void ObserveEvents(uint32_t enabled_event_types) override;
void QueryServiceState(QueryServiceStateArgs,
QueryServiceStateCallback) override;
void QueryCapabilities(QueryCapabilitiesCallback) override;
void SaveTraceForBugreport(SaveTraceForBugreportCallback) override;
void CloneSession(CloneSessionArgs) override;
// Will queue a task to notify the consumer about the state change.
void OnDataSourceInstanceStateChange(const ProducerEndpointImpl&,
const DataSourceInstance&);
void OnAllDataSourcesStarted();
base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
friend class TracingServiceImpl;
friend struct TracingSession;
ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
void NotifyCloneSnapshotTrigger(const TriggerInfo& trigger_name);
// Returns a pointer to an ObservableEvents object that the caller can fill
// and schedules a task to send the ObservableEvents to the consumer.
ObservableEvents* AddObservableEvents();
base::TaskRunner* const task_runner_;
TracingServiceImpl* const service_;
Consumer* const consumer_;
uid_t const uid_;
TracingSessionID tracing_session_id_ = 0;
// Whether the consumer is interested in DataSourceInstance state change
// events.
uint32_t observable_events_mask_ = 0;
// ObservableEvents that will be sent to the consumer. If set, a task to
// flush the events to the consumer has been queued.
std::unique_ptr<ObservableEvents> observable_events_;
PERFETTO_THREAD_CHECKER(thread_checker_)
base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_; // Keep last.
};
class RelayEndpointImpl : public TracingService::RelayEndpoint {
public:
using SyncMode = RelayEndpoint::SyncMode;
using RelayClientID = TracingService::RelayClientID;
struct SyncedClockSnapshots {
SyncedClockSnapshots(SyncMode _sync_mode,
base::ClockSnapshotVector _client_clocks,
base::ClockSnapshotVector _host_clocks)
: sync_mode(_sync_mode),
client_clocks(std::move(_client_clocks)),
host_clocks(std::move(_host_clocks)) {}
SyncMode sync_mode;
base::ClockSnapshotVector client_clocks;
base::ClockSnapshotVector host_clocks;
};
explicit RelayEndpointImpl(RelayClientID relay_client_id,
TracingServiceImpl* service);
~RelayEndpointImpl() override;
void CacheSystemInfo(std::vector<uint8_t> serialized_system_info) override {
serialized_system_info_ = serialized_system_info;
}
void SyncClocks(SyncMode sync_mode,
base::ClockSnapshotVector client_clocks,
base::ClockSnapshotVector host_clocks) override;
void Disconnect() override;
MachineID machine_id() const { return relay_client_id_.first; }
base::CircularQueue<SyncedClockSnapshots>& synced_clocks() {
return synced_clocks_;
}
std::vector<uint8_t>& serialized_system_info() {
return serialized_system_info_;
}
private:
friend class TracingServiceImpl;
RelayEndpointImpl(const RelayEndpointImpl&) = delete;
RelayEndpointImpl& operator=(const RelayEndpointImpl&) = delete;
RelayClientID relay_client_id_;
TracingServiceImpl* const service_;
std::vector<uint8_t> serialized_system_info_;
base::CircularQueue<SyncedClockSnapshots> synced_clocks_;
PERFETTO_THREAD_CHECKER(thread_checker_)
};
} // namespace tracing_service
} // namespace perfetto
#endif // SRC_TRACING_SERVICE_TRACING_SERVICE_ENDPOINTS_IMPL_H_