1 //
2 // Copyright (C) 2023 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 #include "host/commands/secure_env/suspend_resume_handler.h"
17
18 #include <android-base/logging.h>
19
20 #include "host/libs/command_util/util.h"
21
22 namespace cuttlefish {
23 namespace {
24
WriteSuspendRequest(const SharedFD & socket)25 Result<void> WriteSuspendRequest(const SharedFD& socket) {
26 const SnapshotSocketMessage suspend_request = SnapshotSocketMessage::kSuspend;
27 CF_EXPECT_EQ(sizeof(suspend_request),
28 socket->Write(&suspend_request, sizeof(suspend_request)),
29 "socket write failed: " << socket->StrError());
30 return {};
31 }
32
ReadSuspendAck(const SharedFD & socket)33 Result<void> ReadSuspendAck(const SharedFD& socket) {
34 SnapshotSocketMessage ack_response;
35 CF_EXPECT_EQ(sizeof(ack_response),
36 socket->Read(&ack_response, sizeof(ack_response)),
37 "socket read failed: " << socket->StrError());
38 CF_EXPECT_EQ(SnapshotSocketMessage::kSuspendAck, ack_response);
39 return {};
40 }
41
WriteResumeRequest(const SharedFD & socket)42 Result<void> WriteResumeRequest(const SharedFD& socket) {
43 const SnapshotSocketMessage resume_request = SnapshotSocketMessage::kResume;
44 CF_EXPECT_EQ(sizeof(resume_request),
45 socket->Write(&resume_request, sizeof(resume_request)),
46 "socket write failed: " << socket->StrError());
47 return {};
48 }
49
50 } // namespace
51
~SnapshotCommandHandler()52 SnapshotCommandHandler::~SnapshotCommandHandler() { Join(); }
53
Join()54 void SnapshotCommandHandler::Join() {
55 if (handler_thread_.joinable()) {
56 handler_thread_.join();
57 }
58 }
59
SnapshotCommandHandler(SharedFD channel_to_run_cvd,SnapshotSockets snapshot_sockets)60 SnapshotCommandHandler::SnapshotCommandHandler(SharedFD channel_to_run_cvd,
61 SnapshotSockets snapshot_sockets)
62 : channel_to_run_cvd_(channel_to_run_cvd),
63 snapshot_sockets_(std::move(snapshot_sockets)) {
64 handler_thread_ = std::thread([this]() {
65 while (true) {
66 auto result = SuspendResumeHandler();
67 if (!result.ok()) {
68 LOG(ERROR) << result.error().Trace();
69 return;
70 }
71 }
72 });
73 }
74
SuspendResumeHandler()75 Result<void> SnapshotCommandHandler::SuspendResumeHandler() {
76 using ActionsCase =
77 ::cuttlefish::run_cvd::ExtendedLauncherAction::ActionsCase;
78
79 auto launcher_action_opt =
80 CF_EXPECT(ReadLauncherActionFromFd(channel_to_run_cvd_),
81 "Failed to read LauncherAction from run_cvd");
82 auto launcher_action = CF_EXPECT(std::move(launcher_action_opt),
83 "Channel to run_cvd closed unexpectedly");
84 CF_EXPECT(launcher_action.action == LauncherAction::kExtended);
85
86 switch (launcher_action.extended_action.actions_case()) {
87 case ActionsCase::kSuspend: {
88 LOG(DEBUG) << "Handling suspended...";
89 // Request all worker threads to suspend.
90 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.rust));
91 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.keymaster));
92 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.gatekeeper));
93 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.oemlock));
94 // Wait for ACKs from worker threads.
95 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.rust));
96 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.keymaster));
97 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.gatekeeper));
98 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.oemlock));
99 // Write response to run_cvd.
100 auto response = LauncherResponse::kSuccess;
101 const auto n_written =
102 channel_to_run_cvd_->Write(&response, sizeof(response));
103 CF_EXPECT_EQ(sizeof(response), n_written);
104 return {};
105 };
106 case ActionsCase::kResume: {
107 LOG(DEBUG) << "Handling resume...";
108 // Request all worker threads to resume.
109 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.rust));
110 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.keymaster));
111 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.gatekeeper));
112 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.oemlock));
113 // Write response to run_cvd.
114 auto response = LauncherResponse::kSuccess;
115 const auto n_written =
116 channel_to_run_cvd_->Write(&response, sizeof(response));
117 CF_EXPECT_EQ(sizeof(response), n_written);
118 return {};
119 };
120 default:
121 return CF_ERR("Unsupported run_cvd snapshot command.");
122 }
123 }
124
125 } // namespace cuttlefish
126