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