• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/network_service.h"
17 
18 #include <android-base/logging.h>
19 
20 #include <map>
21 #include <sstream>
22 
23 #include "common/libs/utils/files.h"
24 #include "host/commands/modem_simulator/device_config.h"
25 #include "host/commands/modem_simulator/nvram_config.h"
26 #include "host/commands/modem_simulator/thread_looper.h"
27 namespace cuttlefish {
28 
29 // string type; two byte location area code in hexadecimal format
30 static const std::string kAreaCode = "2142";
31 // string type; four byte GERAN/UTRAN cell ID in hexadecimal format
32 static const std::string kCellId = "0000B804";
33 
34 // Check SignalStrength.java file for more details on how these map to
35 // signal strength bars
36 const std::pair<int, int> kGSMSignalStrength = std::make_pair(4, 30);
37 const std::pair<int, int> kCDMASignalStrength = std::make_pair(4, 120);
38 const std::pair<int, int> kEVDOSignalStrength = std::make_pair(4, 120);
39 const std::pair<int, int> kLTESignalStrength = std::make_pair(4, 30);
40 const std::pair<int, int> kWCDMASignalStrength = std::make_pair(4, 30);
41 const std::pair<int, int> kNRSignalStrength = std::make_pair(45, 135);
42 
NetworkService(int32_t service_id,ChannelMonitor * channel_monitor,ThreadLooper * thread_looper)43 NetworkService::NetworkService(int32_t service_id,
44                                ChannelMonitor* channel_monitor,
45                                ThreadLooper* thread_looper)
46     : ModemService(service_id, this->InitializeCommandHandlers(),
47                    channel_monitor, thread_looper) {
48   InitializeServiceState();
49 }
50 
InitializeCommandHandlers()51 std::vector<CommandHandler> NetworkService::InitializeCommandHandlers() {
52   std::vector<CommandHandler> command_handlers = {
53       CommandHandler(
54           "+CFUN?",
55           [this](const Client& client) { this->HandleRadioPowerReq(client); }),
56       CommandHandler("+CFUN=",
57                      [this](const Client& client, std::string& cmd) {
58                        this->HandleRadioPower(client, cmd);
59                      }),
60       CommandHandler("+REMOTECFUN=",
61                      [this](const Client& client, std::string& cmd) {
62                        this->HandleRadioPower(client, cmd);
63                      }),
64       CommandHandler(
65           "+CSQ",
66           [this](const Client& client) { this->HandleSignalStrength(client); }),
67       CommandHandler("+COPS?",
68                      [this](const Client& client) {
69                        this->HandleQueryNetworkSelectionMode(client);
70                      }),
71       CommandHandler("+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
72                      [this](const Client& client) {
73                        this->HandleRequestOperator(client);
74                      }),
75       CommandHandler("+COPS=?",
76                      [this](const Client& client) {
77                        this->HandleQueryAvailableNetwork(client);
78                      }),
79       CommandHandler("+COPS=",
80                      [this](const Client& client, std::string& cmd) {
81                        this->HandleSetNetworkSelectionMode(client, cmd);
82                      }),
83       CommandHandler("+CREG",
84                      [this](const Client& client, std::string& cmd) {
85                        this->HandleVoiceNetworkRegistration(client, cmd);
86                      }),
87       CommandHandler("+CGREG",
88                      [this](const Client& client, std::string& cmd) {
89                        this->HandleDataNetworkRegistration(client, cmd);
90                      }),
91       CommandHandler("+CEREG",
92                      [this](const Client& client, std::string& cmd) {
93                        this->HandleDataNetworkRegistration(client, cmd);
94                      }),
95       CommandHandler("+CTEC?",
96                      [this](const Client& client) {
97                        this->HandleGetPreferredNetworkType(client);
98                      }),
99       CommandHandler("+CTEC=?",
100                      [this](const Client& client) {
101                        this->HandleQuerySupportedTechs(client);
102                      }),
103       CommandHandler("+CTEC=",
104                      [this](const Client& client, std::string& cmd) {
105                        this->HandleSetPreferredNetworkType(client, cmd);
106                      }),
107       CommandHandler("+REMOTECTEC",
108                      [this](const Client& client, std::string& cmd) {
109                        this->HandleReceiveRemoteCTEC(client, cmd);
110                      }),
111       CommandHandler("+REMOTESIGNAL",
112                      [this](const Client& client, std::string& cmd) {
113                        this->HandleReceiveRemoteSignal(client, cmd);
114                      }),
115       CommandHandler("+REMOTEREG",
116                      [this](const Client& client, std::string& cmd) {
117                        this->HandleReceiveRemoteVoiceDataReg(client, cmd);
118                      }),
119   };
120   return (command_handlers);
121 }
122 
InitializeServiceState()123 void NetworkService::InitializeServiceState() {
124   radio_state_ = RadioState::RADIO_STATE_OFF;
125 
126   modem_radio_capability_ =
127       M_MODEM_TECH_GSM | M_MODEM_TECH_WCDMA | M_MODEM_TECH_LTE | M_MODEM_TECH_NR;
128 
129   auto nvram_config = NvramConfig::Get();
130   auto instance = nvram_config->ForInstance(service_id_);
131 
132   // Default to be ""
133   current_operator_numeric_ = instance.operator_numeric();
134   // Default to be OPER_SELECTION_AUTOMATIC
135   oper_selection_mode_ = (OperatorSelectionMode)instance.network_selection_mode();
136   // Default to be M_MODEM_TECH_LTE | M_MODEM_TECH_WCDMA | M_MODEM_TECH_GSM;
137   preferred_network_mode_ = instance.preferred_network_mode();
138   // Default to be M_MODEM_TECH_LTE
139   current_network_mode_ = (ModemTechnology)instance.modem_technoloy();
140 
141   InitializeNetworkOperator();
142 
143   first_signal_strength_request_ = true;
144   android_last_signal_time_ = 0;
145 }
146 
InitializeNetworkOperator()147 void NetworkService::InitializeNetworkOperator() {
148   operator_list_.push_back(
149       {"311740", "Android Virtual Operator", "Android", NetworkOperator::OPER_STATE_AVAILABLE});
150   operator_list_.push_back(
151       {"310300", "Alternative Operator", "Alternative", NetworkOperator::OPER_STATE_AVAILABLE});
152   operator_list_.push_back(
153       {"310400", "Hermetic Network Operator", "Hermetic", NetworkOperator::OPER_STATE_FORBIDDEN});
154 
155   if (oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_AUTOMATIC) {
156     current_operator_numeric_ = operator_list_.begin()->numeric;
157     operator_list_.begin()->operator_state = NetworkOperator::OPER_STATE_CURRENT;
158   } else if (oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC) {
159     auto iter = operator_list_.begin();
160     for (; iter != operator_list_.end(); ++iter) {
161       if (iter->numeric == current_operator_numeric_) {
162         break;
163       }
164     }
165     if (iter == operator_list_.end()) {
166       current_operator_numeric_ = operator_list_.begin()->numeric;
167       operator_list_.begin()->operator_state = NetworkOperator::OPER_STATE_CURRENT;
168     } else {
169       iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
170     }
171   }
172 }
173 
InitializeSimOperator()174 void NetworkService::InitializeSimOperator() {
175   if (sim_service_ == nullptr) {
176     return;
177   }
178   auto sim_operator_numeric = sim_service_->GetSimOperator();
179   if (sim_operator_numeric == "") {
180     return;
181   }
182 
183   // ensure the first element is sim_operator_numeric
184   for (auto iter = operator_list_.begin(); iter != operator_list_.end();
185        ++iter) {
186     if (iter->numeric == sim_operator_numeric) {
187       std::swap(*iter, *(operator_list_.begin()));
188       return;
189     }
190   }
191 
192   {
193     const char *operator_numeric_xml = "etc/modem_simulator/files/numeric_operator.xml";
194     auto file = cuttlefish::modem::DeviceConfig::DefaultHostArtifactsPath(
195         operator_numeric_xml);
196     if (!cuttlefish::FileExists(file) || !cuttlefish::FileHasContent(file)) {
197       return;
198     }
199 
200     XMLDocument doc;
201     auto err = doc.LoadFile(file.c_str());
202     if (err != tinyxml2::XML_SUCCESS) {
203       LOG(ERROR) << "unable to load XML file '" << file << " ', error " << err;
204       return;
205     }
206     XMLElement *resources = doc.RootElement();
207     if (resources == NULL)  return;
208 
209     XMLElement *stringArray = resources->FirstChildElement("string-array");
210     if (stringArray == NULL) return;
211 
212     XMLElement *item = stringArray->FirstChildElement("item");
213     while (item) {
214       const XMLAttribute *attr_numeric = item->FindAttribute("numeric");
215       std::string numeric = attr_numeric ? attr_numeric->Value() : "";
216       if (numeric == sim_operator_numeric) {
217         break;
218       }
219       item = item->NextSiblingElement("item");
220     }
221     if (item) {
222       std::string names = item->GetText();
223       auto pos = names.find('=');
224       if (pos != std::string::npos) {
225         auto long_name = names.substr(0, pos);
226         auto short_name = names.substr(pos + 1);
227         NetworkOperator sim_operator(sim_operator_numeric, long_name,
228             short_name, NetworkOperator::OPER_STATE_AVAILABLE);
229         operator_list_.insert(operator_list_.begin(), sim_operator);
230       }
231     }
232   }
233   InitializeNetworkOperator();
234 }
235 
SetupDependency(MiscService * misc,SimService * sim,DataService * data)236 void NetworkService::SetupDependency(MiscService* misc, SimService* sim,
237                                      DataService* data) {
238   misc_service_ = misc;
239   sim_service_ = sim;
240   data_service_ = data;
241   InitializeSimOperator();
242 }
243 
OnSimStatusChanged(SimService::SimStatus sim_status)244 void NetworkService::OnSimStatusChanged(SimService::SimStatus sim_status) {
245   if (radio_state_ == RadioState::RADIO_STATE_OFF) {
246     return;  // RegistrationState::NET_REGISTRATION_UNREGISTERED unchanged
247   }
248   if (sim_status == SimService::SIM_STATUS_READY) {
249     voice_registration_status_.registration_state = NET_REGISTRATION_HOME;
250   } else {
251     voice_registration_status_.registration_state = NET_REGISTRATION_EMERGENCY;
252     // 3GPP TS 24.008 [8] and 3GPP TS 24.301 [83] specify the condition
253     // when the MT is considered as attached for emergency bearer services.
254     // applicable only when <AcT> indicates 2,4,5,6
255     // Note: not saved to nvram config due to sim status may change after reboot
256     current_network_mode_ = M_MODEM_TECH_WCDMA;
257   }
258   thread_looper_->PostWithDelay(std::chrono::seconds(1),
259       makeSafeCallback(this, &NetworkService::UpdateRegisterState,
260           voice_registration_status_.registration_state));
261 }
262 
263 /**
264  * AT+CFUN
265  *   Set command selects the level of functionality <fun> in the MT. Level
266  * "full functionality" is where the highest level of power is drawn.
267  * "Minimum functionality" is where minimum power is drawn. Level of functionality
268  * between these may also be specified by manufacturers. When supported by
269  * manufacturers, MT resetting with <rst> parameter may be utilized
270  *
271  * Command                Possible response(s)
272  * +CFUN=[<fun>[,<rst>]]    +CME ERROR: <err>
273  * +CFUN?                   +CFUN: <fun>
274  *                          +CME ERROR: <err>
275  *
276  * <fun>: integer type
277  *   0 minimum functionality
278  *   1 full functionality. Enable (turn on) the transmit and receive RF circuits
279  *     for all supported radio access technologies.
280  *   2 disable (turn off) MT transmit RF circuits only
281  *   3 disable (turn off) MT receive RF circuits only
282  *   4 disable (turn off) both MT transmit and receive RF circuits
283  *   5...127 reserved for manufacturers as intermediate states between full
284  *           and minimum functionality
285  *   128 Full functionality with radio access support according to the setting of +CSRA.
286  *   129 Prepare for shutdown.
287  *
288  * see RIL_REQUEST_RADIO_POWER in RIL
289  */
HandleRadioPowerReq(const Client & client)290 void NetworkService::HandleRadioPowerReq(const Client& client) {
291   std::stringstream ss;
292   ss << "+CFUN: " << radio_state_;
293 
294   std::vector<std::string> responses;
295   responses.push_back(ss.str());
296   responses.push_back("OK");
297 
298   client.SendCommandResponse(responses);
299 }
300 
HandleRadioPower(const Client & client,std::string & command)301 void NetworkService::HandleRadioPower(const Client& client, std::string& command) {
302   CommandParser cmd(command);
303   cmd.SkipPrefix();
304   int on = cmd.GetNextInt();
305   switch (on) {
306     case 0:
307       radio_state_ = RadioState::RADIO_STATE_OFF;
308       UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
309       break;
310     case 1:
311       radio_state_ = RadioState::RADIO_STATE_ON;
312       if (sim_service_ != nullptr) {
313         auto sim_status = sim_service_->GetSimStatus();
314         OnSimStatusChanged(sim_status);
315       }
316       break;
317     default:
318       client.SendCommandResponse(kCmeErrorOperationNotSupported);
319       return;
320   }
321   signal_strength_.Reset();
322 
323   client.SendCommandResponse("OK");
324 }
325 
WakeupFromSleep()326 bool NetworkService::WakeupFromSleep() {
327   // It has not called once yet
328   if (android_last_signal_time_ == 0) {
329       return false;
330   }
331   // Heuristics: if guest has not asked for signal strength
332   // for 2 minutes, we assume it is caused by host sleep
333   time_t now = time(0);
334   const bool wakeup_from_sleep = (now > android_last_signal_time_ + 120);
335   return wakeup_from_sleep;
336 }
337 
SetSignalStrengthValue(int & value,const std::pair<int,int> & range,double percentd)338 void NetworkService::SetSignalStrengthValue(int& value,
339                                             const std::pair<int, int>& range,
340                                             double percentd) {
341   value = range.first + percentd * (range.second - range.first);
342   AdjustSignalStrengthValue(value, range);
343 }
344 
AdjustSignalStrengthValue(int & value,const std::pair<int,int> & range)345 void NetworkService::AdjustSignalStrengthValue(int& value,
346                                                const std::pair<int, int>& range) {
347   if (value < range.first) {
348     value = range.first;
349   } else if (value > range.second) {
350     value = range.second;
351   }
352 }
353 /**
354  * AT+CSQ
355  *   Execution command returns received signal strength indication <rssi>
356  *   and channel bit error rate <ber> from the MT.
357  *
358  * command            Possible response(s)
359  * AT+CSQ               +CSQ: <rssi>,<ber>
360  *                      +CME ERROR: <err>
361  *
362  * <rssi>: integer type
363  *       0 ‑113 dBm or less
364  *       1 ‑111 dBm
365  *       2...30  ‑109... ‑53 dBm
366  *       31  ‑51 dBm or greater
367  *       99  not known or not detectable
368  * <ber>: integer type; channel bit error rate (in percent)
369  *      0...7 as RXQUAL values in the table in 3GPP TS 45.008 [20] subclause 8.2.4
370  *      99  not known or not detectable
371  *
372  * see RIL_REQUEST_SIGNAL_STRENGTH in RIL
373  */
HandleSignalStrength(const Client & client)374 void NetworkService::HandleSignalStrength(const Client& client) {
375   std::vector<std::string> responses;
376   std::stringstream ss;
377 
378   if (WakeupFromSleep()) {
379     misc_service_->TimeUpdate();
380   } else if (first_signal_strength_request_) {
381     first_signal_strength_request_ = false;
382     misc_service_->TimeUpdate();
383   }
384 
385   android_last_signal_time_ = time(0);
386 
387   auto response = GetSignalStrength();
388 
389   responses.push_back(response);
390   responses.push_back("OK");
391   client.SendCommandResponse(responses);
392 }
393 
IsHasNetwork()394 bool NetworkService::IsHasNetwork() {
395   if (radio_state_ == RADIO_STATE_OFF ||
396       oper_selection_mode_ == OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION) {
397     return false;
398   }
399   return true;
400 }
401 
402 /**
403  * AT+COPS
404  *    Set command forces an attempt to select and register to the
405  *    GSM/UMTS/EPS/5GS network operator using the SIM/USIM card installed
406  *    in the currently selected card slot.
407  *
408  * command                         Possible response(s)
409  * +COPS=[<mode>[,<format>          +CME ERROR: <err>
410  *       [,<oper>[,<AcT>]]]]
411  *
412  * +COPS?                           +COPS: <mode>[,<format>,<oper>[,<AcT>]]
413  *                                  +CME ERROR: <err>
414  *
415  * +COPS=?                          +COPS: [list of supported (<stat>,
416  *                                         long alphanumeric <oper>,
417  *                                         short alphanumeric <oper>,
418  *                                         numeric <oper>[,<AcT>])s]
419  *                                      [,,(list of supported <mode>s),
420  *                                      (list of supported <format>s)]
421  *                                  +CME ERROR: <err>
422  *
423  * <mode>: integer type
424  *       0 automatic (<oper> field is ignored)
425  *       1 manual (<oper> field shall be present, and <AcT> optionally)
426  *       2 deregister from network
427  *       3 set only <format> (for read command +COPS?), do not attempt
428  *       registration/deregistration (<oper> and <AcT> fields are ignored);
429  *        this value is not applicable in read command response
430  *       4 manual/automatic (<oper> field shall be present); if manual selection fails, automatic mode (<mode>=0) is entered
431  * <format>: integer type
432  *         0 long format alphanumeric <oper>
433  *         1 short format alphanumeric <oper>
434  *         2 numeric <oper>
435  * <oper>: string type;
436  * <format> indicates if the format is alphanumeric or numeric;
437  * <stat>: integer type
438  *       0 unknown
439  *       1 available
440  *       2 current
441  *       3 forbidden
442  * <AcT>: integer type; access technology selected
443  *      0 GSM
444  *      1 GSM Compact
445  *      2 UTRAN
446  *      3 GSM w/EGPRS (see NOTE 1)
447  *      4 UTRAN w/HSDPA (see NOTE 2)
448  *      5 UTRAN w/HSUPA (see NOTE 2)
449  *      6 UTRAN w/HSDPA and HSUPA (see NOTE 2)
450  *      7 E-UTRAN
451  *      8 EC-GSM-IoT (A/Gb mode) (see NOTE 3)
452  *      9 E-UTRAN (NB-S1 mode) (see NOTE 4)
453  *      10 E-UTRA connected to a 5GCN (see NOTE 5)
454  *      11 NR connected to a 5GCN (see NOTE 5)
455  *      12 NG-RAN
456  *      13 E-UTRA-NR dual connectivity (see NOTE 6)
457  *
458  *  see RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC or
459  *      RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE or
460  *      RIL_REQUEST_OPERATOR in RIL
461  */
HandleQueryNetworkSelectionMode(const Client & client)462 void NetworkService::HandleQueryNetworkSelectionMode(const Client& client) {
463   std::vector<std::string> responses;
464   std::stringstream ss;
465 
466   if (!IsHasNetwork()) {
467     ss << "+COPS: 0,0,0";
468   } else {
469     auto iter = operator_list_.begin();
470     for (; iter != operator_list_.end(); ++iter) {
471       if (iter->numeric == current_operator_numeric_) {
472         break;
473       }
474     }
475     if (iter != operator_list_.end()) {
476       ss << "+COPS: " << oper_selection_mode_ << ",2," << iter->numeric;
477     } else {
478       ss << "+COPS: " << oper_selection_mode_ << ",0,0";
479     }
480   }
481   responses.push_back(ss.str());
482   responses.push_back("OK");
483   client.SendCommandResponse(responses);
484 }
485 
486 /* AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS? */
HandleRequestOperator(const Client & client)487 void NetworkService::HandleRequestOperator(const Client& client) {
488   if (!IsHasNetwork()) {
489     client.SendCommandResponse(kCmeErrorOperationNotAllowed);
490     return;
491   }
492 
493   auto iter = operator_list_.begin();
494   for (; iter != operator_list_.end(); ++iter) {
495     if (iter->numeric == current_operator_numeric_) {
496       break;
497     }
498   }
499   if (iter == operator_list_.end()) {
500     client.SendCommandResponse(kCmeErrorNoNetworkService);
501     return;
502   }
503 
504   std::vector<std::string> responses;
505   std::vector<std::stringstream> ss;
506   ss.resize(3);
507 
508   ss[0] << "+COPS: 0,0," << iter->long_name;
509   ss[1] << "+COPS: 0,1," << iter->short_name;
510   ss[2] << "+COPS: 0,2," << iter->numeric;
511 
512   responses.push_back(ss[0].str());
513   responses.push_back(ss[1].str());
514   responses.push_back(ss[2].str());
515   responses.push_back("OK");
516 
517   client.SendCommandResponse(responses);
518 }
519 
520 /* AT+COPS=? */
HandleQueryAvailableNetwork(const Client & client)521 void NetworkService::HandleQueryAvailableNetwork(const Client& client) {
522   std::vector<std::string> responses;
523   std::stringstream ss;
524 
525   for (auto iter = operator_list_.begin(); iter != operator_list_.end(); ++iter) {
526     ss.clear();
527     ss << "+COPS: (" << iter->operator_state << ","
528                      << iter->long_name << ","
529                      << iter->short_name << ","
530                      << iter->numeric << "),";
531     responses.push_back(ss.str());
532     ss.str("");
533   }
534 
535   responses.push_back("OK");
536   client.SendCommandResponse(responses);
537 }
538 
539 /* AT+COPS=mode,format,operatorNumeric,act */
HandleSetNetworkSelectionMode(const Client & client,std::string & command)540 void NetworkService::HandleSetNetworkSelectionMode(const Client& client, std::string& command) {
541   std::vector<std::string> responses;
542   std::stringstream ss;
543 
544   CommandParser cmd(command);
545   cmd.SkipPrefix();
546 
547   int mode = (OperatorSelectionMode)cmd.GetNextInt();
548   cmd.SkipPrefix();  // Default to be numeric
549 
550   auto& registration_state = voice_registration_status_.registration_state;
551 
552   switch (mode) {
553     // <oper> field is ignored
554     case OperatorSelectionMode::OPER_SELECTION_AUTOMATIC: {
555       oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_AUTOMATIC;
556 
557       // The first operator stored in operator_list_ map default to be
558       // the automatic selected operator
559       auto iter = operator_list_.begin();
560       current_operator_numeric_ = iter->numeric;
561       iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
562 
563       // Change operator state stored in the operator_list_ map
564       ++iter;
565       for (; iter != operator_list_.end(); ++iter) {
566         if (iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
567           iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
568           break;
569         }
570       }
571 
572       registration_state = NET_REGISTRATION_HOME;
573       client.SendCommandResponse("OK");
574       break;
575     }
576 
577     // <oper> field shall be present, and <AcT> optionally
578     case OperatorSelectionMode::OPER_SELECTION_MANUAL: {
579       oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_MANUAL;
580       current_operator_numeric_ = cmd.GetNextStr();
581       auto iter = operator_list_.begin();
582       for (; iter != operator_list_.end(); ++iter) {
583         if (iter->numeric == current_operator_numeric_) {
584           break;
585         }
586       }
587       // If the selected operator is not available, no other operator shall be
588       // selected (except <mode>=4).
589       if (iter == operator_list_.end()) {
590         registration_state = NET_REGISTRATION_UNKNOWN;
591         client.SendCommandResponse(kCmeErrorNoNetworkService);
592         break;
593       }
594 
595       // Change operator state stored in the operator_list_ vector
596       iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
597       iter = operator_list_.begin();
598       for (; iter != operator_list_.end(); ++iter) {
599         if (iter->numeric != current_operator_numeric_ &&
600             iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
601           iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
602         }
603       }
604 
605       // If the selected access technology is not available, then the same operator
606       // shall be selected in other access technology
607       int act = cmd.GetNextInt();
608       if (act != -1) {
609         auto tech = getTechFromNetworkType((NetworkRegistrationStatus::AccessTechnoloy)act);
610         if (tech & modem_radio_capability_) {
611           current_network_mode_ = tech;
612         }  // else: remain current network mode unchanged
613       }  // else: remain act unchanged
614 
615       if (iter->operator_state == NetworkOperator::OPER_STATE_FORBIDDEN) {
616         registration_state = NET_REGISTRATION_DENIED;
617       } else if (iter->operator_state == NetworkOperator::OPER_STATE_UNKNOWN) {
618         registration_state = NET_REGISTRATION_UNKNOWN;
619       } else {
620         registration_state = NET_REGISTRATION_HOME;
621       }
622       client.SendCommandResponse("OK");
623       break;
624     }
625 
626     case OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION: {
627       oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_DEREGISTRATION;
628       registration_state = NET_REGISTRATION_UNREGISTERED;
629       client.SendCommandResponse("OK");
630       break;
631     }
632 
633     // <oper> field shall be present
634     case OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC: {
635       oper_selection_mode_ = OperatorSelectionMode::OPER_SELECTION_MANUAL_AUTOMATIC;
636       auto operator_numeric = cmd.GetNextStr();
637       // If manual selection fails, automatic mode (<mode>=0) is entered
638       auto iter = operator_list_.begin();
639       for (; iter != operator_list_.end(); ++iter) {
640         if (iter->numeric == operator_numeric) {
641           break;
642         }
643       }
644       // If the selected operator is not available, no other operator shall be
645       // selected (except <mode>=4)
646       if (iter != operator_list_.end() ||
647           iter->operator_state == NetworkOperator::OPER_STATE_AVAILABLE) {
648         current_operator_numeric_ = iter->numeric;
649       }
650 
651       // Change operator state stored in the operator_list_ vector
652       iter = operator_list_.begin();
653       for (; iter != operator_list_.end(); ++iter) {
654         if (iter->numeric == current_operator_numeric_) {
655           iter->operator_state = NetworkOperator::OPER_STATE_CURRENT;
656         } else if (iter->operator_state == NetworkOperator::OPER_STATE_CURRENT) {
657           iter->operator_state = NetworkOperator::OPER_STATE_AVAILABLE;
658         }
659       }
660 
661       registration_state = NET_REGISTRATION_HOME;
662       client.SendCommandResponse("OK");
663       break;
664     }
665 
666     default:
667       client.SendCommandResponse(kCmeErrorInCorrectParameters);
668       return;
669   }
670 
671   // Save the value anyway, no matter the value changes or not
672   auto nvram_config = NvramConfig::Get();
673   auto instance = nvram_config->ForInstance(service_id_);
674   instance.set_network_selection_mode(oper_selection_mode_);
675   instance.set_operator_numeric(current_operator_numeric_);
676 
677   NvramConfig::SaveToFile();
678 
679   thread_looper_->PostWithDelay(std::chrono::seconds(1),
680       makeSafeCallback(this, &NetworkService::UpdateRegisterState, registration_state));
681 }
682 
683 NetworkService::NetworkRegistrationStatus::AccessTechnoloy
getNetworkTypeFromTech(ModemTechnology modemTech)684 NetworkService::getNetworkTypeFromTech(ModemTechnology modemTech) {
685   switch (modemTech) {
686    case ModemTechnology::M_MODEM_TECH_GSM:
687      return NetworkRegistrationStatus::ACESS_TECH_EGPRS;
688    case ModemTechnology::M_MODEM_TECH_WCDMA:
689      return NetworkRegistrationStatus::ACESS_TECH_HSPA;
690    case ModemTechnology::M_MODEM_TECH_LTE:
691      return NetworkRegistrationStatus::ACESS_TECH_EUTRAN;
692    case ModemTechnology::M_MODEM_TECH_NR:
693      return NetworkRegistrationStatus::ACESS_TECH_NR;
694    default:
695      return NetworkRegistrationStatus::ACESS_TECH_EGPRS;
696   }
697 }
698 
getTechFromNetworkType(NetworkRegistrationStatus::AccessTechnoloy act)699 NetworkService::ModemTechnology NetworkService::getTechFromNetworkType(
700     NetworkRegistrationStatus::AccessTechnoloy act) {
701   switch (act) {
702     case NetworkRegistrationStatus::ACESS_TECH_GSM:
703     case NetworkRegistrationStatus::ACESS_TECH_GSM_COMPACT:
704     case NetworkRegistrationStatus::ACESS_TECH_EGPRS:
705     case NetworkRegistrationStatus::ACESS_TECH_EC_GSM_IoT:
706       return ModemTechnology::M_MODEM_TECH_GSM;
707 
708     case NetworkRegistrationStatus::ACESS_TECH_UTRAN:
709     case NetworkRegistrationStatus::ACESS_TECH_HSDPA:
710     case NetworkRegistrationStatus::ACESS_TECH_HSUPA:
711     case NetworkRegistrationStatus::ACESS_TECH_HSPA:
712       return ModemTechnology::M_MODEM_TECH_WCDMA;
713 
714     case NetworkRegistrationStatus::ACESS_TECH_EUTRAN:
715     case NetworkRegistrationStatus::ACESS_TECH_E_UTRAN:
716     case NetworkRegistrationStatus::ACESS_TECH_E_UTRA:
717       return ModemTechnology::M_MODEM_TECH_LTE;
718 
719     case NetworkRegistrationStatus::ACESS_TECH_NR:
720     case NetworkRegistrationStatus::ACESS_TECH_NG_RAN:
721     case NetworkRegistrationStatus::ACESS_TECH_E_UTRA_NR:
722       return ModemTechnology::M_MODEM_TECH_NR;
723 
724     default:
725       return ModemTechnology::M_MODEM_TECH_GSM;
726   }
727 }
728 
729 /**
730  * AT+CREG
731  *   Set command controls the presentation of an unsolicited result code
732  * +CREG: <stat> when <n>=1 and there is a change in the MT’s circuit
733  * mode network registration status in GERAN/UTRAN/E-UTRAN, or unsolicited
734  * result code +CREG: <stat>[,[<lac>],[<ci>],[<AcT>]]
735  * when <n>=2 and there is a change of the network cell in GERAN/UTRAN/E-UTRAN. The
736  * parameters <AcT>, <lac> and <ci> are sent only if available.
737  * The value <n>=3 further extends the unsolicited result code with [,<cause_type>,
738  * <reject_cause>], when available, when the value of <stat> changes.
739  *
740  * command             Possible response(s)
741  * +CREG=[<n>]         +CME ERROR: <err>
742  *
743  * +CREG?             +CREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>]
744  *                            [,<cause_type>,<reject_cause>]]
745  *
746  * <n>: integer type
747  *    0 disable network registration unsolicited result code
748  *    1 enable network registration unsolicited result code +CREG: <stat>
749  *    2 enable network registration and location information unsolicited
750  *      result code +CREG: <stat>[,[<lac>],[<ci>],[<AcT>]]
751  *    3 enable network registration, location information and cause value
752  *      information unsolicited result code +CREG: <stat>[,[<lac>],[<ci>],
753  *      [<AcT>][,<cause_type>,<reject_cause>]]
754  *
755  * <stat>: integer type;
756  *      0 not registered, MT is not currently searching a new operator to register to
757  *      1 registered, home network
758  *      2 not registered, but MT is currently searching a new operator to register to
759  *      3 registration denied
760  *      4 unknown (e.g. out of GERAN/UTRAN/E-UTRAN coverage)
761  *      5 registered, roaming
762  *
763  * <lac>: string type; two byte location area code (when <AcT> indicates
764  *        value 0 to 6), or tracking area code (when <AcT> indicates
765  *        value 7). In hexadecimal format
766  * <ci>: string type; four byte GERAN/UTRAN/E-UTRAN cell ID in
767  *       hexadecimal format
768  * <AcT>: refer line 190
769  *
770  * see RIL_REQUEST_VOICE_REGISTRATION_STATE or in RIL
771 */
HandleVoiceNetworkRegistration(const Client & client,std::string & command)772 void NetworkService::HandleVoiceNetworkRegistration(const Client& client,
773                                                     std::string& command) {
774   std::vector<std::string> responses;
775   std::stringstream ss;
776 
777   CommandParser cmd(command);
778   cmd.SkipPrefix();
779   if (*cmd == "AT+CREG?") {
780     ss << "+CREG: " << voice_registration_status_.unsol_mode << ","
781                     << voice_registration_status_.registration_state;
782     if (voice_registration_status_.unsol_mode ==
783             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL &&
784        (voice_registration_status_.registration_state ==
785             NET_REGISTRATION_HOME ||
786         voice_registration_status_.registration_state ==
787             NET_REGISTRATION_ROAMING ||
788         voice_registration_status_.registration_state ==
789             NET_REGISTRATION_EMERGENCY)) {
790       ss << ",\"" << kAreaCode << "\"" << ",\"" << kCellId << "\","
791                   << voice_registration_status_.network_type;
792     }
793 
794     responses.push_back(ss.str());
795   } else {
796     int n = cmd.GetNextInt();
797     switch (n) {
798       case 0:
799         voice_registration_status_.unsol_mode =
800             NetworkRegistrationStatus::REGISTRATION_UNSOL_DISABLED;
801         break;
802       case 1:
803         voice_registration_status_.unsol_mode =
804             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED;
805         break;
806       case 2:
807         voice_registration_status_.unsol_mode =
808             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL;
809         break;
810       default:
811         client.SendCommandResponse(kCmeErrorInCorrectParameters);
812         return;
813     }
814   }
815   responses.push_back("OK");
816   client.SendCommandResponse(responses);
817 }
818 
819 /**
820  * AT+CGREG
821  * The set command controls the presentation of an unsolicited result
822  *  code +CGREG: <stat> when <n>=1 and there is a change in the MT's
823  *  GPRS network registration status, or code +CGREG: <stat>[,<lac>,
824  *  <ci>[,<AcT>]] when <n>=2 and there is a change of the network cell.
825  *
826  * command             Possible response(s)
827  * +CGREG=[<n>]         +CME ERROR: <err>
828  *
829  * +CGREG?             when <n>=0, 1, 2 or 3 and command successful:
830  *                     +CGREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>],
831  *                             [<rac>][,<cause_type>,<reject_cause>]]
832  *                     when <n>=4 or 5 and command successful:
833  *                     +CGREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>],
834  *                             [<rac>][,[<cause_type>],[<reject_cause>][,
835  *                             [<Active-Time>],[<Periodic-RAU>],
836  *                             [<GPRS-READY-timer>]]]]
837  *                             [,<cause_type>,<reject_cause>]]
838  *
839  * note: see AT+CREG
840  *
841  * see  RIL_REQUEST_DATA_REGISTRATION_STATE in RIL
842  */
HandleDataNetworkRegistration(const Client & client,std::string & command)843 void NetworkService::HandleDataNetworkRegistration(const Client& client,
844                                                    std::string& command) {
845   std::vector<std::string> responses;
846   std::stringstream ss;
847   std::string prefix;
848 
849   CommandParser cmd(command);
850   cmd.SkipPrefix();
851   if (command.find("CGREG") != std::string::npos) {
852     prefix = "+CGREG: ";
853   } else if (command.find("CEREG") != std::string::npos){
854     prefix = "+CEREG: ";
855   }
856 
857   if (*cmd == "AT+CGREG?" || *cmd == "AT+CEREG?") {
858     ss << prefix << data_registration_status_.unsol_mode << ","
859                  << data_registration_status_.registration_state;
860     if (voice_registration_status_.unsol_mode ==
861             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL &&
862        (voice_registration_status_.registration_state ==
863             NET_REGISTRATION_HOME ||
864         voice_registration_status_.registration_state ==
865             NET_REGISTRATION_ROAMING ||
866         voice_registration_status_.registration_state ==
867             NET_REGISTRATION_EMERGENCY)) {
868       data_registration_status_.network_type =
869           getNetworkTypeFromTech(current_network_mode_);
870       ss << ",\"" << kAreaCode << "\"" << ",\"" << kCellId << "\"" << ","
871                   << data_registration_status_.network_type;
872     }
873     responses.push_back(ss.str());
874   } else {
875     int n = cmd.GetNextInt();
876     switch (n) {
877       case 0:
878         data_registration_status_.unsol_mode =
879             NetworkRegistrationStatus::REGISTRATION_UNSOL_DISABLED;
880         break;
881       case 1:
882         data_registration_status_.unsol_mode =
883             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED;
884         break;
885       case 2:
886         data_registration_status_.unsol_mode =
887             NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL;
888         break;
889       default:
890         client.SendCommandResponse(kCmeErrorInCorrectParameters);
891         return;
892     }
893   }
894   responses.push_back("OK");
895   client.SendCommandResponse(responses);
896 }
897 
898 /* AT+CTEC? */
HandleGetPreferredNetworkType(const Client & client)899 void NetworkService::HandleGetPreferredNetworkType(const Client& client) {
900   std::vector<std::string> responses;
901   std::stringstream ss;
902 
903   ss << "+CTEC: " << current_network_mode_ << "," << std::hex << preferred_network_mode_;
904 
905   responses.push_back(ss.str());
906   responses.push_back("OK");
907   client.SendCommandResponse(responses);
908 }
909 
910 /* AT+CTEC=? */
HandleQuerySupportedTechs(const Client & client)911 void NetworkService::HandleQuerySupportedTechs(const Client& client) {
912   std::vector<std::string> responses;
913   std::stringstream ss;
914   ss << "+CTEC: 0,1,5,6";  // NR | LTE | WCDMA | GSM
915   responses.push_back(ss.str());
916   responses.push_back("OK");
917   client.SendCommandResponse(responses);
918 }
919 
920 /**
921  * Preferred mode bitmask. This is actually 4 byte-sized bitmasks with different priority values,
922  * in which the byte number from LSB to MSB give the priority.
923  *
924  *          |MSB|   |   |LSB
925  * value:   |00 |00 |00 |00
926  * byte #:  |3  |2  |1  |0
927  *
928  * Higher byte order give higher priority. Thus, a value of 0x0000000f represents
929  * a preferred mode of GSM, WCDMA, CDMA, and EvDo in which all are equally preferrable, whereas
930  * 0x00000201 represents a mode with GSM and WCDMA, in which WCDMA is preferred over GSM
931  */
getModemTechFromPrefer(int preferred_mask)932 int NetworkService::getModemTechFromPrefer(int preferred_mask) {
933   int i, j;
934 
935   // Current implementation will only return the highest priority,
936   // lowest numbered technology that is set in the mask.
937   for (i = 3 ; i >= 0; i--) {
938     for (j = 7 ; j >= 0 ; j--) {
939       if (preferred_mask & (1 << (j + 8 * i)))
940           return 1 << j;
941     }
942   }
943   // This should never happen. Just to please the compiler.
944   return ModemTechnology::M_MODEM_TECH_GSM;
945 }
946 
UpdateRegisterState(RegistrationState state)947 void NetworkService::UpdateRegisterState(RegistrationState state ) {
948   voice_registration_status_.registration_state = state;
949   data_registration_status_.registration_state = state;
950   voice_registration_status_.network_type =
951       (NetworkRegistrationStatus::AccessTechnoloy)getNetworkTypeFromTech(current_network_mode_);
952   data_registration_status_.network_type =
953       (NetworkRegistrationStatus::AccessTechnoloy)getNetworkTypeFromTech(current_network_mode_);
954 
955   OnVoiceRegisterStateChanged();
956   OnDataRegisterStateChanged();
957   OnSignalStrengthChanged();
958 
959   int cellBandwidthDownlink = 5000;
960   const int UNKNOWN = 0;
961   const int MMWAVE = 4;
962   int freq = UNKNOWN;
963   if (current_network_mode_ == M_MODEM_TECH_NR) {
964     freq = MMWAVE;
965     cellBandwidthDownlink = 50000;
966   }
967 
968   data_service_->onUpdatePhysicalChannelconfigs(current_network_mode_, freq,
969                                                 cellBandwidthDownlink);
970 }
971 
972 /* AT+CTEC=current,preferred */
HandleSetPreferredNetworkType(const Client & client,std::string & command)973 void NetworkService::HandleSetPreferredNetworkType(const Client& client, std::string& command) {
974   std::vector<std::string> responses;
975   std::stringstream ss;
976   int preferred_mask_new;
977   CommandParser cmd(command);
978   cmd.SkipPrefix();
979 
980   int current = cmd.GetNextInt();
981   std::string preferred(cmd.GetNextStr());
982   preferred_mask_new = std::stoi(preferred, nullptr, 16);
983   if (preferred_mask_new != preferred_network_mode_) {
984     current_network_mode_ = (ModemTechnology)getModemTechFromPrefer(preferred_mask_new);
985     preferred_network_mode_ = preferred_mask_new;
986   }
987 
988   if (current != current_network_mode_) {
989     UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
990     signal_strength_.Reset();
991 
992     ss << "+CTEC: "<< current_network_mode_;
993 
994     thread_looper_->PostWithDelay(std::chrono::milliseconds(200),
995         makeSafeCallback(this, &NetworkService::UpdateRegisterState,
996             NET_REGISTRATION_HOME));
997   } else {
998     ss << "+CTEC: DONE";
999   }
1000 
1001   auto nvram_config = NvramConfig::Get();
1002   auto instance = nvram_config->ForInstance(service_id_);
1003   instance.set_modem_technoloy(current_network_mode_);
1004   instance.set_preferred_network_mode(preferred_network_mode_);
1005 
1006   NvramConfig::SaveToFile();
1007 
1008   responses.push_back(ss.str());
1009   responses.push_back("OK");
1010   client.SendCommandResponse(responses);
1011 }
1012 
OnVoiceRegisterStateChanged()1013 void NetworkService::OnVoiceRegisterStateChanged() {
1014   std::stringstream ss;
1015 
1016   switch (voice_registration_status_.unsol_mode) {
1017     case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED:
1018       ss << "+CREG: " << voice_registration_status_.registration_state;
1019       break;
1020     case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL:
1021       ss << "+CREG: " << voice_registration_status_.registration_state;
1022       if (voice_registration_status_.registration_state ==
1023               NET_REGISTRATION_HOME ||
1024           voice_registration_status_.registration_state ==
1025               NET_REGISTRATION_ROAMING) {
1026         ss << ",\""<< kAreaCode << "\",\"" << kCellId << "\","
1027                  << voice_registration_status_.network_type;
1028       }
1029       break;
1030     default :
1031       return;
1032   }
1033   SendUnsolicitedCommand(ss.str());
1034 }
1035 
OnDataRegisterStateChanged()1036 void NetworkService::OnDataRegisterStateChanged() {
1037   std::stringstream ss;
1038 
1039   switch (data_registration_status_.unsol_mode) {
1040     case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED:
1041       ss << "+CGREG: " << data_registration_status_.registration_state;
1042       if (data_registration_status_.network_type ==
1043               NetworkRegistrationStatus::ACESS_TECH_EUTRAN) {
1044         ss << "\r+CEREG: " << data_registration_status_.registration_state;
1045       }
1046       break;
1047     case NetworkRegistrationStatus::REGISTRATION_UNSOL_ENABLED_FULL:
1048       ss << "+CGREG: " << data_registration_status_.registration_state;
1049       if (data_registration_status_.registration_state ==
1050                 NET_REGISTRATION_HOME ||
1051           data_registration_status_.registration_state ==
1052                 NET_REGISTRATION_ROAMING) {
1053         ss << ",\"" << kAreaCode << "\",\"" << kCellId << "\","
1054            << data_registration_status_.network_type;
1055       }
1056       if (data_registration_status_.network_type ==
1057                 NetworkRegistrationStatus::ACESS_TECH_EUTRAN) {
1058           ss << "\r+CEREG: " << data_registration_status_.registration_state;
1059           if (data_registration_status_.registration_state ==
1060                   NET_REGISTRATION_HOME ||
1061               data_registration_status_.registration_state ==
1062                   NET_REGISTRATION_ROAMING) {
1063             ss << ",\"" << kAreaCode << "\",\"" << kCellId << "\","
1064                       << data_registration_status_.network_type;
1065           }
1066       }
1067       break;
1068     default:
1069       return;
1070   }
1071   SendUnsolicitedCommand(ss.str());
1072 }
1073 
GetSignalStrength()1074 std::string NetworkService::GetSignalStrength() {
1075   switch (current_network_mode_) {
1076     case M_MODEM_TECH_GSM:
1077       signal_strength_.gsm_rssi += (rand() % 3 - 1);
1078       AdjustSignalStrengthValue(signal_strength_.gsm_rssi, kGSMSignalStrength);
1079       break;
1080     case M_MODEM_TECH_CDMA:
1081       signal_strength_.cdma_dbm += (rand() % 3 - 1);
1082       AdjustSignalStrengthValue(signal_strength_.cdma_dbm, kCDMASignalStrength);
1083       break;
1084     case M_MODEM_TECH_EVDO:
1085       signal_strength_.evdo_dbm += (rand() % 3 - 1);
1086       AdjustSignalStrengthValue(signal_strength_.evdo_dbm, kEVDOSignalStrength);
1087       break;
1088     case M_MODEM_TECH_LTE:
1089       signal_strength_.lte_rssi += (rand() % 3 - 1);
1090       AdjustSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength);
1091       break;
1092     case M_MODEM_TECH_WCDMA:
1093       signal_strength_.wcdma_rssi += (rand() % 3 - 1);
1094       AdjustSignalStrengthValue(signal_strength_.wcdma_rssi, kWCDMASignalStrength);
1095       break;
1096     case M_MODEM_TECH_NR:
1097       signal_strength_.nr_ss_rsrp += (rand() % 3 - 1);
1098       AdjustSignalStrengthValue(signal_strength_.nr_ss_rsrp, kNRSignalStrength);
1099       break;
1100     default:
1101       break;
1102   }
1103 
1104   std::stringstream ss;
1105   ss << "+CSQ: " << signal_strength_.gsm_rssi << ","
1106                  << signal_strength_.gsm_ber << ","
1107                  << signal_strength_.cdma_dbm << ","
1108                  << signal_strength_.cdma_ecio << ","
1109                  << signal_strength_.evdo_dbm << ","
1110                  << signal_strength_.evdo_ecio << ","
1111                  << signal_strength_.evdo_snr << ","
1112                  << signal_strength_.lte_rssi << ","
1113                  << signal_strength_.lte_rsrp << ","
1114                  << signal_strength_.lte_rsrq << ","
1115                  << signal_strength_.lte_rssnr << ","
1116                  << signal_strength_.lte_cqi << ","
1117                  << signal_strength_.lte_ta << ","
1118                  << signal_strength_.tdscdma_rscp << ","
1119                  << signal_strength_.wcdma_rssi << ","
1120                  << signal_strength_.wcdma_ber << ","
1121                  << signal_strength_.nr_ss_rsrp << ","
1122                  << signal_strength_.nr_ss_rsrq << ","
1123                  << signal_strength_.nr_ss_sinr << ","
1124                  << signal_strength_.nr_csi_rsrp << ","
1125                  << signal_strength_.nr_csi_rsrq << ","
1126                  << signal_strength_.nr_csi_sinr;;
1127   return ss.str();
1128 }
1129 
1130 /* AT+REMOTEREG: state*/
HandleReceiveRemoteVoiceDataReg(const Client & client,std::string & command)1131 void NetworkService::HandleReceiveRemoteVoiceDataReg(const Client& client,
1132                                                      std::string& command) {
1133   (void)client;
1134   std::stringstream ss;
1135   std::string states = command.substr(std::string("AT+REMOTEREG:").size());
1136   int stated = std::stoi(states, nullptr, 10);
1137 
1138   UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
1139   signal_strength_.Reset();
1140 
1141   thread_looper_->PostWithDelay(
1142       std::chrono::seconds(1),
1143       makeSafeCallback(this, &NetworkService::UpdateRegisterState,
1144                        (cuttlefish::NetworkService::RegistrationState)stated));
1145 }
1146 
1147 /* AT+REMOTECTEC: ctec */
HandleReceiveRemoteCTEC(const Client & client,std::string & command)1148 void NetworkService::HandleReceiveRemoteCTEC(const Client& client,
1149                                              std::string& command) {
1150   (void)client;
1151   LOG(DEBUG) << "calling ctec from remote";
1152   std::stringstream ss;
1153   std::string types = command.substr(std::string("AT+REMOTECTEC: ").size());
1154   int preferred_mask_new = std::stoi(types, nullptr, 10);
1155 
1156   if (preferred_mask_new != preferred_network_mode_) {
1157     preferred_network_mode_ = preferred_mask_new;
1158   }
1159   auto current_network_mode_new =
1160       (ModemTechnology)getModemTechFromPrefer(preferred_mask_new);
1161   if (current_network_mode_new != current_network_mode_) {
1162     current_network_mode_ = current_network_mode_new;
1163     auto saved_state = voice_registration_status_.registration_state;
1164     UpdateRegisterState(NET_REGISTRATION_UNREGISTERED);
1165     signal_strength_.Reset();
1166 
1167     ss << "+CTEC: " << current_network_mode_;
1168 
1169     thread_looper_->PostWithDelay(
1170         std::chrono::seconds(1),
1171         makeSafeCallback(this, &NetworkService::UpdateRegisterState,
1172                          saved_state));
1173   }
1174 }
1175 
applySignalPercentage(double percentd)1176 void NetworkService::applySignalPercentage(double percentd) {
1177   switch (current_network_mode_) {
1178     case M_MODEM_TECH_GSM:
1179       signal_strength_.gsm_rssi = 99;
1180       signal_strength_.gsm_ber = 0;
1181       SetSignalStrengthValue(signal_strength_.gsm_rssi, kGSMSignalStrength,
1182                              percentd);
1183       break;
1184     case M_MODEM_TECH_CDMA:
1185       signal_strength_.cdma_dbm = 125;
1186       signal_strength_.cdma_ecio = 165;
1187       SetSignalStrengthValue(signal_strength_.cdma_dbm, kCDMASignalStrength,
1188                              percentd);
1189       break;
1190     case M_MODEM_TECH_EVDO:
1191       signal_strength_.evdo_dbm = 125;
1192       signal_strength_.evdo_ecio = 165;
1193       signal_strength_.evdo_snr = -1;
1194       SetSignalStrengthValue(signal_strength_.evdo_dbm, kEVDOSignalStrength,
1195                              percentd);
1196       break;
1197     case M_MODEM_TECH_LTE:
1198       signal_strength_.lte_rssi = 99;
1199       signal_strength_.lte_rsrp = -1;
1200       signal_strength_.lte_rsrq = -5;
1201       signal_strength_.lte_rssnr = -205;
1202       signal_strength_.lte_cqi = -1;
1203       signal_strength_.lte_ta = -1;
1204       SetSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength,
1205                              percentd);
1206       break;
1207     case M_MODEM_TECH_WCDMA:
1208       signal_strength_.tdscdma_rscp = 99;
1209       signal_strength_.wcdma_rssi = 99;
1210       signal_strength_.wcdma_ber = 0;
1211       SetSignalStrengthValue(signal_strength_.wcdma_rssi, kWCDMASignalStrength,
1212                              percentd);
1213       break;
1214     case M_MODEM_TECH_NR:
1215       // special for NR: it uses LTE as primary, so LTE signal strength is
1216       // needed as well
1217       signal_strength_.lte_rssi = 99;
1218       signal_strength_.lte_rsrp = -1;
1219       signal_strength_.lte_rsrq = -5;
1220       signal_strength_.lte_rssnr = -205;
1221       signal_strength_.lte_cqi = -1;
1222       signal_strength_.lte_ta = -1;
1223       SetSignalStrengthValue(signal_strength_.lte_rssi, kLTESignalStrength,
1224                              percentd);
1225       signal_strength_.nr_ss_rsrp = 0;
1226       signal_strength_.nr_ss_rsrq = 0;
1227       signal_strength_.nr_ss_sinr = 45;
1228       signal_strength_.nr_csi_rsrp = 0;
1229       signal_strength_.nr_csi_rsrq = 0;
1230       signal_strength_.nr_csi_sinr = 30;
1231       SetSignalStrengthValue(signal_strength_.nr_ss_rsrp, kNRSignalStrength,
1232                              percentd);
1233       break;
1234     default:
1235       break;
1236   }
1237 }
1238 
1239 /* AT+REMOTESIGNAL: percent */
HandleReceiveRemoteSignal(const Client & client,std::string & command)1240 void NetworkService::HandleReceiveRemoteSignal(const Client& client,
1241                                                std::string& command) {
1242   (void)client;
1243   std::stringstream ss;
1244   std::string percents = command.substr(std::string("AT+REMOTESIGNAL:").size());
1245   double percentd = std::stoi(percents, nullptr, 10) / 100.0;
1246 
1247   if (percentd >= 0 && percentd <= 1.0) {
1248     percentd_ = percentd;
1249   } else {
1250     LOG(DEBUG) << "out of bound signal strength: " << percentd;
1251     return;
1252   }
1253 
1254   OnSignalStrengthChanged();
1255 }
1256 
OnSignalStrengthChanged()1257 void NetworkService::OnSignalStrengthChanged() {
1258   applySignalPercentage(percentd_);
1259   auto command = GetSignalStrength();
1260   SendUnsolicitedCommand(command);
1261 }
1262 
GetVoiceRegistrationState() const1263 NetworkService::RegistrationState NetworkService::GetVoiceRegistrationState() const {
1264   return voice_registration_status_.registration_state;
1265 }
1266 }  // namespace cuttlefish
1267