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