blob: b0fce4ae8b51d73189a9326299b84d71f360d335 [file] [log] [blame]
Primiano Tucciaf429f92017-12-19 01:51:50 +01001/*
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#include "src/tracing/ipc/service/consumer_ipc_service.h"
18
19#include <inttypes.h>
20
21#include "perfetto/base/logging.h"
22#include "perfetto/base/task_runner.h"
23#include "perfetto/ipc/host.h"
24#include "perfetto/tracing/core/chunk.h"
25#include "perfetto/tracing/core/service.h"
26#include "perfetto/tracing/core/trace_config.h"
27#include "perfetto/tracing/core/trace_packet.h"
28
29namespace perfetto {
30
31ConsumerIPCService::ConsumerIPCService(Service* core_service)
32 : core_service_(core_service), weak_ptr_factory_(this) {}
33
34ConsumerIPCService::~ConsumerIPCService() = default;
35
36ConsumerIPCService::RemoteConsumer*
37ConsumerIPCService::GetConsumerForCurrentRequest() {
38 const ipc::ClientID ipc_client_id = ipc::Service::client_info().client_id();
39 PERFETTO_CHECK(ipc_client_id);
40 auto it = consumers_.find(ipc_client_id);
41 if (it == consumers_.end()) {
42 auto* remote_consumer = new RemoteConsumer();
43 consumers_[ipc_client_id].reset(remote_consumer);
44 remote_consumer->service_endpoint =
45 core_service_->ConnectConsumer(remote_consumer);
46 return remote_consumer;
47 }
48 return it->second.get();
49}
50
51// Called by the IPC layer.
52void ConsumerIPCService::OnClientDisconnected() {
53 ipc::ClientID client_id = ipc::Service::client_info().client_id();
Primiano Tucciaf429f92017-12-19 01:51:50 +010054 consumers_.erase(client_id);
55}
56
57// Called by the IPC layer.
58void ConsumerIPCService::EnableTracing(const EnableTracingRequest& req,
59 DeferredEnableTracingResponse resp) {
60 TraceConfig trace_config;
61 trace_config.FromProto(req.trace_config());
62 GetConsumerForCurrentRequest()->service_endpoint->EnableTracing(trace_config);
63 resp.Resolve(ipc::AsyncResult<EnableTracingResponse>::Create());
64}
65
66// Called by the IPC layer.
67void ConsumerIPCService::DisableTracing(const DisableTracingRequest& req,
68 DeferredDisableTracingResponse resp) {
69 GetConsumerForCurrentRequest()->service_endpoint->DisableTracing();
70 resp.Resolve(ipc::AsyncResult<DisableTracingResponse>::Create());
71}
72
73// Called by the IPC layer.
74void ConsumerIPCService::ReadBuffers(const ReadBuffersRequest& req,
75 DeferredReadBuffersResponse resp) {
76 RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest();
77 remote_consumer->read_buffers_response = std::move(resp);
78 remote_consumer->service_endpoint->ReadBuffers();
79}
80
81// Called by the IPC layer.
82void ConsumerIPCService::FreeBuffers(const FreeBuffersRequest& req,
83 DeferredFreeBuffersResponse resp) {
84 GetConsumerForCurrentRequest()->service_endpoint->FreeBuffers();
85 resp.Resolve(ipc::AsyncResult<FreeBuffersResponse>::Create());
86}
87
88////////////////////////////////////////////////////////////////////////////////
89// RemoteConsumer methods
90////////////////////////////////////////////////////////////////////////////////
91
92ConsumerIPCService::RemoteConsumer::RemoteConsumer() = default;
93ConsumerIPCService::RemoteConsumer::~RemoteConsumer() = default;
94
95// Invoked by the |core_service_| business logic after the ConnectConsumer()
96// call. There is nothing to do here, we really expected the ConnectConsumer()
97// to just work in the local case.
98void ConsumerIPCService::RemoteConsumer::OnConnect() {}
99
100// Invoked by the |core_service_| business logic after we destroy the
101// |service_endpoint| (in the RemoteConsumer dtor).
102void ConsumerIPCService::RemoteConsumer::OnDisconnect() {}
103
104void ConsumerIPCService::RemoteConsumer::OnTraceData(
Primiano Tucci3324dfc2017-12-20 14:35:58 +0100105 std::vector<TracePacket> trace_packets,
Primiano Tucciaf429f92017-12-19 01:51:50 +0100106 bool has_more) {
107 if (!read_buffers_response.IsBound())
108 return;
109
110 auto result = ipc::AsyncResult<ReadBuffersResponse>::Create();
111 result.set_has_more(has_more);
112 // TODO(primiano): Expose the chunks to the Consumer rather than stitching
113 // them and wasting cpu time to hide this detail.
114 for (const TracePacket& trace_packet : trace_packets) {
115 std::string* dst = result->add_trace_packets();
116 dst->reserve(trace_packet.size());
117 for (const Chunk& chunk : trace_packet)
118 dst->append(reinterpret_cast<const char*>(chunk.start), chunk.size);
119 }
120 read_buffers_response.Resolve(std::move(result));
121}
122
123} // namespace perfetto