blob: 86f0de0b649e065bf5573a9f3ca5aaae549098a0 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/tracing/tracing_service.h"
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/timer/timer.h"
#include "services/service_manager/public/mojom/service_manager.mojom.h"
#include "services/tracing/agent_registry.h"
#include "services/tracing/coordinator.h"
#include "services/tracing/perfetto/perfetto_service.h"
#include "services/tracing/perfetto/perfetto_tracing_coordinator.h"
#include "services/tracing/public/cpp/tracing_features.h"
#include "services/tracing/public/mojom/traced_process.mojom.h"
namespace tracing {
// Listener used to connect to every other service and
// pass them the needed interface pointers to connect
// back and register with the tracing service.
class ServiceListener : public service_manager::mojom::ServiceManagerListener {
public:
ServiceListener(service_manager::Connector* connector,
scoped_refptr<base::SequencedTaskRunner> task_runner,
AgentRegistry* agent_registry)
: binding_(this),
connector_(connector),
task_runner_(task_runner),
agent_registry_(agent_registry) {
service_manager::mojom::ServiceManagerPtr service_manager;
connector_->BindInterface(service_manager::mojom::kServiceName,
&service_manager);
service_manager::mojom::ServiceManagerListenerPtr listener;
service_manager::mojom::ServiceManagerListenerRequest request(
mojo::MakeRequest(&listener));
service_manager->AddListener(std::move(listener));
binding_.Bind(std::move(request));
}
void ConnectProcessToTracingService(
const service_manager::Identity& identity) {
mojom::TracedProcessPtr traced_process;
connector_->BindInterface(
service_manager::ServiceFilter::ForExactIdentity(identity),
mojo::MakeRequest(&traced_process),
service_manager::mojom::BindInterfacePriority::kBestEffort);
auto new_connection_request = mojom::ConnectToTracingRequest::New();
PerfettoService::GetInstance()->BindRequest(
mojo::MakeRequest(&new_connection_request->perfetto_service));
agent_registry_->BindAgentRegistryRequest(
task_runner_,
mojo::MakeRequest(&new_connection_request->agent_registry));
traced_process->ConnectToTracingService(std::move(new_connection_request));
}
// service_manager::mojom::ServiceManagerListener implementation.
void OnInit(std::vector<service_manager::mojom::RunningServiceInfoPtr>
running_services) override {
for (auto& service : running_services) {
ConnectProcessToTracingService(service->identity);
}
}
void OnServiceStarted(const service_manager::Identity& identity,
uint32_t pid) override {
ConnectProcessToTracingService(identity);
}
void OnServiceCreated(
service_manager::mojom::RunningServiceInfoPtr service) override {}
void OnServicePIDReceived(const service_manager::Identity& identity,
uint32_t pid) override {}
void OnServiceFailedToStart(
const service_manager::Identity& identity) override {}
void OnServiceStopped(const service_manager::Identity& identity) override {}
private:
mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
service_manager::Connector* connector_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
AgentRegistry* agent_registry_;
};
TracingService::TracingService(service_manager::mojom::ServiceRequest request)
: service_binding_(this, std::move(request)),
task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
TracingService::~TracingService() {
task_runner_->DeleteSoon(FROM_HERE, std::move(tracing_agent_registry_));
if (perfetto_tracing_coordinator_) {
task_runner_->DeleteSoon(FROM_HERE,
std::move(perfetto_tracing_coordinator_));
}
}
void TracingService::OnDisconnected() {
CloseAgentConnectionsAndTerminate();
}
void TracingService::OnStart() {
tracing_agent_registry_ = std::make_unique<AgentRegistry>();
if (TracingUsesPerfettoBackend()) {
task_runner_ = tracing::PerfettoService::GetInstance()->task_runner();
auto perfetto_coordinator = std::make_unique<PerfettoTracingCoordinator>(
tracing_agent_registry_.get(),
base::BindRepeating(&TracingService::OnCoordinatorConnectionClosed,
base::Unretained(this),
base::SequencedTaskRunnerHandle::Get()));
registry_.AddInterface(
base::BindRepeating(&PerfettoTracingCoordinator::BindCoordinatorRequest,
base::Unretained(perfetto_coordinator.get())));
perfetto_tracing_coordinator_ = std::move(perfetto_coordinator);
} else {
auto tracing_coordinator = std::make_unique<Coordinator>(
tracing_agent_registry_.get(),
base::BindRepeating(&TracingService::OnCoordinatorConnectionClosed,
base::Unretained(this), nullptr));
registry_.AddInterface(
base::BindRepeating(&Coordinator::BindCoordinatorRequest,
base::Unretained(tracing_coordinator.get())));
tracing_coordinator_ = std::move(tracing_coordinator);
}
service_listener_ = std::make_unique<ServiceListener>(
service_binding_.GetConnector(), task_runner_,
tracing_agent_registry_.get());
}
void TracingService::OnBindInterface(
const service_manager::BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
registry_.BindInterface(interface_name, std::move(interface_pipe),
source_info);
}
void TracingService::OnCoordinatorConnectionClosed(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
// TODO(oysteine): Running TracingService and Perfetto on different
// sequences is getting messy; refactor so that the service manager
// runs the tracing service on a single threaded taskrunner so
// Perfetto can use the same.
if (task_runner && !task_runner->RunsTasksInCurrentSequence()) {
task_runner->PostTask(
FROM_HERE,
base::BindOnce(&TracingService::OnCoordinatorConnectionClosed,
base::Unretained(this), nullptr));
return;
}
service_binding_.RequestClose();
}
void TracingService::CloseAgentConnectionsAndTerminate() {
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&AgentRegistry::DisconnectAllAgents,
base::Unretained(tracing_agent_registry_.get())),
base::BindOnce(&TracingService::Terminate, base::Unretained(this)));
}
} // namespace tracing