1 //
2 // Copyright (C) 2013 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 
17 #include "shill/cellular/cellular_capability_universal_cdma.h"
18 
19 #include <base/strings/string_number_conversions.h>
20 #include <base/strings/string_util.h>
21 #include <base/strings/stringprintf.h>
22 #if defined(__ANDROID__)
23 #include <dbus/service_constants.h>
24 #else
25 #include <chromeos/dbus/service_constants.h>
26 #endif  // __ANDROID__
27 
28 #include "shill/cellular/cellular_bearer.h"
29 #include "shill/cellular/cellular_service.h"
30 #include "shill/control_interface.h"
31 #include "shill/dbus_properties_proxy_interface.h"
32 #include "shill/error.h"
33 #include "shill/logging.h"
34 #include "shill/pending_activation_store.h"
35 
36 #ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
37 #error "Do not include mm-modem.h"
38 #endif
39 
40 using base::UintToString;
41 
42 using std::string;
43 using std::vector;
44 
45 namespace shill {
46 
47 namespace Logging {
48 static auto kModuleLogScope = ScopeLogger::kCellular;
ObjectID(CellularCapabilityUniversalCDMA * c)49 static string ObjectID(CellularCapabilityUniversalCDMA* c) {
50   return c->cellular()->GetRpcIdentifier();
51 }
52 }
53 
54 namespace {
55 
56 const char kPhoneNumber[] = "#777";
57 const char kPropertyConnectNumber[] = "number";
58 
59 }  // namespace
60 
CellularCapabilityUniversalCDMA(Cellular * cellular,ControlInterface * control_interface,ModemInfo * modem_info)61 CellularCapabilityUniversalCDMA::CellularCapabilityUniversalCDMA(
62     Cellular* cellular,
63     ControlInterface* control_interface,
64     ModemInfo* modem_info)
65     : CellularCapabilityUniversal(cellular, control_interface, modem_info),
66       weak_cdma_ptr_factory_(this),
67       activation_state_(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
68       cdma_1x_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
69       cdma_evdo_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
70       nid_(0),
71       sid_(0) {
72   SLOG(this, 2) << "Cellular capability constructed: Universal CDMA";
73   // TODO(armansito): Update PRL for activation over cellular.
74   // See crbug.com/197330.
75 }
76 
~CellularCapabilityUniversalCDMA()77 CellularCapabilityUniversalCDMA::~CellularCapabilityUniversalCDMA() {}
78 
InitProxies()79 void CellularCapabilityUniversalCDMA::InitProxies() {
80   SLOG(this, 2) << __func__;
81   modem_cdma_proxy_.reset(
82       control_interface()->CreateMM1ModemModemCdmaProxy(
83           cellular()->dbus_path(), cellular()->dbus_service()));
84   modem_cdma_proxy_->set_activation_state_callback(
85       Bind(&CellularCapabilityUniversalCDMA::OnActivationStateChangedSignal,
86       weak_cdma_ptr_factory_.GetWeakPtr()));
87   CellularCapabilityUniversal::InitProxies();
88 }
89 
ReleaseProxies()90 void CellularCapabilityUniversalCDMA::ReleaseProxies() {
91   SLOG(this, 2) << __func__;
92   modem_cdma_proxy_.reset();
93   CellularCapabilityUniversal::ReleaseProxies();
94 }
95 
Activate(const string & carrier,Error * error,const ResultCallback & callback)96 void CellularCapabilityUniversalCDMA::Activate(const string& carrier,
97                                                Error* error,
98                                                const ResultCallback& callback) {
99   // Currently activation over the cellular network is not supported using
100   // ModemManager-next. Service activation is currently carried through over
101   // non-cellular networks and only the final step of the OTA activation
102   // procedure ("automatic activation") is performed by this class.
103   OnUnsupportedOperation(__func__, error);
104 }
105 
CompleteActivation(Error * error)106 void CellularCapabilityUniversalCDMA::CompleteActivation(Error* error) {
107   SLOG(this, 2) << __func__;
108   if (cellular()->state() < Cellular::kStateEnabled) {
109     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
110                           "Unable to activate in state " +
111                           Cellular::GetStateString(cellular()->state()));
112     return;
113   }
114   ActivateAutomatic();
115 }
116 
ActivateAutomatic()117 void CellularCapabilityUniversalCDMA::ActivateAutomatic() {
118   if (!cellular()->serving_operator_info()->IsMobileNetworkOperatorKnown() ||
119       cellular()->serving_operator_info()->activation_code().empty()) {
120     SLOG(this, 2) << "OTA activation cannot be run in the presence of no "
121                   << "activation code.";
122     return;
123   }
124 
125   PendingActivationStore::State state =
126       modem_info()->pending_activation_store()->GetActivationState(
127           PendingActivationStore::kIdentifierMEID, cellular()->meid());
128   if (state == PendingActivationStore::kStatePending) {
129     SLOG(this, 2) << "There's already a pending activation. Ignoring.";
130     return;
131   }
132   if (state == PendingActivationStore::kStateActivated) {
133     SLOG(this, 2) << "A call to OTA activation has already completed "
134                   << "successfully. Ignoring.";
135     return;
136   }
137 
138   // Mark as pending activation, so that shill can recover if anything fails
139   // during OTA activation.
140   modem_info()->pending_activation_store()->SetActivationState(
141       PendingActivationStore::kIdentifierMEID,
142       cellular()->meid(),
143       PendingActivationStore::kStatePending);
144 
145   // Initiate OTA activation.
146   ResultCallback activation_callback =
147     Bind(&CellularCapabilityUniversalCDMA::OnActivateReply,
148          weak_cdma_ptr_factory_.GetWeakPtr(),
149          ResultCallback());
150 
151   Error error;
152   modem_cdma_proxy_->Activate(
153       cellular()->serving_operator_info()->activation_code(),
154       &error,
155       activation_callback,
156       kTimeoutActivate);
157 }
158 
UpdatePendingActivationState()159 void CellularCapabilityUniversalCDMA::UpdatePendingActivationState() {
160   SLOG(this, 2) << __func__;
161   if (IsActivated()) {
162     SLOG(this, 3) << "CDMA service activated. Clear store.";
163     modem_info()->pending_activation_store()->RemoveEntry(
164         PendingActivationStore::kIdentifierMEID, cellular()->meid());
165     return;
166   }
167   PendingActivationStore::State state =
168       modem_info()->pending_activation_store()->GetActivationState(
169           PendingActivationStore::kIdentifierMEID, cellular()->meid());
170   if (IsActivating() && state != PendingActivationStore::kStateFailureRetry) {
171     SLOG(this, 3) << "OTA activation in progress. Nothing to do.";
172     return;
173   }
174   switch (state) {
175     case PendingActivationStore::kStateFailureRetry:
176       SLOG(this, 3) << "OTA activation failed. Scheduling a retry.";
177       cellular()->dispatcher()->PostTask(
178           Bind(&CellularCapabilityUniversalCDMA::ActivateAutomatic,
179                weak_cdma_ptr_factory_.GetWeakPtr()));
180       break;
181     case PendingActivationStore::kStateActivated:
182       SLOG(this, 3) << "OTA Activation has completed successfully. "
183                     << "Waiting for activation state update to finalize.";
184       break;
185     default:
186       break;
187   }
188 }
189 
IsServiceActivationRequired() const190 bool CellularCapabilityUniversalCDMA::IsServiceActivationRequired() const {
191   // If there is no online payment portal information, it's safer to assume
192   // the service does not require activation.
193   if (!cellular()->serving_operator_info()->IsMobileNetworkOperatorKnown() ||
194       cellular()->serving_operator_info()->olp_list().empty()) {
195     return false;
196   }
197 
198   // We could also use the MDN to determine whether or not the service is
199   // activated, however, the CDMA ActivatonState property is a more absolute
200   // and fine-grained indicator of activation status.
201   return (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED);
202 }
203 
IsActivated() const204 bool CellularCapabilityUniversalCDMA::IsActivated() const {
205   return (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED);
206 }
207 
OnServiceCreated()208 void CellularCapabilityUniversalCDMA::OnServiceCreated() {
209   SLOG(this, 2) << __func__;
210   cellular()->service()->SetActivationType(
211       CellularService::kActivationTypeOTASP);
212   UpdateServiceActivationStateProperty();
213   HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
214   UpdatePendingActivationState();
215 }
216 
UpdateServiceActivationStateProperty()217 void CellularCapabilityUniversalCDMA::UpdateServiceActivationStateProperty() {
218   string activation_state;
219   if (IsActivating())
220       activation_state = kActivationStateActivating;
221   else if (IsServiceActivationRequired())
222       activation_state = kActivationStateNotActivated;
223   else
224       activation_state = kActivationStateActivated;
225   cellular()->service()->SetActivationState(activation_state);
226 }
227 
UpdateServiceOLP()228 void CellularCapabilityUniversalCDMA::UpdateServiceOLP() {
229   SLOG(this, 2) << __func__;
230 
231   // In this case, the Home Provider is trivial. All information comes from the
232   // Serving Operator.
233   if (!cellular()->serving_operator_info()->IsMobileNetworkOperatorKnown()) {
234     return;
235   }
236 
237   const vector<MobileOperatorInfo::OnlinePortal>& olp_list =
238       cellular()->serving_operator_info()->olp_list();
239   if (olp_list.empty()) {
240     return;
241   }
242 
243   if (olp_list.size() > 1) {
244     SLOG(this, 1) << "Found multiple online portals. Choosing the first.";
245   }
246   string post_data = olp_list[0].post_data;
247   base::ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}",
248                                      cellular()->esn());
249   base::ReplaceSubstringsAfterOffset(
250       &post_data, 0, "${mdn}",
251       GetMdnForOLP(cellular()->serving_operator_info()));
252   base::ReplaceSubstringsAfterOffset(&post_data, 0,
253                                      "${meid}", cellular()->meid());
254   base::ReplaceSubstringsAfterOffset(&post_data, 0, "${oem}", "GOG2");
255   cellular()->service()->SetOLP(olp_list[0].url, olp_list[0].method, post_data);
256 }
257 
GetProperties()258 void CellularCapabilityUniversalCDMA::GetProperties() {
259   SLOG(this, 2) << __func__;
260   CellularCapabilityUniversal::GetProperties();
261 
262   std::unique_ptr<DBusPropertiesProxyInterface> properties_proxy(
263       control_interface()->CreateDBusPropertiesProxy(
264           cellular()->dbus_path(), cellular()->dbus_service()));
265 
266   KeyValueStore properties(
267       properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM_MODEMCDMA));
268   OnModemCDMAPropertiesChanged(properties, vector<string>());
269 }
270 
OnActivationStateChangedSignal(uint32_t activation_state,uint32_t activation_error,const KeyValueStore & status_changes)271 void CellularCapabilityUniversalCDMA::OnActivationStateChangedSignal(
272     uint32_t activation_state,
273     uint32_t activation_error,
274     const KeyValueStore& status_changes) {
275   SLOG(this, 2) << __func__;
276 
277   activation_state_ =
278       static_cast<MMModemCdmaActivationState>(activation_state);
279 
280   string value;
281   if (status_changes.ContainsString("mdn"))
282     cellular()->set_mdn(status_changes.GetString("mdn"));
283   if (status_changes.ContainsString("min"))
284     cellular()->set_min(status_changes.GetString("min"));
285   SLOG(this, 2) << "Activation state: "
286                 << GetActivationStateString(activation_state_);
287 
288   HandleNewActivationStatus(activation_error);
289   UpdatePendingActivationState();
290 }
291 
OnActivateReply(const ResultCallback & callback,const Error & error)292 void CellularCapabilityUniversalCDMA::OnActivateReply(
293     const ResultCallback& callback,
294     const Error& error) {
295   SLOG(this, 2) << __func__;
296   if (error.IsSuccess()) {
297     LOG(INFO) << "Activation completed successfully.";
298     modem_info()->pending_activation_store()->SetActivationState(
299         PendingActivationStore::kIdentifierMEID,
300         cellular()->meid(),
301         PendingActivationStore::kStateActivated);
302   } else {
303     LOG(ERROR) << "Activation failed with error: " << error;
304     modem_info()->pending_activation_store()->SetActivationState(
305         PendingActivationStore::kIdentifierMEID,
306         cellular()->meid(),
307         PendingActivationStore::kStateFailureRetry);
308   }
309   UpdatePendingActivationState();
310 
311   // CellularCapabilityUniversalCDMA::ActivateAutomatic passes a dummy
312   // ResultCallback when it calls Activate on the proxy object, in which case
313   // |callback.is_null()| will return true.
314   if (!callback.is_null())
315     callback.Run(error);
316 }
317 
HandleNewActivationStatus(uint32_t error)318 void CellularCapabilityUniversalCDMA::HandleNewActivationStatus(
319     uint32_t error) {
320   SLOG(this, 2) << __func__ << "(" << error << ")";
321   if (!cellular()->service().get()) {
322     LOG(ERROR) << "In " << __func__ << "(): service is null.";
323     return;
324   }
325   SLOG(this, 2) << "Activation State: " << activation_state_;
326   cellular()->service()->SetActivationState(
327       GetActivationStateString(activation_state_));
328   cellular()->service()->set_error(GetActivationErrorString(error));
329   UpdateServiceOLP();
330 }
331 
332 // static
GetActivationStateString(uint32_t state)333 string CellularCapabilityUniversalCDMA::GetActivationStateString(
334     uint32_t state) {
335   switch (state) {
336     case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
337       return kActivationStateActivated;
338     case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
339       return kActivationStateActivating;
340     case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
341       return kActivationStateNotActivated;
342     case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
343       return kActivationStatePartiallyActivated;
344     default:
345       return kActivationStateUnknown;
346   }
347 }
348 
349 // static
GetActivationErrorString(uint32_t error)350 string CellularCapabilityUniversalCDMA::GetActivationErrorString(
351     uint32_t error) {
352   switch (error) {
353     case MM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
354       return kErrorNeedEvdo;
355     case MM_CDMA_ACTIVATION_ERROR_ROAMING:
356       return kErrorNeedHomeNetwork;
357     case MM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
358     case MM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
359     case MM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
360       return kErrorOtaspFailed;
361     case MM_CDMA_ACTIVATION_ERROR_NONE:
362       return "";
363     case MM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
364     default:
365       return kErrorActivationFailed;
366   }
367 }
368 
Register(const ResultCallback & callback)369 void CellularCapabilityUniversalCDMA::Register(const ResultCallback& callback) {
370   // TODO(armansito): Remove once 3GPP is implemented in its own class.
371 }
372 
RegisterOnNetwork(const string & network_id,Error * error,const ResultCallback & callback)373 void CellularCapabilityUniversalCDMA::RegisterOnNetwork(
374     const string& network_id,
375     Error* error,
376     const ResultCallback& callback) {
377   // TODO(armansito): Remove once 3GPP is implemented in its own class.
378 }
379 
IsActivating() const380 bool CellularCapabilityUniversalCDMA::IsActivating() const {
381   PendingActivationStore::State state =
382       modem_info()->pending_activation_store()->GetActivationState(
383           PendingActivationStore::kIdentifierMEID, cellular()->meid());
384   return (state == PendingActivationStore::kStatePending) ||
385       (state == PendingActivationStore::kStateFailureRetry) ||
386       (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING);
387 }
388 
IsRegistered() const389 bool CellularCapabilityUniversalCDMA::IsRegistered() const {
390   return (cdma_1x_registration_state_ !=
391               MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
392           cdma_evdo_registration_state_ !=
393               MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN);
394 }
395 
SetUnregistered(bool)396 void CellularCapabilityUniversalCDMA::SetUnregistered(bool /*searching*/) {
397   cdma_1x_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
398   cdma_evdo_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
399 }
400 
SetupConnectProperties(KeyValueStore * properties)401 void CellularCapabilityUniversalCDMA::SetupConnectProperties(
402     KeyValueStore* properties) {
403   properties->SetString(kPropertyConnectNumber, kPhoneNumber);
404 }
405 
RequirePIN(const string & pin,bool require,Error * error,const ResultCallback & callback)406 void CellularCapabilityUniversalCDMA::RequirePIN(
407     const string& pin, bool require,
408     Error* error, const ResultCallback& callback) {
409   // TODO(armansito): Remove once 3GPP is implemented in its own class.
410 }
411 
EnterPIN(const string & pin,Error * error,const ResultCallback & callback)412 void CellularCapabilityUniversalCDMA::EnterPIN(
413     const string& pin,
414     Error* error,
415     const ResultCallback& callback) {
416   // TODO(armansito): Remove once 3GPP is implemented in its own class.
417 }
418 
UnblockPIN(const string & unblock_code,const string & pin,Error * error,const ResultCallback & callback)419 void CellularCapabilityUniversalCDMA::UnblockPIN(
420     const string& unblock_code,
421     const string& pin,
422     Error* error,
423     const ResultCallback& callback) {
424   // TODO(armansito): Remove once 3GPP is implemented in its own class.
425 }
426 
ChangePIN(const string & old_pin,const string & new_pin,Error * error,const ResultCallback & callback)427 void CellularCapabilityUniversalCDMA::ChangePIN(
428     const string& old_pin, const string& new_pin,
429     Error* error, const ResultCallback& callback) {
430   // TODO(armansito): Remove once 3GPP is implemented in its own class.
431 }
432 
Scan(Error * error,const ResultStringmapsCallback & callback)433 void CellularCapabilityUniversalCDMA::Scan(
434     Error* error,
435     const ResultStringmapsCallback& callback) {
436   // TODO(armansito): Remove once 3GPP is implemented in its own class.
437   OnUnsupportedOperation(__func__, error);
438 }
439 
OnSimPathChanged(const string & sim_path)440 void CellularCapabilityUniversalCDMA::OnSimPathChanged(
441     const string& sim_path) {
442   // TODO(armansito): Remove once 3GPP is implemented in its own class.
443 }
444 
GetRoamingStateString() const445 string CellularCapabilityUniversalCDMA::GetRoamingStateString() const {
446   uint32_t state = cdma_evdo_registration_state_;
447   if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
448     state = cdma_1x_registration_state_;
449   }
450   switch (state) {
451     case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
452     case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
453       break;
454     case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
455       return kRoamingStateHome;
456     case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
457       return kRoamingStateRoaming;
458     default:
459       NOTREACHED();
460   }
461   return kRoamingStateUnknown;
462 }
463 
OnPropertiesChanged(const string & interface,const KeyValueStore & changed_properties,const vector<string> & invalidated_properties)464 void CellularCapabilityUniversalCDMA::OnPropertiesChanged(
465     const string& interface,
466     const KeyValueStore& changed_properties,
467     const vector<string>& invalidated_properties) {
468   SLOG(this, 2) << __func__ << "(" << interface << ")";
469   if (interface == MM_DBUS_INTERFACE_MODEM_MODEMCDMA) {
470     OnModemCDMAPropertiesChanged(changed_properties, invalidated_properties);
471   } else {
472     CellularCapabilityUniversal::OnPropertiesChanged(
473         interface, changed_properties, invalidated_properties);
474   }
475 }
476 
OnModemCDMAPropertiesChanged(const KeyValueStore & properties,const std::vector<std::string> &)477 void CellularCapabilityUniversalCDMA::OnModemCDMAPropertiesChanged(
478     const KeyValueStore& properties,
479     const std::vector<std::string>& /*invalidated_properties*/) {
480   SLOG(this, 2) << __func__;
481   string str_value;
482   if (properties.ContainsString(MM_MODEM_MODEMCDMA_PROPERTY_MEID)) {
483     cellular()->set_meid(
484         properties.GetString(MM_MODEM_MODEMCDMA_PROPERTY_MEID));
485   }
486   if (properties.ContainsString(MM_MODEM_MODEMCDMA_PROPERTY_ESN)) {
487     cellular()->set_esn(properties.GetString(MM_MODEM_MODEMCDMA_PROPERTY_ESN));
488   }
489 
490   uint32_t sid = sid_;
491   uint32_t nid = nid_;
492   MMModemCdmaRegistrationState state_1x = cdma_1x_registration_state_;
493   MMModemCdmaRegistrationState state_evdo = cdma_evdo_registration_state_;
494   bool registration_changed = false;
495   if (properties.ContainsUint(
496       MM_MODEM_MODEMCDMA_PROPERTY_CDMA1XREGISTRATIONSTATE)) {
497     state_1x = static_cast<MMModemCdmaRegistrationState>(
498         properties.GetUint(
499             MM_MODEM_MODEMCDMA_PROPERTY_CDMA1XREGISTRATIONSTATE));
500     registration_changed = true;
501   }
502   if (properties.ContainsUint(
503       MM_MODEM_MODEMCDMA_PROPERTY_EVDOREGISTRATIONSTATE)) {
504     state_evdo = static_cast<MMModemCdmaRegistrationState>(
505         properties.GetUint(MM_MODEM_MODEMCDMA_PROPERTY_EVDOREGISTRATIONSTATE));
506     registration_changed = true;
507   }
508   if (properties.ContainsUint(MM_MODEM_MODEMCDMA_PROPERTY_SID)) {
509     sid = properties.GetUint(MM_MODEM_MODEMCDMA_PROPERTY_SID);
510     registration_changed = true;
511   }
512   if (properties.ContainsUint(MM_MODEM_MODEMCDMA_PROPERTY_NID)) {
513     nid = properties.GetUint(MM_MODEM_MODEMCDMA_PROPERTY_NID);
514     registration_changed = true;
515   }
516   if (properties.ContainsUint(MM_MODEM_MODEMCDMA_PROPERTY_ACTIVATIONSTATE)) {
517     activation_state_ = static_cast<MMModemCdmaActivationState>(
518         properties.GetUint(MM_MODEM_MODEMCDMA_PROPERTY_ACTIVATIONSTATE));
519     HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
520   }
521   if (registration_changed)
522     OnCDMARegistrationChanged(state_1x, state_evdo, sid, nid);
523 }
524 
OnCDMARegistrationChanged(MMModemCdmaRegistrationState state_1x,MMModemCdmaRegistrationState state_evdo,uint32_t sid,uint32_t nid)525 void CellularCapabilityUniversalCDMA::OnCDMARegistrationChanged(
526       MMModemCdmaRegistrationState state_1x,
527       MMModemCdmaRegistrationState state_evdo,
528       uint32_t sid, uint32_t nid) {
529   SLOG(this, 2) << __func__ << ": state_1x=" << state_1x
530                             << ", state_evdo=" << state_evdo;
531   cdma_1x_registration_state_ = state_1x;
532   cdma_evdo_registration_state_ = state_evdo;
533   sid_ = sid;
534   nid_ = nid;
535   cellular()->serving_operator_info()->UpdateSID(UintToString(sid));
536   cellular()->serving_operator_info()->UpdateNID(UintToString(nid));
537   cellular()->HandleNewRegistrationState();
538 }
539 
540 }  // namespace shill
541