xref: /aosp_15_r20/external/perfetto/src/tracing/ipc/service/relay_ipc_service.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2024 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/relay_ipc_service.h"
18 
19 #include <cinttypes>
20 #include <utility>
21 
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/clock_snapshots.h"
24 #include "perfetto/ext/ipc/service.h"
25 #include "perfetto/ext/tracing/core/tracing_service.h"
26 #include "perfetto/tracing/core/forward_decls.h"
27 
28 namespace perfetto {
29 
RelayIPCService(TracingService * core_service)30 RelayIPCService::RelayIPCService(TracingService* core_service)
31     : core_service_(core_service), weak_ptr_factory_(this) {}
32 
GetRelayEndpoint(ipc::ClientID client_id)33 TracingService::RelayEndpoint* RelayIPCService::GetRelayEndpoint(
34     ipc::ClientID client_id) {
35   auto* endpoint = relay_endpoints_.Find(client_id);
36   if (!endpoint)
37     return nullptr;
38   return endpoint->get();
39 }
40 
OnClientDisconnected()41 void RelayIPCService::OnClientDisconnected() {
42   auto client_id = ipc::Service::client_info().client_id();
43   PERFETTO_DLOG("Relay endpoint %" PRIu64 "disconnected ", client_id);
44 
45   auto* endpoint = GetRelayEndpoint(client_id);
46   if (!endpoint)
47     return;
48 
49   endpoint->Disconnect();
50   relay_endpoints_.Erase(client_id);
51 }
52 
SyncClock(const protos::gen::SyncClockRequest & req,DeferredSyncClockResponse resp)53 void RelayIPCService::SyncClock(const protos::gen::SyncClockRequest& req,
54                                 DeferredSyncClockResponse resp) {
55   auto host_clock_snapshots = base::CaptureClockSnapshots();
56 
57   // Send the response to client to reduce RTT.
58   auto async_resp = ipc::AsyncResult<protos::gen::SyncClockResponse>::Create();
59   resp.Resolve(std::move(async_resp));
60 
61   base::ClockSnapshotVector client_clock_snapshots;
62   for (size_t i = 0; i < req.clocks().size(); i++) {
63     auto& client_clock = req.clocks()[i];
64     client_clock_snapshots.emplace_back(client_clock.clock_id(),
65                                         client_clock.timestamp());
66   }
67 
68   // Handle the request in the core service.
69   auto machine_id = ipc::Service::client_info().machine_id();
70   auto client_id = ipc::Service::client_info().client_id();
71   auto* endpoint = GetRelayEndpoint(client_id);
72   if (!endpoint) {
73     auto ep = core_service_->ConnectRelayClient(
74         std::make_pair(machine_id, client_id));
75     endpoint = ep.get();
76     relay_endpoints_.Insert(client_id, std::move(ep));
77   }
78 
79   RelayEndpoint::SyncMode mode = req.phase() == SyncClockRequest::PING
80                                      ? RelayEndpoint::SyncMode::PING
81                                      : RelayEndpoint::SyncMode::UPDATE;
82   endpoint->SyncClocks(mode, std::move(client_clock_snapshots),
83                        std::move(host_clock_snapshots));
84 }
85 }  // namespace perfetto
86