1 //
2 // Copyright (C) 2020 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 <android-base/strings.h>
17 #include <gflags/gflags.h>
18 #include <signal.h>
19 #include <unistd.h>
20 
21 #include <limits>
22 
23 #include "common/libs/device_config/device_config.h"
24 #include "common/libs/fs/shared_buf.h"
25 #include "common/libs/fs/shared_fd.h"
26 #include "common/libs/utils/tee_logging.h"
27 #include "host/commands/modem_simulator/modem_simulator.h"
28 #include "host/libs/config/cuttlefish_config.h"
29 
30 // we can start multiple modems simultaneously; each modem
31 // will listent to one server fd for incoming sms/phone call
32 // there should be at least 1 valid fd
33 DEFINE_string(server_fds, "", "A comma separated list of file descriptors");
34 
ServerFdsFromCmdline()35 std::vector<cuttlefish::SharedFD> ServerFdsFromCmdline() {
36   // Validate the parameter
37   std::string fd_list = FLAGS_server_fds;
38   for (auto c: fd_list) {
39     if (c != ',' && (c < '0' || c > '9')) {
40       LOG(ERROR) << "Invalid file descriptor list: " << fd_list;
41       std::exit(1);
42     }
43   }
44 
45   auto fds = android::base::Split(fd_list, ",");
46   std::vector<cuttlefish::SharedFD> shared_fds;
47   for (auto& fd_str: fds) {
48     auto fd = std::stoi(fd_str);
49     auto shared_fd = cuttlefish::SharedFD::Dup(fd);
50     close(fd);
51     shared_fds.push_back(shared_fd);
52   }
53 
54   return shared_fds;
55 }
56 
main(int argc,char ** argv)57 int main(int argc, char** argv) {
58   ::android::base::InitLogging(argv, android::base::StderrLogger);
59   google::ParseCommandLineFlags(&argc, &argv, false);
60 
61   // Modem simulator log saved in cuttlefish_runtime
62   auto config = cuttlefish::CuttlefishConfig::Get();
63   auto instance = config->ForDefaultInstance();
64 
65   auto modem_log_path = instance.PerInstancePath("modem_simulator.log");
66 
67   {
68     auto log_path = instance.launcher_log_path();
69     std::vector<std::string> log_files{log_path, modem_log_path};
70     android::base::SetLogger(cuttlefish::LogToStderrAndFiles(log_files));
71   }
72 
73   LOG(INFO) << "Start modem simulator, server_fds: " << FLAGS_server_fds;
74 
75   auto server_fds = ServerFdsFromCmdline();
76   if (server_fds.empty()) {
77     LOG(ERROR) << "Need to provide server fd";
78     return -1;
79   }
80 
81   cuttlefish::NvramConfig::InitNvramConfigService(server_fds.size());
82 
83   // Don't get a SIGPIPE from the clients
84   if (sigaction(SIGPIPE, nullptr, nullptr) != 0) {
85     LOG(ERROR) << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
86   }
87 
88   auto nvram_config = cuttlefish::NvramConfig::Get();
89   auto nvram_config_file = nvram_config->ConfigFileLocation();
90 
91   // Start channel monitor, wait for RIL to connect
92   int32_t modem_id = 0;
93   std::vector<std::shared_ptr<cuttlefish::ModemSimulator>> modem_simulators;
94 
95   for (auto& fd : server_fds) {
96     CHECK(fd->IsOpen()) << "Error creating or inheriting modem simulator server: "
97         << fd->StrError();
98 
99     auto modem_simulator = std::make_shared<cuttlefish::ModemSimulator>(modem_id);
100     auto channel_monitor =
101         std::make_unique<cuttlefish::ChannelMonitor>(modem_simulator.get(), fd);
102 
103     modem_simulator->Initialize(std::move(channel_monitor));
104 
105     modem_simulators.push_back(modem_simulator);
106 
107     modem_id++;
108   }
109 
110   // Monitor exit request and
111   // remote call, remote sms from other cuttlefish instance
112   std::string monitor_socket_name = "modem_simulator";
113   std::stringstream ss;
114   ss << instance.host_port();
115   monitor_socket_name.append(ss.str());
116 
117   auto monitor_socket = cuttlefish::SharedFD::SocketLocalServer(
118       monitor_socket_name.c_str(), true, SOCK_STREAM, 0666);
119   if (!monitor_socket->IsOpen()) {
120     LOG(ERROR) << "Unable to create monitor socket for modem simulator";
121     std::exit(cuttlefish::kServerError);
122   }
123 
124   // Server loop
125   while (true) {
126     cuttlefish::SharedFDSet read_set;
127     read_set.Set(monitor_socket);
128     int num_fds = cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
129     if (num_fds <= 0) {  // Ignore select error
130       LOG(ERROR) << "Select call returned error : " << strerror(errno);
131     } else if (read_set.IsSet(monitor_socket)) {
132       auto conn = cuttlefish::SharedFD::Accept(*monitor_socket);
133       std::string buf(4, ' ');
134       auto read = cuttlefish::ReadExact(conn, &buf);
135       if (read <= 0) {
136         conn->Close();
137         LOG(WARNING) << "Detected close from the other side";
138         continue;
139       }
140       if (buf == "STOP") {  // Exit request from parent process
141         LOG(INFO) << "Exit request from parent process";
142         nvram_config->SaveToFile(nvram_config_file);
143         for (auto modem : modem_simulators) {
144           modem->SaveModemState();
145         }
146         cuttlefish::WriteAll(conn, "OK"); // Ignore the return value. Exit anyway.
147         std::exit(cuttlefish::kSuccess);
148       } else if (buf.compare(0, 3, "REM") == 0) {  // REMO for modem id 0 ...
149         // Remote request from other cuttlefish instance
150         int id = std::stoi(buf.substr(3, 1));
151         if (id >= modem_simulators.size()) {
152           LOG(ERROR) << "Not supported modem simulator count: " << id;
153         } else {
154           modem_simulators[id]->SetRemoteClient(conn, true);
155         }
156       }
157     }
158   }
159   // Until kill or exit
160 }
161