Primiano Tucci | af429f9 | 2017-12-19 01:51:50 +0100 | [diff] [blame] | 1 | /* |
| 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 | |
| 29 | namespace perfetto { |
| 30 | |
| 31 | ConsumerIPCService::ConsumerIPCService(Service* core_service) |
| 32 | : core_service_(core_service), weak_ptr_factory_(this) {} |
| 33 | |
| 34 | ConsumerIPCService::~ConsumerIPCService() = default; |
| 35 | |
| 36 | ConsumerIPCService::RemoteConsumer* |
| 37 | ConsumerIPCService::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. |
| 52 | void ConsumerIPCService::OnClientDisconnected() { |
| 53 | ipc::ClientID client_id = ipc::Service::client_info().client_id(); |
Primiano Tucci | af429f9 | 2017-12-19 01:51:50 +0100 | [diff] [blame] | 54 | consumers_.erase(client_id); |
| 55 | } |
| 56 | |
| 57 | // Called by the IPC layer. |
| 58 | void 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. |
| 67 | void 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. |
| 74 | void 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. |
| 82 | void 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 | |
| 92 | ConsumerIPCService::RemoteConsumer::RemoteConsumer() = default; |
| 93 | ConsumerIPCService::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. |
| 98 | void ConsumerIPCService::RemoteConsumer::OnConnect() {} |
| 99 | |
| 100 | // Invoked by the |core_service_| business logic after we destroy the |
| 101 | // |service_endpoint| (in the RemoteConsumer dtor). |
| 102 | void ConsumerIPCService::RemoteConsumer::OnDisconnect() {} |
| 103 | |
| 104 | void ConsumerIPCService::RemoteConsumer::OnTraceData( |
Primiano Tucci | 3324dfc | 2017-12-20 14:35:58 +0100 | [diff] [blame^] | 105 | std::vector<TracePacket> trace_packets, |
Primiano Tucci | af429f9 | 2017-12-19 01:51:50 +0100 | [diff] [blame] | 106 | 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 |