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
17 #include "host/commands/cvd/server_command/acloud_translator.h"
18
19 #include <mutex>
20
21 #include <fruit/fruit.h>
22
23 #include "common/libs/fs/shared_buf.h"
24 #include "common/libs/utils/flag_parser.h"
25 #include "common/libs/utils/result.h"
26 #include "cvd_server.pb.h"
27 #include "host/commands/cvd/server_client.h"
28 #include "host/commands/cvd/server_command/server_handler.h"
29 #include "host/commands/cvd/server_command/utils.h"
30 #include "host/commands/cvd/types.h"
31
32 namespace cuttlefish {
33
34 static constexpr char kTranslatorHelpMessage[] =
35 R"(Cuttlefish Virtual Device (CVD) CLI.
36
37 usage: cvd acloud translator <args>
38
39 Args:
40 --opt-out Opt-out CVD Acloud and choose to run original Python Acloud.
41 --opt-in Opt-in and run CVD Acloud as default.
42 Both -opt-out and --opt-in are mutually exclusive.
43 )";
44
45 class AcloudTranslatorCommand : public CvdServerHandler {
46 public:
INJECT(AcloudTranslatorCommand (ANNOTATED (AcloudTranslatorOptOut,std::atomic<bool> &)optout))47 INJECT(AcloudTranslatorCommand(ANNOTATED(AcloudTranslatorOptOut,
48 std::atomic<bool>&) optout))
49 : optout_(optout) {}
50 ~AcloudTranslatorCommand() = default;
51
CanHandle(const RequestWithStdio & request) const52 Result<bool> CanHandle(const RequestWithStdio& request) const override {
53 auto invocation = ParseInvocation(request.Message());
54 if (invocation.arguments.size() >= 2) {
55 if (invocation.command == "acloud" &&
56 invocation.arguments[0] == "translator") {
57 return true;
58 }
59 }
60 return false;
61 }
62
CmdList() const63 cvd_common::Args CmdList() const override { return {}; }
64
Handle(const RequestWithStdio & request)65 Result<cvd::Response> Handle(const RequestWithStdio& request) override {
66 CF_EXPECT(CanHandle(request));
67 auto invocation = ParseInvocation(request.Message());
68 if (invocation.arguments.empty() || invocation.arguments.size() < 2) {
69 return CF_ERR("Translator command not support");
70 }
71
72 // cvd acloud translator --opt-out
73 // cvd acloud translator --opt-in
74 cvd::Response response;
75 response.mutable_command_response();
76 bool help = false;
77 bool flag_optout = false;
78 bool flag_optin = false;
79 std::vector<Flag> translator_flags = {
80 GflagsCompatFlag("help", help),
81 GflagsCompatFlag("opt-out", flag_optout),
82 GflagsCompatFlag("opt-in", flag_optin),
83 };
84 CF_EXPECT(ParseFlags(translator_flags, invocation.arguments),
85 "Failed to process translator flag.");
86 if (help) {
87 WriteAll(request.Out(), kTranslatorHelpMessage);
88 return response;
89 }
90 CF_EXPECT(flag_optout != flag_optin,
91 "Only one of --opt-out or --opt-in should be given.");
92 optout_ = flag_optout;
93 return response;
94 }
Interrupt()95 Result<void> Interrupt() override { return CF_ERR("Can't be interrupted."); }
96
97 private:
98 std::atomic<bool>& optout_;
99 };
100
101 fruit::Component<fruit::Required<
102 fruit::Annotated<AcloudTranslatorOptOut, std::atomic<bool>>>>
AcloudTranslatorCommandComponent()103 AcloudTranslatorCommandComponent() {
104 return fruit::createComponent()
105 .addMultibinding<CvdServerHandler, AcloudTranslatorCommand>();
106 }
107
108 } // namespace cuttlefish
109