blob: 9c12a5b3e243b8b016457e3787af218f8143329d [file] [log] [blame]
Primiano Tuccidcbbf132017-12-11 23:17:53 +00001/*
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/consumer/consumer_ipc_client_impl.h"
18
19#include <inttypes.h>
20#include <string.h>
21
22#include "perfetto/base/task_runner.h"
23#include "perfetto/ipc/client.h"
24#include "perfetto/tracing/core/consumer.h"
25#include "perfetto/tracing/core/trace_config.h"
26#include "perfetto/tracing/core/trace_packet.h"
27
28// TODO Add a test to check to what happens when ConsumerIPCClientImpl gets
29// destroyed w.r.t. the Consumer pointer. Also think to lifetime of the
30// Consumer* during the callbacks.
31
32namespace perfetto {
33
34// static. (Declared in include/tracing/ipc/consumer_ipc_client.h).
35std::unique_ptr<Service::ConsumerEndpoint> ConsumerIPCClient::Connect(
36 const char* service_sock_name,
37 Consumer* consumer,
38 base::TaskRunner* task_runner) {
39 return std::unique_ptr<Service::ConsumerEndpoint>(
40 new ConsumerIPCClientImpl(service_sock_name, consumer, task_runner));
41}
42
43ConsumerIPCClientImpl::ConsumerIPCClientImpl(const char* service_sock_name,
44 Consumer* consumer,
45 base::TaskRunner* task_runner)
46 : consumer_(consumer),
47 ipc_channel_(ipc::Client::CreateInstance(service_sock_name, task_runner)),
48 consumer_port_(this /* event_listener */),
49 weak_ptr_factory_(this) {
50 ipc_channel_->BindService(consumer_port_.GetWeakPtr());
51}
52
53ConsumerIPCClientImpl::~ConsumerIPCClientImpl() = default;
54
55// Called by the IPC layer if the BindService() succeeds.
56void ConsumerIPCClientImpl::OnConnect() {
57 connected_ = true;
58 consumer_->OnConnect();
59}
60
61void ConsumerIPCClientImpl::OnDisconnect() {
62 PERFETTO_DLOG("Tracing service connection failure");
63 connected_ = false;
64 consumer_->OnDisconnect();
65}
66
67void ConsumerIPCClientImpl::EnableTracing(const TraceConfig& trace_config) {
68 if (!connected_) {
69 PERFETTO_DLOG("Cannot EnableTracing(), not connected to tracing service");
70 return;
71 }
72
73 // Serialize the |trace_config| into a EnableTracingRequest protobuf.
74 // Keep this in sync with changes in consumer_port.proto.
75 EnableTracingRequest req;
76 trace_config.ToProto(req.mutable_trace_config());
77 ipc::Deferred<EnableTracingResponse> async_response;
78 async_response.Bind([](ipc::AsyncResult<EnableTracingResponse> response) {
79 if (!response)
80 PERFETTO_DLOG("EnableTracing() failed");
81 });
82 consumer_port_.EnableTracing(req, std::move(async_response));
83}
84
85void ConsumerIPCClientImpl::DisableTracing() {
86 if (!connected_) {
87 PERFETTO_DLOG("Cannot DisableTracing(), not connected to tracing service");
88 return;
89 }
90
91 ipc::Deferred<DisableTracingResponse> async_response;
92 async_response.Bind([](ipc::AsyncResult<DisableTracingResponse> response) {
93 if (!response)
94 PERFETTO_DLOG("DisableTracing() failed");
95 });
96 consumer_port_.DisableTracing(DisableTracingRequest(),
97 std::move(async_response));
98}
99
100void ConsumerIPCClientImpl::ReadBuffers() {
101 if (!connected_) {
102 PERFETTO_DLOG("Cannot ReadBuffers(), not connected to tracing service");
103 return;
104 }
105
106 ipc::Deferred<ReadBuffersResponse> async_response;
107
108 // The IPC layer guarantees that callbacks are destroyed after this object
109 // is destroyed (by virtue of destroying the |consumer_port_|). In turn the
110 // contract of this class expects the caller to not destroy the Consumer class
111 // before having destroyed this class. Hence binding |this| here is safe.
112 async_response.Bind([this](ipc::AsyncResult<ReadBuffersResponse> response) {
113 OnReadBuffersResponse(std::move(response));
114 });
115 consumer_port_.ReadBuffers(ReadBuffersRequest(), std::move(async_response));
116}
117
118void ConsumerIPCClientImpl::OnReadBuffersResponse(
119 ipc::AsyncResult<ReadBuffersResponse> response) {
120 if (!response) {
121 PERFETTO_DLOG("ReadBuffers() failed");
122 return;
123 }
124 // TODO(primiano): We have to guarantee that the log buffer stays alive at
125 // least as long as these requests are on flights.
126 std::vector<TracePacket> trace_packets;
127 trace_packets.reserve(response->trace_packets().size());
128 for (const std::string& bytes : response->trace_packets()) {
129 trace_packets.emplace_back();
130 trace_packets.back().AddChunk(
131 Chunk(reinterpret_cast<const void*>(bytes.data()), bytes.size()));
132 }
Primiano Tucci3324dfc2017-12-20 14:35:58 +0100133 consumer_->OnTraceData(std::move(trace_packets), response.has_more());
Primiano Tuccidcbbf132017-12-11 23:17:53 +0000134}
135
136void ConsumerIPCClientImpl::FreeBuffers() {
137 if (!connected_) {
138 PERFETTO_DLOG("Cannot FreeBuffers(), not connected to tracing service");
139 return;
140 }
141
142 FreeBuffersRequest req;
143 ipc::Deferred<FreeBuffersResponse> async_response;
144 async_response.Bind([](ipc::AsyncResult<FreeBuffersResponse> response) {
145 if (!response)
146 PERFETTO_DLOG("FreeBuffers() failed");
147 });
148 consumer_port_.FreeBuffers(req, std::move(async_response));
149}
150
151} // namespace perfetto