• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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/cvd/server_command/serial_preset.h"
17 
18 #include <mutex>
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22 
23 #include "common/libs/utils/result.h"
24 #include "cvd_server.pb.h"
25 #include "host/commands/cvd/server_client.h"
26 #include "host/commands/cvd/server_command/server_handler.h"
27 #include "host/commands/cvd/server_command/utils.h"
28 #include "host/commands/cvd/types.h"
29 
30 // file copied from "../demo_multi_vd.cpp"
31 namespace cuttlefish {
32 
33 class SerialPreset : public CvdServerHandler {
34  public:
INJECT(SerialPreset (CommandSequenceExecutor & executor))35   INJECT(SerialPreset(CommandSequenceExecutor& executor))
36       : executor_(executor) {}
37   ~SerialPreset() = default;
38 
CanHandle(const RequestWithStdio & request) const39   Result<bool> CanHandle(const RequestWithStdio& request) const override {
40     auto invocation = ParseInvocation(request.Message());
41     return invocation.command == "experimental" &&
42            invocation.arguments.size() >= 1 &&
43            Presets().count(invocation.arguments[0]) > 0;
44   }
45 
Handle(const RequestWithStdio & request)46   Result<cvd::Response> Handle(const RequestWithStdio& request) override {
47     std::unique_lock interrupt_lock(interrupt_mutex_);
48     if (interrupted_) {
49       return CF_ERR("Interrupted");
50     }
51     CF_EXPECT(CF_EXPECT(CanHandle(request)));
52 
53     auto invocation = ParseInvocation(request.Message());
54     CF_EXPECT(invocation.arguments.size() >= 1);
55     const auto& presets = Presets();
56     auto devices = presets.find(invocation.arguments[0]);
57     CF_EXPECT(devices != presets.end(), "could not find preset");
58 
59     cvd::Request inner_req_proto = request.Message();
60     auto& cmd = *inner_req_proto.mutable_command_request();
61     cmd.clear_args();
62     cmd.add_args("cvd");
63     cmd.add_args("experimental");
64     cmd.add_args("serial_launch");
65     for (const auto& device : devices->second) {
66       cmd.add_args("--device=" + device);
67     }
68     for (int i = 1; i < invocation.arguments.size(); i++) {
69       cmd.add_args(invocation.arguments[i]);
70     }
71 
72     RequestWithStdio inner_request(request.Client(), std::move(inner_req_proto),
73                                    request.FileDescriptors(),
74                                    request.Credentials());
75 
76     CF_EXPECT(executor_.Execute({std::move(inner_request)}, request.Err()));
77     interrupt_lock.unlock();
78 
79     cvd::Response response;
80     response.mutable_command_response();
81     return response;
82   }
83 
Interrupt()84   Result<void> Interrupt() override {
85     std::scoped_lock interrupt_lock(interrupt_mutex_);
86     interrupted_ = true;
87     CF_EXPECT(executor_.Interrupt());
88     return {};
89   }
90 
CmdList() const91   cvd_common::Args CmdList() const override { return {"experimental"}; }
92 
93  private:
94   CommandSequenceExecutor& executor_;
95 
Presets()96   static std::unordered_map<std::string, std::vector<std::string>> Presets() {
97     return {
98         {"create_phone_tablet",
99          {"git_master/cf_x86_64_phone-userdebug",
100           "git_master/cf_x86_64_tablet-userdebug"}},
101         {"create_phone_wear",
102          {"git_master/cf_x86_64_phone-userdebug", "git_master/cf_gwear_x86"}},
103     };
104   }
105 
106   std::mutex interrupt_mutex_;
107   bool interrupted_ = false;
108 };
109 
110 fruit::Component<fruit::Required<CommandSequenceExecutor>>
cvdSerialPresetComponent()111 cvdSerialPresetComponent() {
112   return fruit::createComponent()
113       .addMultibinding<CvdServerHandler, SerialPreset>();
114 }
115 
116 }  // namespace cuttlefish
117