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