• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 <android-base/logging.h>
18 #include <android-base/strings.h>
19 #include <fruit/fruit.h>
20 #include <gflags/gflags.h>
21 #include <unistd.h>
22 
23 #include <fstream>
24 #include <memory>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 #include "common/libs/fs/shared_buf.h"
30 #include "common/libs/fs/shared_fd.h"
31 #include "common/libs/utils/environment.h"
32 #include "common/libs/utils/files.h"
33 #include "common/libs/utils/size_utils.h"
34 #include "common/libs/utils/subprocess.h"
35 #include "common/libs/utils/tee_logging.h"
36 #include "host/commands/run_cvd/boot_state_machine.h"
37 #include "host/commands/run_cvd/launch/launch.h"
38 #include "host/commands/run_cvd/process_monitor.h"
39 #include "host/commands/run_cvd/reporting.h"
40 #include "host/commands/run_cvd/runner_defs.h"
41 #include "host/commands/run_cvd/server_loop.h"
42 #include "host/commands/run_cvd/validate.h"
43 #include "host/libs/config/adb/adb.h"
44 #include "host/libs/config/fastboot/fastboot.h"
45 #include "host/libs/config/config_flag.h"
46 #include "host/libs/config/config_fragment.h"
47 #include "host/libs/config/custom_actions.h"
48 #include "host/libs/config/cuttlefish_config.h"
49 #include "host/libs/config/inject.h"
50 #include "host/libs/metrics/metrics_receiver.h"
51 #include "host/libs/vm_manager/vm_manager.h"
52 
53 namespace cuttlefish {
54 
55 namespace {
56 
57 class CuttlefishEnvironment : public DiagnosticInformation {
58  public:
INJECT(CuttlefishEnvironment (const CuttlefishConfig::InstanceSpecific & instance))59   INJECT(
60       CuttlefishEnvironment(const CuttlefishConfig::InstanceSpecific& instance))
61       : instance_(instance) {}
62 
63   // DiagnosticInformation
Diagnostics() const64   std::vector<std::string> Diagnostics() const override {
65     auto config_path = instance_.PerInstancePath("cuttlefish_config.json");
66     return {
67         "Launcher log: " + instance_.launcher_log_path(),
68         "Instance configuration: " + config_path,
69     };
70   }
71 
72  private:
73   const CuttlefishConfig::InstanceSpecific& instance_;
74 };
75 
76 class InstanceLifecycle : public LateInjected {
77  public:
INJECT(InstanceLifecycle (const CuttlefishConfig & config,ServerLoop & server_loop))78   INJECT(InstanceLifecycle(const CuttlefishConfig& config,
79                            ServerLoop& server_loop))
80       : config_(config), server_loop_(server_loop) {}
81 
LateInject(fruit::Injector<> & injector)82   Result<void> LateInject(fruit::Injector<>& injector) override {
83     config_fragments_ = injector.getMultibindings<ConfigFragment>();
84     setup_features_ = injector.getMultibindings<SetupFeature>();
85     diagnostics_ = injector.getMultibindings<DiagnosticInformation>();
86     return {};
87   }
88 
Run()89   Result<void> Run() {
90     for (auto& fragment : config_fragments_) {
91       CF_EXPECT(config_.LoadFragment(*fragment));
92     }
93 
94     // One of the setup features can consume most output, so print this early.
95     DiagnosticInformation::PrintAll(diagnostics_);
96 
97     CF_EXPECT(SetupFeature::RunSetup(setup_features_));
98 
99     CF_EXPECT(server_loop_.Run());
100 
101     return {};
102   }
103 
104  private:
105   const CuttlefishConfig& config_;
106   ServerLoop& server_loop_;
107   std::vector<ConfigFragment*> config_fragments_;
108   std::vector<SetupFeature*> setup_features_;
109   std::vector<DiagnosticInformation*> diagnostics_;
110 };
111 
runCvdComponent(const CuttlefishConfig * config,const CuttlefishConfig::InstanceSpecific * instance)112 fruit::Component<> runCvdComponent(
113     const CuttlefishConfig* config,
114     const CuttlefishConfig::InstanceSpecific* instance) {
115   return fruit::createComponent()
116       .addMultibinding<DiagnosticInformation, CuttlefishEnvironment>()
117       .addMultibinding<InstanceLifecycle, InstanceLifecycle>()
118       .addMultibinding<LateInjected, InstanceLifecycle>()
119       .bindInstance(*config)
120       .bindInstance(*instance)
121       .install(AdbConfigComponent)
122       .install(AdbConfigFragmentComponent)
123       .install(FastbootConfigComponent)
124       .install(FastbootConfigFragmentComponent)
125       .install(bootStateMachineComponent)
126       .install(ConfigFlagPlaceholder)
127       .install(CustomActionsComponent)
128       .install(LaunchAdbComponent)
129       .install(LaunchFastbootComponent)
130       .install(BluetoothConnectorComponent)
131       .install(UwbConnectorComponent)
132       .install(ConfigServerComponent)
133       .install(ConsoleForwarderComponent)
134       .install(EchoServerComponent)
135       .install(GnssGrpcProxyServerComponent)
136       .install(LogcatReceiverComponent)
137       .install(KernelLogMonitorComponent)
138       .install(MetricsServiceComponent)
139       .install(OpenWrtComponent)
140       .install(OpenwrtControlServerComponent)
141       .install(PicaComponent)
142       .install(RootCanalComponent)
143       .install(NetsimServerComponent)
144       .install(SecureEnvComponent)
145       .install(TombstoneReceiverComponent)
146       .install(WmediumdServerComponent)
147       .install(launchModemComponent)
148       .install(launchStreamerComponent)
149       .install(serverLoopComponent)
150       .install(validationComponent)
151       .install(vm_manager::VmManagerComponent);
152 }
153 
StdinValid()154 Result<void> StdinValid() {
155   CF_EXPECT(!isatty(0),
156             "stdin was a tty, expected to be passed the output of a"
157             " previous stage. Did you mean to run launch_cvd?");
158   CF_EXPECT(errno != EBADF,
159             "stdin was not a valid file descriptor, expected to be passed the "
160             "output of assemble_cvd. Did you mean to run launch_cvd?");
161   return {};
162 }
163 
FindConfigFromStdin()164 Result<const CuttlefishConfig*> FindConfigFromStdin() {
165   std::string input_files_str;
166   {
167     auto input_fd = SharedFD::Dup(0);
168     auto bytes_read = ReadAll(input_fd, &input_files_str);
169     CF_EXPECT(bytes_read >= 0, "Failed to read input files. Error was \""
170                                    << input_fd->StrError() << "\"");
171   }
172   std::vector<std::string> input_files =
173       android::base::Split(input_files_str, "\n");
174   for (const auto& file : input_files) {
175     if (file.find("cuttlefish_config.json") != std::string::npos) {
176       setenv(kCuttlefishConfigEnvVarName, file.c_str(), /* overwrite */ false);
177     }
178   }
179   return CF_EXPECT(CuttlefishConfig::Get());  // Null check
180 }
181 
ConfigureLogs(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)182 void ConfigureLogs(const CuttlefishConfig& config,
183                    const CuttlefishConfig::InstanceSpecific& instance) {
184   auto log_path = instance.launcher_log_path();
185 
186   if (!FileHasContent(log_path)) {
187     std::ofstream launcher_log_ofstream(log_path.c_str());
188     auto assembly_path = config.AssemblyPath("assemble_cvd.log");
189     std::ifstream assembly_log_ifstream(assembly_path);
190     if (assembly_log_ifstream) {
191       auto assemble_log = ReadFile(assembly_path);
192       launcher_log_ofstream << assemble_log;
193     }
194   }
195   std::string prefix;
196   if (config.Instances().size() > 1) {
197     prefix = instance.instance_name() + ": ";
198   }
199   ::android::base::SetLogger(LogToStderrAndFiles({log_path}, prefix));
200 }
201 
ChdirIntoRuntimeDir(const CuttlefishConfig::InstanceSpecific & instance)202 Result<void> ChdirIntoRuntimeDir(
203     const CuttlefishConfig::InstanceSpecific& instance) {
204   // Change working directory to the instance directory as early as possible to
205   // ensure all host processes have the same working dir. This helps stop_cvd
206   // find the running processes when it can't establish a communication with the
207   // launcher.
208   CF_EXPECT(chdir(instance.instance_dir().c_str()) == 0,
209             "Unable to change dir into instance directory \""
210                 << instance.instance_dir() << "\": " << strerror(errno));
211   return {};
212 }
213 
214 }  // namespace
215 
RunCvdMain(int argc,char ** argv)216 Result<void> RunCvdMain(int argc, char** argv) {
217   setenv("ANDROID_LOG_TAGS", "*:v", /* overwrite */ 0);
218   ::android::base::InitLogging(argv, android::base::StderrLogger);
219   google::ParseCommandLineFlags(&argc, &argv, false);
220 
221   CF_EXPECT(StdinValid(), "Invalid stdin");
222   auto config = CF_EXPECT(FindConfigFromStdin());
223   auto instance = config->ForDefaultInstance();
224 
225   ConfigureLogs(*config, instance);
226   CF_EXPECT(ChdirIntoRuntimeDir(instance));
227 
228   fruit::Injector<> injector(runCvdComponent, config, &instance);
229 
230   for (auto& late_injected : injector.getMultibindings<LateInjected>()) {
231     CF_EXPECT(late_injected->LateInject(injector));
232   }
233 
234   MetricsReceiver::LogMetricsVMStart();
235 
236   auto instance_bindings = injector.getMultibindings<InstanceLifecycle>();
237   CF_EXPECT(instance_bindings.size() == 1);
238   CF_EXPECT(instance_bindings[0]->Run());  // Should not return
239 
240   return CF_ERR("The server loop returned, it should never happen!!");
241 }
242 
243 } // namespace cuttlefish
244 
main(int argc,char ** argv)245 int main(int argc, char** argv) {
246   auto result = cuttlefish::RunCvdMain(argc, argv);
247   if (result.ok()) {
248     return 0;
249   }
250   LOG(ERROR) << result.error().Message();
251   LOG(DEBUG) << result.error().Trace();
252   abort();
253 }
254