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/run_cvd/launch/webrtc_controller.h"
17 
18 #include <android-base/logging.h>
19 #include <fruit/fruit.h>
20 
21 #include "common/libs/fs/shared_buf.h"
22 #include "common/libs/fs/shared_fd.h"
23 #include "common/libs/transport/channel_sharedfd.h"
24 #include "common/libs/utils/result.h"
25 #include "google/rpc/code.pb.h"
26 #include "host/commands/run_cvd/launch/launch.h"
27 #include "webrtc_commands.pb.h"
28 
29 namespace cuttlefish {
30 namespace {
31 
IsSuccess(const webrtc::WebrtcCommandResponse & response)32 Result<void> IsSuccess(const webrtc::WebrtcCommandResponse& response) {
33   CF_EXPECT(response.has_status(), "Webrtc command response missing status?");
34   const auto& response_status = response.status();
35   CF_EXPECT_EQ(response_status.code(), google::rpc::Code::OK,
36                "Webrtc command failed: " << response_status.message());
37   return {};
38 }
39 
40 }  // namespace
41 
42 using webrtc::WebrtcCommandRequest;
43 using webrtc::WebrtcCommandResponse;
44 
ResultSetup()45 Result<void> WebRtcController::ResultSetup() {
46   LOG(DEBUG) << "Initializing the WebRTC command sockets.";
47   SharedFD host_socket;
48   CF_EXPECT(SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &client_socket_,
49                                  &host_socket),
50             client_socket_->StrError());
51 
52   command_channel_.emplace(host_socket);
53   return {};
54 }
55 
GetClientSocket() const56 SharedFD WebRtcController::GetClientSocket() const { return client_socket_; }
57 
SendStartRecordingCommand()58 Result<void> WebRtcController::SendStartRecordingCommand() {
59   CF_EXPECT(command_channel_.has_value(), "Not initialized?");
60   WebrtcCommandRequest request;
61   request.mutable_start_recording_request();
62   WebrtcCommandResponse response =
63       CF_EXPECT(command_channel_->SendCommand(request));
64   CF_EXPECT(IsSuccess(response), "Failed to start recording.");
65   return {};
66 }
67 
SendStopRecordingCommand()68 Result<void> WebRtcController::SendStopRecordingCommand() {
69   CF_EXPECT(command_channel_.has_value(), "Not initialized?");
70   WebrtcCommandRequest request;
71   request.mutable_stop_recording_request();
72   WebrtcCommandResponse response =
73       CF_EXPECT(command_channel_->SendCommand(request));
74   CF_EXPECT(IsSuccess(response), "Failed to stop recording.");
75   return {};
76 }
77 
SendScreenshotDisplayCommand(int display_number,const std::string & screenshot_path)78 Result<void> WebRtcController::SendScreenshotDisplayCommand(
79     int display_number, const std::string& screenshot_path) {
80   CF_EXPECT(command_channel_.has_value(), "Not initialized?");
81   WebrtcCommandRequest request;
82   auto* screenshot_request = request.mutable_screenshot_display_request();
83   screenshot_request->set_display_number(display_number);
84   screenshot_request->set_screenshot_path(screenshot_path);
85   WebrtcCommandResponse response =
86       CF_EXPECT(command_channel_->SendCommand(request));
87   CF_EXPECT(IsSuccess(response), "Failed to screenshot display.");
88   return {};
89 }
90 
WebRtcControllerComponent()91 fruit::Component<WebRtcController> WebRtcControllerComponent() {
92   return fruit::createComponent()
93       .addMultibinding<SetupFeature, WebRtcController>();
94 }
95 
96 }  // namespace cuttlefish
97