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 "host/commands/modem_simulator/modem_simulator.h"
17 
18 #include <memory>
19 
20 #include "host/commands/modem_simulator/call_service.h"
21 #include "host/commands/modem_simulator/data_service.h"
22 #include "host/commands/modem_simulator/misc_service.h"
23 #include "host/commands/modem_simulator/network_service.h"
24 #include "host/commands/modem_simulator/sim_service.h"
25 #include "host/commands/modem_simulator/sms_service.h"
26 #include "host/commands/modem_simulator/stk_service.h"
27 #include "host/commands/modem_simulator/sup_service.h"
28 
29 namespace cuttlefish {
30 
ModemSimulator(int32_t modem_id)31 ModemSimulator::ModemSimulator(int32_t modem_id)
32     : modem_id_(modem_id), thread_looper_(new ThreadLooper()) {}
33 
~ModemSimulator()34 ModemSimulator::~ModemSimulator() {
35   // this will stop the looper so all the callbacks
36   // will be gone;
37   thread_looper_->Stop();
38   modem_services_.clear();
39 }
40 
LoadNvramConfig()41 void ModemSimulator::LoadNvramConfig() {
42   auto nvram_config = NvramConfig::Get();
43   if (!nvram_config) {
44     LOG(FATAL) << "Failed to obtain nvram config singleton";
45     return;
46   }
47 }
48 
Initialize(std::unique_ptr<ChannelMonitor> && channel_monitor)49 void ModemSimulator::Initialize(
50     std::unique_ptr<ChannelMonitor>&& channel_monitor) {
51   channel_monitor_ = std::move(channel_monitor);
52   LoadNvramConfig();
53   RegisterModemService();
54 }
55 
RegisterModemService()56 void ModemSimulator::RegisterModemService() {
57   auto netservice = std::make_unique<NetworkService>(
58       modem_id_, channel_monitor_.get(), thread_looper_.get());
59   auto simservice = std::make_unique<SimService>(
60       modem_id_, channel_monitor_.get(), thread_looper_.get());
61   auto miscservice = std::make_unique<MiscService>(
62       modem_id_, channel_monitor_.get(), thread_looper_.get());
63   auto callservice = std::make_unique<CallService>(
64       modem_id_, channel_monitor_.get(), thread_looper_.get());
65   auto stkservice = std::make_unique<StkService>(
66       modem_id_, channel_monitor_.get(), thread_looper_.get());
67   auto smsservice = std::make_unique<SmsService>(
68       modem_id_, channel_monitor_.get(), thread_looper_.get());
69   auto dataservice = std::make_unique<DataService>(
70       modem_id_, channel_monitor_.get(), thread_looper_.get());
71   auto supservice = std::make_unique<SupService>(
72       modem_id_, channel_monitor_.get(), thread_looper_.get());
73 
74   netservice->SetupDependency(miscservice.get(), simservice.get(),
75                               dataservice.get());
76   simservice->SetupDependency(netservice.get());
77   callservice->SetupDependency(simservice.get(), netservice.get());
78   stkservice->SetupDependency(simservice.get());
79   smsservice->SetupDependency(simservice.get());
80 
81   modem_services_[kSimService] = std::move(simservice);
82   modem_services_[kNetworkService] = std::move(netservice);
83   modem_services_[kCallService] = std::move(callservice);
84   modem_services_[kDataService] = std::move(dataservice);
85   modem_services_[kSmsService] = std::move(smsservice);
86   modem_services_[kSupService] = std::move(supservice);
87   modem_services_[kStkService] = std::move(stkservice);
88   modem_services_[kMiscService] = std::move(miscservice);
89 }
90 
DispatchCommand(const Client & client,std::string & command)91 void ModemSimulator::DispatchCommand(const Client& client, std::string& command) {
92   auto iter = modem_services_.find(kSmsService);
93   if (iter != modem_services_.end()) {
94     auto sms_service =
95         dynamic_cast<SmsService*>(modem_services_[kSmsService].get());
96     if (sms_service->IsWaitingSmsPdu()) {
97       sms_service->HandleSendSMSPDU(client, command);
98       return;
99     } else if (sms_service->IsWaitingSmsToSim()) {
100       sms_service->HandleWriteSMSPduToSim(client, command);
101       return;
102     }
103   }
104 
105   bool success = false;
106   for (auto& service : modem_services_) {
107     success = service.second->HandleModemCommand(client, command);
108     if (success) {
109       break;
110     }
111   }
112 
113   if (!success && client.type != Client::REMOTE) {
114     LOG(DEBUG) << "Not supported AT command: " << command;
115     client.SendCommandResponse(ModemService::kCmeErrorOperationNotSupported);
116   }
117 }
118 
OnFirstClientConnected()119 void ModemSimulator::OnFirstClientConnected() {
120   auto iter = modem_services_.find(kMiscService);
121   if (iter != modem_services_.end()) {
122     auto misc_service =
123         dynamic_cast<MiscService*>(modem_services_[kMiscService].get());
124     misc_service->TimeUpdate();
125   }
126 
127   iter = modem_services_.find(kNetworkService);
128   if (iter != modem_services_.end()) {
129     auto network_service =
130         dynamic_cast<NetworkService*>(modem_services_[kNetworkService].get());
131     network_service->OnVoiceRegisterStateChanged();
132     network_service->OnDataRegisterStateChanged();
133   }
134 }
135 
SaveModemState()136 void ModemSimulator::SaveModemState() {
137   auto iter = modem_services_.find(kSimService);
138   if (iter != modem_services_.end()) {
139     auto sim_service =
140         dynamic_cast<SimService*>(modem_services_[kSimService].get());
141     sim_service->SavePinStateToIccProfile();
142     sim_service->SaveFacilityLockToIccProfile();
143   }
144 }
145 
IsWaitingSmsPdu()146 bool ModemSimulator::IsWaitingSmsPdu() {
147   auto iter = modem_services_.find(kSmsService);
148   if (iter != modem_services_.end()) {
149     auto sms_service =
150         dynamic_cast<SmsService*>(modem_services_[kSmsService].get());
151     return (sms_service->IsWaitingSmsPdu() | sms_service->IsWaitingSmsToSim());
152   }
153   return false;
154 }
155 
156 }  // namespace cuttlefish
157