cellular_service.cc revision d47738866711ed29c04a82647d9acb7b8a668924
18a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
23bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone// Use of this source code is governed by a BSD-style license that can be
33bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone// found in the LICENSE file.
43bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
53bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone#include "shill/cellular_service.h"
63bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
73bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone#include <string>
83bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
934af218abe6a99144ffe01332ce36fbad94f2628Chris Masone#include <base/stringprintf.h>
103bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone#include <chromeos/dbus/service_constants.h>
113bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
12b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov#include "shill/adaptor_interfaces.h"
133bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone#include "shill/cellular.h"
1430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood#include "shill/property_accessor.h"
1530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood#include "shill/store_interface.h"
163bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
173bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masoneusing std::string;
183bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
193bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masonenamespace shill {
20c5f56564e1594f218c44e9b77c4c6645cd9239e8Darin Petkov
211582bddf620625f9e6f6c407a707d6a916387df1Christopher Wileyconst char CellularService::kAutoConnActivating[] = "activating";
22d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawalconst char CellularService::kAutoConnBadPPPCredentials[] =
23d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawal    "bad PPP credentials";
2419f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chanconst char CellularService::kAutoConnDeviceDisabled[] = "device disabled";
25398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Leconst char CellularService::kAutoConnOutOfCredits[] = "device out of credits";
26398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Leconst char CellularService::kAutoConnOutOfCreditsDetectionInProgress[] =
27398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    "device detecting out-of-credits";
28398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Leconst int64 CellularService::kOutOfCreditsConnectionDropSeconds = 15;
29398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Leconst int CellularService::kOutOfCreditsMaxConnectAttempts = 3;
3099dc56dd45ec8429c3de57365658540820ceb000Thieu Leconst int64 CellularService::kOutOfCreditsResumeIgnoreSeconds = 5;
3130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
32381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov// TODO(petkov): Add these to system_api/dbus/service_constants.h
33381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovnamespace {
34381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst char kKeyOLPURL[] = "url";
35381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst char kKeyOLPMethod[] = "method";
36381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst char kKeyOLPPostData[] = "postdata";
373ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kCellularPPPUsernameProperty[] = "Cellular.PPP.Username";
383ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kCellularPPPPasswordProperty[] = "Cellular.PPP.Password";
393ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal}  // namespace
403ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal
413ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalnamespace {
423ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kStorageAPN[] = "Cellular.APN";
433ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
443ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kStoragePPPUsername[] = "Cellular.PPP.Username";
453ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawalconst char kStoragePPPPassword[] = "Cellular.PPP.Password";
4619f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan}  // namespace
47381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
4830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodstatic bool GetNonEmptyField(const Stringmap &stringmap,
4930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                             const string &fieldname,
5030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                             string *value) {
5130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  Stringmap::const_iterator it = stringmap.find(fieldname);
5230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (it != stringmap.end() && !it->second.empty()) {
5330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    *value = it->second;
5430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return true;
5530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  }
5630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return false;
5730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
5830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
59381928f996d23a21d4cfbed70d07cbf9029f625dDarin PetkovCellularService::OLP::OLP() {
60381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  SetURL("");
61381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  SetMethod("");
62381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  SetPostData("");
63381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
64381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
65381928f996d23a21d4cfbed70d07cbf9029f625dDarin PetkovCellularService::OLP::~OLP() {}
66381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
67381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovvoid CellularService::OLP::CopyFrom(const OLP &olp) {
68381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  dict_ = olp.dict_;
69381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
70381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
71381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovbool CellularService::OLP::Equals(const OLP &olp) const {
72381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  return dict_ == olp.dict_;
73381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
74381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
75381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst string &CellularService::OLP::GetURL() const {
76381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  return dict_.find(kKeyOLPURL)->second;
77381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
78381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
79381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovvoid CellularService::OLP::SetURL(const string &url) {
80381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  dict_[kKeyOLPURL] = url;
81381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
82381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
83381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst string &CellularService::OLP::GetMethod() const {
84381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  return dict_.find(kKeyOLPMethod)->second;
85381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
86381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
87381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovvoid CellularService::OLP::SetMethod(const string &method) {
88381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  dict_[kKeyOLPMethod] = method;
89381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
90381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
91381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst string &CellularService::OLP::GetPostData() const {
92381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  return dict_.find(kKeyOLPPostData)->second;
93381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
94381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
95381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovvoid CellularService::OLP::SetPostData(const string &post_data) {
96381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  dict_[kKeyOLPPostData] = post_data;
97381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
98381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
99381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovconst Stringmap &CellularService::OLP::ToDict() const {
100381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  return dict_;
101381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
102381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
1030d36b4fb5424a4c6f890e65a62a3b29e26eddb7aPrathmesh PrabhuCellularService::CellularService(ModemInfo *modem_info,
10451a7e939ed0d260392a40bc5d58e6d2651c6ddc0mukesh agrawal                                 const CellularRefPtr &device)
1050d36b4fb5424a4c6f890e65a62a3b29e26eddb7aPrathmesh Prabhu    : Service(modem_info->control_interface(), modem_info->dispatcher(),
1060d36b4fb5424a4c6f890e65a62a3b29e26eddb7aPrathmesh Prabhu              modem_info->metrics(), modem_info->manager(),
1073426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le              Technology::kCellular),
108398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      weak_ptr_factory_(this),
1093d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan      activate_over_non_cellular_network_(false),
1107cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le      cellular_(device),
111398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      is_auto_connecting_(false),
112398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      enforce_out_of_credits_detection_(false),
113398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      num_connect_attempts_(0),
114398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      out_of_credits_detection_in_progress_(false),
115398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      out_of_credits_(false) {
116cbfb34e699532f62eb5b381d0ea3a15d39e00b7cmukesh agrawal  SetConnectable(true);
117de29fa8d95092f28548b5e4537a6c61e21ae760bmukesh agrawal  PropertyStore *store = this->mutable_store();
1183d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan  store->RegisterConstBool(kActivateOverNonCellularNetworkProperty,
1193d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan                           &activate_over_non_cellular_network_);
120ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstString(flimflam::kActivationStateProperty,
12127c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone                             &activation_state_);
12230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  HelpRegisterDerivedStringmap(flimflam::kCellularApnProperty,
12330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                               &CellularService::GetApn,
12430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                               &CellularService::SetApn);
125ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstStringmap(flimflam::kCellularLastGoodApnProperty,
12627c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone                                &last_good_apn_info_);
127ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstString(flimflam::kNetworkTechnologyProperty,
128b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov                             &network_technology_);
129398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  store->RegisterConstBool(kOutOfCreditsProperty, &out_of_credits_);
130381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  store->RegisterConstStringmap(flimflam::kPaymentPortalProperty,
131381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov                                &olp_.ToDict());
132ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstString(flimflam::kRoamingStateProperty, &roaming_state_);
133ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstStringmap(flimflam::kServingOperatorProperty,
1343335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov                                &serving_operator_.ToDict());
135ac4ac00189acd22ce95098712c74e1c2c23ede53Paul Stewart  store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
1363ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  store->RegisterString(kCellularPPPUsernameProperty, &ppp_username_);
1373ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  store->RegisterWriteOnlyString(kCellularPPPPasswordProperty, &ppp_password_);
138ac635a8fb539fd44f3e24c33872b61fd064c0d60Darin Petkov
139457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov  string name = device->CreateFriendlyServiceName();
140457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov  set_friendly_name(name);
141dd3e86688859f209f1128f5562fc03a21f211aa8Darin Petkov  SetStorageIdentifier(string(flimflam::kTypeCellular) + "_" +
142457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov                       device->address() + "_" + name);
1433bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone}
1443bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
1453bd3c8c33917221d1074f1aa19272e45c0ce2793Chris MasoneCellularService::~CellularService() { }
1463bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
14719f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chanbool CellularService::IsAutoConnectable(const char **reason) const {
14819f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan  if (!cellular_->running()) {
14919f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan    *reason = kAutoConnDeviceDisabled;
15019f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan    return false;
15119f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan  }
1521582bddf620625f9e6f6c407a707d6a916387df1Christopher Wiley  if (cellular_->IsActivating()) {
1531582bddf620625f9e6f6c407a707d6a916387df1Christopher Wiley    *reason = kAutoConnActivating;
1541582bddf620625f9e6f6c407a707d6a916387df1Christopher Wiley    return false;
1551582bddf620625f9e6f6c407a707d6a916387df1Christopher Wiley  }
156d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawal  if (failure() == kFailurePPPAuth) {
157d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawal    *reason = kAutoConnBadPPPCredentials;
158d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawal    return false;
159d47738866711ed29c04a82647d9acb7b8a668924mukesh agrawal  }
160398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (out_of_credits_detection_in_progress_) {
161398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    *reason = kAutoConnOutOfCreditsDetectionInProgress;
162398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return false;
163398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  }
164398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (out_of_credits_) {
165398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    *reason = kAutoConnOutOfCredits;
166398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return false;
167398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  }
16819f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan  return Service::IsAutoConnectable(reason);
16919f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan}
17019f83971a35d7f2c7b08aae6eb0abdc8e52ba057Ben Chan
17130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::HelpRegisterDerivedStringmap(
17230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    const string &name,
17330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    Stringmap(CellularService::*get)(Error *error),
174bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal    bool(CellularService::*set)(
17530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood        const Stringmap &value, Error *error)) {
17630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  mutable_store()->RegisterDerivedStringmap(
17730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood      name,
17830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood      StringmapAccessor(
17930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood          new CustomAccessor<CellularService, Stringmap>(this, get, set)));
18030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
18130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
18230bc0ecfcdad79f652eab10c7cda9adca33a04faEric ShienbroodStringmap *CellularService::GetUserSpecifiedApn() {
18330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  Stringmap::iterator it = apn_info_.find(flimflam::kApnProperty);
18430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (it == apn_info_.end() || it->second.empty())
18530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return NULL;
18630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return &apn_info_;
18730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
18830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
18930bc0ecfcdad79f652eab10c7cda9adca33a04faEric ShienbroodStringmap *CellularService::GetLastGoodApn() {
19030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  Stringmap::iterator it =
19130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood      last_good_apn_info_.find(flimflam::kApnProperty);
19230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (it == last_good_apn_info_.end() || it->second.empty())
19330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return NULL;
19430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return &last_good_apn_info_;
19530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
19630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
19730bc0ecfcdad79f652eab10c7cda9adca33a04faEric ShienbroodStringmap CellularService::GetApn(Error */*error*/) {
19830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return apn_info_;
19930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
20030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
201bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawalbool CellularService::SetApn(const Stringmap &value, Error *error) {
20230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  // Only copy in the fields we care about, and validate the contents.
203c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood  // If the "apn" field is missing or empty, the APN is cleared.
20430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  string str;
205bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  Stringmap new_apn_info;
206bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  if (GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
207bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal    new_apn_info[flimflam::kApnProperty] = str;
208c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
209bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal      new_apn_info[flimflam::kApnUsernameProperty] = str;
210c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
211bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal      new_apn_info[flimflam::kApnPasswordProperty] = str;
212bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  }
213bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  if (apn_info_ == new_apn_info) {
214bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal    return false;
215bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  }
216bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  apn_info_ = new_apn_info;
217bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  if (ContainsKey(apn_info_, flimflam::kApnProperty)) {
218c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    // Clear the last good APN, otherwise the one the user just
219c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    // set won't be used, since LastGoodApn comes first in the
220c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    // search order when trying to connect. Only do this if a
221c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    // non-empty user APN has been supplied. If the user APN is
222c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    // being cleared, leave LastGoodApn alone.
223c7073307211b6b5a090a14b951524ac210ab1c9cEric Shienbrood    ClearLastGoodApn();
22430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  }
22530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
22630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  SaveToCurrentProfile();
227bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  return true;
22830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
22930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
23030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::SetLastGoodApn(const Stringmap &apn_info) {
23130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  last_good_apn_info_ = apn_info;
23230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
23330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                  last_good_apn_info_);
23430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  SaveToCurrentProfile();
23530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
23630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
23730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::ClearLastGoodApn() {
23830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  last_good_apn_info_.clear();
23930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
24030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                  last_good_apn_info_);
24130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  SaveToCurrentProfile();
24230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
24330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
24499dc56dd45ec8429c3de57365658540820ceb000Thieu Levoid CellularService::OnAfterResume() {
24599dc56dd45ec8429c3de57365658540820ceb000Thieu Le  Service::OnAfterResume();
24699dc56dd45ec8429c3de57365658540820ceb000Thieu Le  resume_start_time_ = base::Time::Now();
24799dc56dd45ec8429c3de57365658540820ceb000Thieu Le}
24899dc56dd45ec8429c3de57365658540820ceb000Thieu Le
24930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodbool CellularService::Load(StoreInterface *storage) {
25030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  // Load properties common to all Services.
25130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (!Service::Load(storage))
25230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return false;
25330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
25430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  const string id = GetStorageIdentifier();
25530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  LoadApn(storage, id, kStorageAPN, &apn_info_);
25630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
2573ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  storage->GetString(id, kStoragePPPUsername, &ppp_username_);
2583ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  storage->GetString(id, kStoragePPPPassword, &ppp_password_);
25930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return true;
26030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
26130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
26230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::LoadApn(StoreInterface *storage,
26330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              const string &storage_group,
26430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              const string &keytag,
26530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              Stringmap *apn_info) {
26630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (!LoadApnField(storage, storage_group, keytag,
26730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood               flimflam::kApnProperty, apn_info))
26830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return;
26930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  LoadApnField(storage, storage_group, keytag,
27030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood               flimflam::kApnUsernameProperty, apn_info);
27130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  LoadApnField(storage, storage_group, keytag,
27230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood               flimflam::kApnPasswordProperty, apn_info);
27330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
27430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
27530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodbool CellularService::LoadApnField(StoreInterface *storage,
27630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &storage_group,
27730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &keytag,
27830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &apntag,
27930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   Stringmap *apn_info) {
28030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  string value;
28130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
28230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood      !value.empty()) {
28330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    (*apn_info)[apntag] = value;
28430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return true;
28530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  }
28630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return false;
28730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
28830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
289398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Levoid CellularService::PerformOutOfCreditsDetection(ConnectState curr_state,
290398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le                                                   ConnectState new_state) {
291398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // WORKAROUND:
292398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // Some modems on Verizon network does not properly redirect when a SIM
293398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // runs out of credits.  This workaround is used to detect an out-of-credits
294398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // condition by by retrying a connect request if it was dropped within
295398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // kOutOfCreditsConnectionDropSeconds.  If the number of retries exceeds
296398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // kOutOfCreditsMaxConnectAttempts, then the SIM is considered
297398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // out-of-credits and the cellular service kOutOfCreditsProperty is set.
298398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // This will signal Chrome to display the appropriate UX and also suppress
299398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // auto-connect until the next time the user manually connects.
300398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  //
301398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // TODO(thieule): Remove this workaround (crosbug.com/p/18169).
3023a8683d45789f9ce3f3e5cc82ed4762a7818d7c0Thieu Le  if (out_of_credits_) {
3033a8683d45789f9ce3f3e5cc82ed4762a7818d7c0Thieu Le    SLOG(Cellular, 2) << __func__
3043a8683d45789f9ce3f3e5cc82ed4762a7818d7c0Thieu Le                      << ": Already out-of-credits, skipping check";
3053a8683d45789f9ce3f3e5cc82ed4762a7818d7c0Thieu Le    return;
3063a8683d45789f9ce3f3e5cc82ed4762a7818d7c0Thieu Le  }
307398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  base::TimeDelta
30899dc56dd45ec8429c3de57365658540820ceb000Thieu Le      time_since_resume = base::Time::Now() - resume_start_time_;
30999dc56dd45ec8429c3de57365658540820ceb000Thieu Le  if (time_since_resume.InSeconds() < kOutOfCreditsResumeIgnoreSeconds) {
31099dc56dd45ec8429c3de57365658540820ceb000Thieu Le    // On platforms that power down the modem during suspend, make sure that
31199dc56dd45ec8429c3de57365658540820ceb000Thieu Le    // we do not display a false out-of-credits warning to the user
31299dc56dd45ec8429c3de57365658540820ceb000Thieu Le    // due to the sequence below by skipping out-of-credits detection
31399dc56dd45ec8429c3de57365658540820ceb000Thieu Le    // immediately after a resume.
31499dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   1. User suspends Chromebook.
31599dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   2. Hardware turns off power to modem.
31699dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   3. User resumes Chromebook.
31799dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   4. Hardware restores power to modem.
31899dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   5. ModemManager still has instance of old modem.
31999dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //      ModemManager does not delete this instance until udev fires a
32099dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //      device removed event.  ModemManager does not detect new modem
32199dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //      until udev fires a new device event.
32299dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   6. Shill performs auto-connect against the old modem.
32399dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //      Make sure at this step that we do not display a false
32499dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //      out-of-credits warning.
32599dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   7. Udev fires device removed event.
32699dc56dd45ec8429c3de57365658540820ceb000Thieu Le    //   8. Udev fires new device event.
32799dc56dd45ec8429c3de57365658540820ceb000Thieu Le    SLOG(Cellular, 2) <<
32899dc56dd45ec8429c3de57365658540820ceb000Thieu Le        "Skipping out-of-credits detection, too soon since resume.";
32999dc56dd45ec8429c3de57365658540820ceb000Thieu Le    ResetOutOfCreditsState();
33099dc56dd45ec8429c3de57365658540820ceb000Thieu Le    return;
33199dc56dd45ec8429c3de57365658540820ceb000Thieu Le  }
33299dc56dd45ec8429c3de57365658540820ceb000Thieu Le  base::TimeDelta
333398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      time_since_connect = base::Time::Now() - connect_start_time_;
334398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (time_since_connect.InSeconds() > kOutOfCreditsConnectionDropSeconds) {
335398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    ResetOutOfCreditsState();
336398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return;
337398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  }
338398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  // Verizon can drop the connection in two ways:
339398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  //   - Denies the connect request
340398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  //   - Allows connect request but disconnects later
341398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  bool connection_dropped =
342398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      (IsConnectedState(curr_state) || IsConnectingState(curr_state)) &&
343398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      (new_state == kStateFailure || new_state == kStateIdle);
344398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (!connection_dropped)
345398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return;
346398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (explicitly_disconnected())
347398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return;
348398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (roaming_state_ == flimflam::kRoamingStateRoaming &&
349398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      !cellular_->allow_roaming_property())
350398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return;
351398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (time_since_connect.InSeconds() <= kOutOfCreditsConnectionDropSeconds) {
352398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    if (num_connect_attempts_ < kOutOfCreditsMaxConnectAttempts) {
353398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      SLOG(Cellular, 2) << "Out-Of-Credits detection: Reconnecting "
354398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le                        << "(retry #" << num_connect_attempts_ << ")";
355398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      // Prevent autoconnect logic from kicking in while we perform the
356398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      // out-of-credits detection.
357398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      out_of_credits_detection_in_progress_ = true;
358398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      dispatcher()->PostTask(
359398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le          Bind(&CellularService::OutOfCreditsReconnect,
360398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le               weak_ptr_factory_.GetWeakPtr()));
361398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    } else {
362398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      LOG(ERROR) <<
363398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le          "Out-Of-Credits detection: Marking service as out-of-credits";
36491fccf6ff2ee20d77905ce71a7e9815b2e2c02d7Thieu Le      metrics()->NotifyCellularOutOfCredits(
36591fccf6ff2ee20d77905ce71a7e9815b2e2c02d7Thieu Le          Metrics::kCellularOutOfCreditsReasonConnectDisconnectLoop);
366398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      SetOutOfCredits(true);
367398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le      ResetOutOfCreditsState();
368398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    }
369398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  }
370398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le}
371398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le
372398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Levoid CellularService::OutOfCreditsReconnect() {
373398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  Error error;
374dc7b8447aa220fae51b73fd8610cbfed14ed57fcmukesh agrawal  Connect(&error, __func__);
375398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le}
376398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le
377398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Levoid CellularService::ResetOutOfCreditsState() {
378398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  out_of_credits_detection_in_progress_ = false;
379398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  num_connect_attempts_ = 0;
380398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le}
381398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le
38230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodbool CellularService::Save(StoreInterface *storage) {
38330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  // Save properties common to all Services.
38430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (!Service::Save(storage))
38530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    return false;
38630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
38730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  const string id = GetStorageIdentifier();
38830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
38930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
3903ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  SaveString(storage, id, kStoragePPPUsername, ppp_username_, false, true);
3913ffe52c6eb79db079a8b5685d2c8bd96f6b49b79mukesh agrawal  SaveString(storage, id, kStoragePPPPassword, ppp_password_, false, true);
39230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  return true;
39330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
39430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
39530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::SaveApn(StoreInterface *storage,
39630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              const string &storage_group,
39730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              const Stringmap *apn_info,
39830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                              const string &keytag) {
39930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    SaveApnField(storage, storage_group, apn_info, keytag,
40030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                 flimflam::kApnProperty);
40130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    SaveApnField(storage, storage_group, apn_info, keytag,
40230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                 flimflam::kApnUsernameProperty);
40330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    SaveApnField(storage, storage_group, apn_info, keytag,
40430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                 flimflam::kApnPasswordProperty);
40530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
40630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
40730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularService::SaveApnField(StoreInterface *storage,
40830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &storage_group,
40930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const Stringmap *apn_info,
41030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &keytag,
41130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood                                   const string &apntag) {
41230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  const string key = keytag + "." + apntag;
41330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  string str;
41430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
41530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    storage->SetString(storage_group, key, str);
41630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood  else
41730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood    storage->DeleteKey(storage_group, key);
41830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood}
41930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood
4207cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Levoid CellularService::AutoConnect() {
4217cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le  is_auto_connecting_ = true;
4227cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le  Service::AutoConnect();
4237cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le  is_auto_connecting_ = false;
4247cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le}
4257cf36b0cbc1e382fb714cf412d100c9f7ad86c09Thieu Le
426dc7b8447aa220fae51b73fd8610cbfed14ed57fcmukesh agrawalvoid CellularService::Connect(Error *error, const char *reason) {
427398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (num_connect_attempts_ == 0)
428398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    SetOutOfCredits(false);
429398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  connect_start_time_ = base::Time::Now();
430398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  num_connect_attempts_++;
431dc7b8447aa220fae51b73fd8610cbfed14ed57fcmukesh agrawal  Service::Connect(error, reason);
4324d6d941563c2c394e5e650d7ee2d24183fff87b3Darin Petkov  cellular_->Connect(error);
433398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (error->IsFailure())
434398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    ResetOutOfCreditsState();
435c5f56564e1594f218c44e9b77c4c6645cd9239e8Darin Petkov}
4363bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone
437fb0625ef0cfd0ad36439138c04fec5ea963132d7Darin Petkovvoid CellularService::Disconnect(Error *error) {
438fb0625ef0cfd0ad36439138c04fec5ea963132d7Darin Petkov  Service::Disconnect(error);
439fb0625ef0cfd0ad36439138c04fec5ea963132d7Darin Petkov  cellular_->Disconnect(error);
440fb0625ef0cfd0ad36439138c04fec5ea963132d7Darin Petkov}
441fb0625ef0cfd0ad36439138c04fec5ea963132d7Darin Petkov
442b100ae709f1b774a646d946eae604a2bf6326fd4Darin Petkovvoid CellularService::ActivateCellularModem(const string &carrier,
4439a24553461df7036755060423f90804011612249Eric Shienbrood                                            Error *error,
4449a24553461df7036755060423f90804011612249Eric Shienbrood                                            const ResultCallback &callback) {
4459a24553461df7036755060423f90804011612249Eric Shienbrood  cellular_->Activate(carrier, error, callback);
446c408e69059dc709408c1a51f4b757424d08b15f5Darin Petkov}
447c408e69059dc709408c1a51f4b757424d08b15f5Darin Petkov
448c7b1560b03c070fad239767f868322e6b3bdd932Arman Ugurayvoid CellularService::CompleteCellularActivation(Error *error) {
449c7b1560b03c070fad239767f868322e6b3bdd932Arman Uguray  cellular_->CompleteActivation(error);
450c7b1560b03c070fad239767f868322e6b3bdd932Arman Uguray}
451c7b1560b03c070fad239767f868322e6b3bdd932Arman Uguray
452398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Levoid CellularService::SetState(ConnectState new_state) {
453398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (enforce_out_of_credits_detection_)
454398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    PerformOutOfCreditsDetection(state(), new_state);
455398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  Service::SetState(new_state);
456398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le}
457398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le
458313324136473f9120b1e485a408f51ae938dcb64Darin Petkovvoid CellularService::SetStorageIdentifier(const string &identifier) {
459313324136473f9120b1e485a408f51ae938dcb64Darin Petkov  storage_identifier_ = identifier;
460313324136473f9120b1e485a408f51ae938dcb64Darin Petkov  std::replace_if(storage_identifier_.begin(),
461313324136473f9120b1e485a408f51ae938dcb64Darin Petkov                  storage_identifier_.end(),
462313324136473f9120b1e485a408f51ae938dcb64Darin Petkov                  &Service::IllegalChar, '_');
463313324136473f9120b1e485a408f51ae938dcb64Darin Petkov}
464313324136473f9120b1e485a408f51ae938dcb64Darin Petkov
4656515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masonestring CellularService::GetStorageIdentifier() const {
466313324136473f9120b1e485a408f51ae938dcb64Darin Petkov  return storage_identifier_;
46734af218abe6a99144ffe01332ce36fbad94f2628Chris Masone}
46834af218abe6a99144ffe01332ce36fbad94f2628Chris Masone
4691b7a616197af7ff753dbe7614a8e207b1e10ac1aGaurav Shahstring CellularService::GetDeviceRpcId(Error */*error*/) {
47095207da4b896bd0a4186163f6f9ebda044a5a7b9Chris Masone  return cellular_->GetRpcIdentifier();
47195207da4b896bd0a4186163f6f9ebda044a5a7b9Chris Masone}
47295207da4b896bd0a4186163f6f9ebda044a5a7b9Chris Masone
4733d6de0eef9998899e9b8b500e628f7180a18da8fBen Chanvoid CellularService::SetActivateOverNonCellularNetwork(bool state) {
4743d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan  if (state == activate_over_non_cellular_network_) {
4753d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan    return;
4763d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan  }
4773d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan  activate_over_non_cellular_network_ = state;
4783d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan  adaptor()->EmitBoolChanged(kActivateOverNonCellularNetworkProperty, state);
4793d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan}
4803d6de0eef9998899e9b8b500e628f7180a18da8fBen Chan
481b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkovvoid CellularService::SetActivationState(const string &state) {
482b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov  if (state == activation_state_) {
483b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov    return;
484b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov  }
485b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov  activation_state_ = state;
486b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov  adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
487cbfb34e699532f62eb5b381d0ea3a15d39e00b7cmukesh agrawal  SetConnectableFull(state != flimflam::kActivationStateNotActivated);
488b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov}
489b9c9933d529e34ce784d4f322d9596cbd9e6ba1cDarin Petkov
490381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkovvoid CellularService::SetOLP(const OLP &olp) {
491381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  if (olp_.Equals(olp)) {
492381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov    return;
493381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  }
494381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  olp_.CopyFrom(olp);
495381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
496381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov                                  olp.ToDict());
497381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
498381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
4992717a10096e12e46413adf47b39c5b19cd33bce7Arman Ugurayvoid CellularService::SetUsageURL(const string &url) {
500381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  if (url == usage_url_) {
501381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov    return;
502381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  }
503381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  usage_url_ = url;
504381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov  adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
505381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov}
506381928f996d23a21d4cfbed70d07cbf9029f625dDarin Petkov
507b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkovvoid CellularService::SetNetworkTechnology(const string &technology) {
508b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  if (technology == network_technology_) {
509b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov    return;
510b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  }
511b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  network_technology_ = technology;
512b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
513b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov                               technology);
514b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov}
515b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov
516b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkovvoid CellularService::SetRoamingState(const string &state) {
517b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  if (state == roaming_state_) {
518b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov    return;
519b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  }
520b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  roaming_state_ = state;
521b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov  adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
522b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov}
523b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov
524398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Levoid CellularService::SetOutOfCredits(bool state) {
525398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  if (state == out_of_credits_) {
526398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le    return;
527398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  }
528398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  out_of_credits_ = state;
529398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le  adaptor()->EmitBoolChanged(kOutOfCreditsProperty, state);
530398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le}
531398b1da04e413f89f0edeb53e939e3a2d2866298Thieu Le
5323335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkovconst Cellular::Operator &CellularService::serving_operator() const {
5333335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov  return serving_operator_;
5343335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov}
5353335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov
5369cb026860ded74991fa26700e07389c9d9e3c841Darin Petkovvoid CellularService::SetServingOperator(const Cellular::Operator &oper) {
5379cb026860ded74991fa26700e07389c9d9e3c841Darin Petkov  if (serving_operator_.Equals(oper)) {
5389cb026860ded74991fa26700e07389c9d9e3c841Darin Petkov    return;
5399cb026860ded74991fa26700e07389c9d9e3c841Darin Petkov  }
5403335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov  serving_operator_.CopyFrom(oper);
5419cb026860ded74991fa26700e07389c9d9e3c841Darin Petkov  adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
5429cb026860ded74991fa26700e07389c9d9e3c841Darin Petkov                                  oper.ToDict());
5433335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov}
5443335b3773067671301a8a02a1f9eefd17a3ce607Darin Petkov
5453bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone}  // namespace shill
546