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 =
80 CF_EXPECT(ReadLauncherActionFromFd(channel_to_run_cvd_),
81 "Failed to read LauncherAction from run_cvd");
82 CF_EXPECT(launcher_action.action == LauncherAction::kExtended);
83
84 switch (launcher_action.extended_action.actions_case()) {
85 case ActionsCase::kSuspend: {
86 LOG(DEBUG) << "Handling suspended...";
87 // Request all worker threads to suspend.
88 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.rust));
89 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.keymaster));
90 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.gatekeeper));
91 CF_EXPECT(WriteSuspendRequest(snapshot_sockets_.oemlock));
92 // Wait for ACKs from worker threads.
93 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.rust));
94 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.keymaster));
95 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.gatekeeper));
96 CF_EXPECT(ReadSuspendAck(snapshot_sockets_.oemlock));
97 // Write response to run_cvd.
98 auto response = LauncherResponse::kSuccess;
99 const auto n_written =
100 channel_to_run_cvd_->Write(&response, sizeof(response));
101 CF_EXPECT_EQ(sizeof(response), n_written);
102 return {};
103 };
104 case ActionsCase::kResume: {
105 LOG(DEBUG) << "Handling resume...";
106 // Request all worker threads to resume.
107 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.rust));
108 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.keymaster));
109 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.gatekeeper));
110 CF_EXPECT(WriteResumeRequest(snapshot_sockets_.oemlock));
111 // Write response to run_cvd.
112 auto response = LauncherResponse::kSuccess;
113 const auto n_written =
114 channel_to_run_cvd_->Write(&response, sizeof(response));
115 CF_EXPECT_EQ(sizeof(response), n_written);
116 return {};
117 };
118 default:
119 return CF_ERR("Unsupported run_cvd snapshot command.");
120 }
121 }
122
123 } // namespace cuttlefish
124