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