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