164 lines
5.7 KiB
C++
164 lines
5.7 KiB
C++
//
|
|
// Copyright (C) 2020 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <android-base/strings.h>
|
|
#include <gflags/gflags.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include <limits>
|
|
|
|
#include "common/libs/device_config/device_config.h"
|
|
#include "common/libs/fs/shared_buf.h"
|
|
#include "common/libs/fs/shared_fd.h"
|
|
#include "common/libs/utils/tee_logging.h"
|
|
#include "host/commands/modem_simulator/modem_simulator.h"
|
|
#include "host/libs/config/cuttlefish_config.h"
|
|
|
|
// we can start multiple modems simultaneously; each modem
|
|
// will listent to one server fd for incoming sms/phone call
|
|
// there should be at least 1 valid fd
|
|
DEFINE_string(server_fds, "", "A comma separated list of file descriptors");
|
|
DEFINE_int32(sim_type, 1, "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
|
|
|
|
std::vector<cuttlefish::SharedFD> ServerFdsFromCmdline() {
|
|
// Validate the parameter
|
|
std::string fd_list = FLAGS_server_fds;
|
|
for (auto c: fd_list) {
|
|
if (c != ',' && (c < '0' || c > '9')) {
|
|
LOG(ERROR) << "Invalid file descriptor list: " << fd_list;
|
|
std::exit(1);
|
|
}
|
|
}
|
|
|
|
auto fds = android::base::Split(fd_list, ",");
|
|
std::vector<cuttlefish::SharedFD> shared_fds;
|
|
for (auto& fd_str: fds) {
|
|
auto fd = std::stoi(fd_str);
|
|
auto shared_fd = cuttlefish::SharedFD::Dup(fd);
|
|
close(fd);
|
|
shared_fds.push_back(shared_fd);
|
|
}
|
|
|
|
return shared_fds;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
::android::base::InitLogging(argv, android::base::StderrLogger);
|
|
google::ParseCommandLineFlags(&argc, &argv, false);
|
|
|
|
// Modem simulator log saved in cuttlefish_runtime
|
|
auto config = cuttlefish::CuttlefishConfig::Get();
|
|
auto instance = config->ForDefaultInstance();
|
|
|
|
auto modem_log_path = instance.PerInstanceLogPath("modem_simulator.log");
|
|
|
|
{
|
|
auto log_path = instance.launcher_log_path();
|
|
std::vector<std::string> log_files{log_path, modem_log_path};
|
|
android::base::SetLogger(cuttlefish::LogToStderrAndFiles(log_files));
|
|
}
|
|
|
|
LOG(INFO) << "Start modem simulator, server_fds: " << FLAGS_server_fds
|
|
<< ", Sim type: " << ((FLAGS_sim_type == 2) ?
|
|
"special for CtsCarrierApiTestCases" : "normal" );
|
|
|
|
auto server_fds = ServerFdsFromCmdline();
|
|
if (server_fds.empty()) {
|
|
LOG(ERROR) << "Need to provide server fd";
|
|
return -1;
|
|
}
|
|
|
|
cuttlefish::NvramConfig::InitNvramConfigService(server_fds.size(), FLAGS_sim_type);
|
|
|
|
// Don't get a SIGPIPE from the clients
|
|
if (sigaction(SIGPIPE, nullptr, nullptr) != 0) {
|
|
LOG(ERROR) << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
|
|
}
|
|
|
|
auto nvram_config = cuttlefish::NvramConfig::Get();
|
|
auto nvram_config_file = nvram_config->ConfigFileLocation();
|
|
|
|
// Start channel monitor, wait for RIL to connect
|
|
int32_t modem_id = 0;
|
|
std::vector<std::shared_ptr<cuttlefish::ModemSimulator>> modem_simulators;
|
|
|
|
for (auto& fd : server_fds) {
|
|
CHECK(fd->IsOpen()) << "Error creating or inheriting modem simulator server: "
|
|
<< fd->StrError();
|
|
|
|
auto modem_simulator = std::make_shared<cuttlefish::ModemSimulator>(modem_id);
|
|
auto channel_monitor =
|
|
std::make_unique<cuttlefish::ChannelMonitor>(modem_simulator.get(), fd);
|
|
|
|
modem_simulator->Initialize(std::move(channel_monitor));
|
|
|
|
modem_simulators.push_back(modem_simulator);
|
|
|
|
modem_id++;
|
|
}
|
|
|
|
// Monitor exit request and
|
|
// remote call, remote sms from other cuttlefish instance
|
|
std::string monitor_socket_name = "modem_simulator";
|
|
std::stringstream ss;
|
|
ss << instance.modem_simulator_host_id();
|
|
monitor_socket_name.append(ss.str());
|
|
|
|
auto monitor_socket = cuttlefish::SharedFD::SocketLocalServer(
|
|
monitor_socket_name.c_str(), true, SOCK_STREAM, 0666);
|
|
if (!monitor_socket->IsOpen()) {
|
|
LOG(ERROR) << "Unable to create monitor socket for modem simulator";
|
|
std::exit(cuttlefish::kServerError);
|
|
}
|
|
|
|
// Server loop
|
|
while (true) {
|
|
cuttlefish::SharedFDSet read_set;
|
|
read_set.Set(monitor_socket);
|
|
int num_fds = cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
|
|
if (num_fds <= 0) { // Ignore select error
|
|
LOG(ERROR) << "Select call returned error : " << strerror(errno);
|
|
} else if (read_set.IsSet(monitor_socket)) {
|
|
auto conn = cuttlefish::SharedFD::Accept(*monitor_socket);
|
|
std::string buf(4, ' ');
|
|
auto read = cuttlefish::ReadExact(conn, &buf);
|
|
if (read <= 0) {
|
|
conn->Close();
|
|
LOG(WARNING) << "Detected close from the other side";
|
|
continue;
|
|
}
|
|
if (buf == "STOP") { // Exit request from parent process
|
|
LOG(INFO) << "Exit request from parent process";
|
|
nvram_config->SaveToFile(nvram_config_file);
|
|
for (auto modem : modem_simulators) {
|
|
modem->SaveModemState();
|
|
}
|
|
cuttlefish::WriteAll(conn, "OK"); // Ignore the return value. Exit anyway.
|
|
std::exit(cuttlefish::kSuccess);
|
|
} else if (buf.compare(0, 3, "REM") == 0) { // REMO for modem id 0 ...
|
|
// Remote request from other cuttlefish instance
|
|
int id = std::stoi(buf.substr(3, 1));
|
|
if (id >= modem_simulators.size()) {
|
|
LOG(ERROR) << "Not supported modem simulator count: " << id;
|
|
} else {
|
|
modem_simulators[id]->SetRemoteClient(conn, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Until kill or exit
|
|
}
|