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