Home | History | Annotate | Download | only in shill
      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/service.h"
     18 
     19 #include <stdio.h>
     20 #include <time.h>
     21 
     22 #include <algorithm>
     23 #include <map>
     24 #include <memory>
     25 #include <string>
     26 #include <vector>
     27 
     28 #include <base/strings/string_number_conversions.h>
     29 #include <base/strings/stringprintf.h>
     30 #if defined(__ANDROID__)
     31 #include <dbus/service_constants.h>
     32 #else
     33 #include <chromeos/dbus/service_constants.h>
     34 #endif  // __ANDROID__
     35 
     36 #include "shill/connection.h"
     37 #include "shill/control_interface.h"
     38 #include "shill/dhcp_properties.h"
     39 #include "shill/error.h"
     40 #include "shill/http_proxy.h"
     41 #include "shill/logging.h"
     42 #include "shill/manager.h"
     43 #include "shill/metrics.h"
     44 #include "shill/net/event_history.h"
     45 #include "shill/net/sockets.h"
     46 #include "shill/profile.h"
     47 #include "shill/property_accessor.h"
     48 #include "shill/refptr_types.h"
     49 #include "shill/service_property_change_notifier.h"
     50 #include "shill/store_interface.h"
     51 
     52 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
     53 #include "shill/eap_credentials.h"
     54 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
     55 
     56 using base::Bind;
     57 using std::map;
     58 using std::string;
     59 using std::vector;
     60 
     61 namespace shill {
     62 
     63 namespace Logging {
     64 static auto kModuleLogScope = ScopeLogger::kService;
     65 static string ObjectID(const Service* s) { return s->GetRpcIdentifier(); }
     66 }
     67 
     68 const char Service::kAutoConnBusy[] = "busy";
     69 const char Service::kAutoConnConnected[] = "connected";
     70 const char Service::kAutoConnConnecting[] = "connecting";
     71 const char Service::kAutoConnExplicitDisconnect[] = "explicitly disconnected";
     72 const char Service::kAutoConnNotConnectable[] = "not connectable";
     73 const char Service::kAutoConnOffline[] = "offline";
     74 const char Service::kAutoConnTechnologyNotConnectable[] =
     75     "technology not connectable";
     76 const char Service::kAutoConnThrottled[] = "throttled";
     77 
     78 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
     79 const size_t Service::kEAPMaxCertificationElements = 10;
     80 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
     81 
     82 const char Service::kCheckPortalAuto[] = "auto";
     83 const char Service::kCheckPortalFalse[] = "false";
     84 const char Service::kCheckPortalTrue[] = "true";
     85 
     86 const char Service::kErrorDetailsNone[] = "";
     87 
     88 const int Service::kPriorityNone = 0;
     89 
     90 const char Service::kServiceSortAutoConnect[] = "AutoConnect";
     91 const char Service::kServiceSortConnectable[] = "Connectable";
     92 const char Service::kServiceSortDependency[] = "Dependency";
     93 const char Service::kServiceSortHasEverConnected[] = "HasEverConnected";
     94 const char Service::kServiceSortIsConnected[] = "IsConnected";
     95 const char Service::kServiceSortIsConnecting[] = "IsConnecting";
     96 const char Service::kServiceSortIsFailed[] = "IsFailed";
     97 const char Service::kServiceSortIsOnline[] = "IsOnline";
     98 const char Service::kServiceSortIsPortalled[] = "IsPortal";
     99 const char Service::kServiceSortPriority[] = "Priority";
    100 const char Service::kServiceSortPriorityWithinTechnology[] =
    101     "PriorityWithinTechnology";
    102 const char Service::kServiceSortSecurity[] = "Security";
    103 const char Service::kServiceSortProfileOrder[] = "ProfileOrder";
    104 const char Service::kServiceSortEtc[] = "Etc";
    105 const char Service::kServiceSortSerialNumber[] = "SerialNumber";
    106 const char Service::kServiceSortTechnology[] = "Technology";
    107 
    108 const char Service::kStorageAutoConnect[] = "AutoConnect";
    109 const char Service::kStorageCheckPortal[] = "CheckPortal";
    110 const char Service::kStorageDNSAutoFallback[] = "DNSAutoFallback";
    111 const char Service::kStorageError[] = "Error";
    112 const char Service::kStorageFavorite[] = "Favorite";
    113 const char Service::kStorageGUID[] = "GUID";
    114 const char Service::kStorageHasEverConnected[] = "HasEverConnected";
    115 const char Service::kStorageName[] = "Name";
    116 const char Service::kStoragePriority[] = "Priority";
    117 const char Service::kStoragePriorityWithinTechnology[]
    118     = "PriorityWithinTechnology";
    119 const char Service::kStorageProxyConfig[] = "ProxyConfig";
    120 const char Service::kStorageSaveCredentials[] = "SaveCredentials";
    121 const char Service::kStorageType[] = "Type";
    122 const char Service::kStorageUIData[] = "UIData";
    123 const char Service::kStorageConnectionId[] = "ConnectionId";
    124 const char Service::kStorageLinkMonitorDisabled[] = "LinkMonitorDisabled";
    125 const char Service::kStorageManagedCredentials[] = "ManagedCredentials";
    126 
    127 const uint8_t Service::kStrengthMax = 100;
    128 const uint8_t Service::kStrengthMin = 0;
    129 
    130 const uint64_t Service::kMaxAutoConnectCooldownTimeMilliseconds =
    131     30 * 60 * 1000;
    132 const uint64_t Service::kMinAutoConnectCooldownTimeMilliseconds = 1000;
    133 const uint64_t Service::kAutoConnectCooldownBackoffFactor = 2;
    134 
    135 const int Service::kDisconnectsMonitorSeconds = 5 * 60;
    136 const int Service::kMisconnectsMonitorSeconds = 5 * 60;
    137 const int Service::kMaxDisconnectEventHistory = 20;
    138 const int Service::kMaxMisconnectEventHistory = 20;
    139 
    140 // static
    141 unsigned int Service::next_serial_number_ = 0;
    142 
    143 Service::Service(ControlInterface* control_interface,
    144                  EventDispatcher* dispatcher,
    145                  Metrics* metrics,
    146                  Manager* manager,
    147                  Technology::Identifier technology)
    148     : weak_ptr_factory_(this),
    149       state_(kStateIdle),
    150       previous_state_(kStateIdle),
    151       failure_(kFailureUnknown),
    152       auto_connect_(false),
    153       retain_auto_connect_(false),
    154       check_portal_(kCheckPortalAuto),
    155       connectable_(false),
    156       error_(ConnectFailureToString(failure_)),
    157       error_details_(kErrorDetailsNone),
    158       previous_error_serial_number_(0),
    159       explicitly_disconnected_(false),
    160       is_in_user_connect_(false),
    161       priority_(kPriorityNone),
    162       priority_within_technology_(kPriorityNone),
    163       crypto_algorithm_(kCryptoNone),
    164       key_rotation_(false),
    165       endpoint_auth_(false),
    166       strength_(0),
    167       save_credentials_(true),
    168       dhcp_properties_(new DhcpProperties()),
    169       technology_(technology),
    170       failed_time_(0),
    171       has_ever_connected_(false),
    172       disconnects_(kMaxDisconnectEventHistory),
    173       misconnects_(kMaxMisconnectEventHistory),
    174       auto_connect_cooldown_milliseconds_(0),
    175       store_(PropertyStore::PropertyChangeCallback(
    176           base::Bind(&Service::OnPropertyChanged,
    177                      weak_ptr_factory_.GetWeakPtr()))),
    178       dispatcher_(dispatcher),
    179       control_interface_(control_interface),
    180       serial_number_(next_serial_number_++),
    181       unique_name_(base::UintToString(serial_number_)),
    182       friendly_name_(unique_name_),
    183       adaptor_(control_interface->CreateServiceAdaptor(this)),
    184       property_change_notifier_(
    185           new ServicePropertyChangeNotifier(adaptor_.get())),
    186       metrics_(metrics),
    187       manager_(manager),
    188       sockets_(new Sockets()),
    189       time_(Time::GetInstance()),
    190       connection_id_(0),
    191       is_dns_auto_fallback_allowed_(false),
    192       link_monitor_disabled_(false),
    193       managed_credentials_(false),
    194       unreliable_(false) {
    195   HelpRegisterDerivedBool(kAutoConnectProperty,
    196                           &Service::GetAutoConnect,
    197                           &Service::SetAutoConnectFull,
    198                           &Service::ClearAutoConnect);
    199 
    200   // kActivationTypeProperty: Registered in CellularService
    201   // kActivationStateProperty: Registered in CellularService
    202   // kCellularApnProperty: Registered in CellularService
    203   // kCellularLastGoodApnProperty: Registered in CellularService
    204   // kNetworkTechnologyProperty: Registered in CellularService
    205   // kOutOfCreditsProperty: Registered in CellularService
    206   // kPaymentPortalProperty: Registered in CellularService
    207   // kRoamingStateProperty: Registered in CellularService
    208   // kServingOperatorProperty: Registered in CellularService
    209   // kUsageURLProperty: Registered in CellularService
    210   // kCellularPPPUsernameProperty: Registered in CellularService
    211   // kCellularPPPPasswordProperty: Registered in CellularService
    212 
    213   // kNetworkIdProperty: Registered in WiMaxService
    214 
    215   HelpRegisterDerivedString(kCheckPortalProperty,
    216                             &Service::GetCheckPortal,
    217                             &Service::SetCheckPortal);
    218   store_.RegisterConstBool(kConnectableProperty, &connectable_);
    219   HelpRegisterConstDerivedRpcIdentifier(kDeviceProperty,
    220                                         &Service::GetDeviceRpcId);
    221 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
    222   store_.RegisterConstStrings(kEapRemoteCertificationProperty,
    223                               &remote_certification_);
    224 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
    225   HelpRegisterDerivedString(kGuidProperty,
    226                             &Service::GetGuid,
    227                             &Service::SetGuid);
    228 
    229   // TODO(ers): in flimflam clearing Error has the side-effect of
    230   // setting the service state to IDLE. Is this important? I could
    231   // see an autotest depending on it.
    232   store_.RegisterConstString(kErrorProperty, &error_);
    233   store_.RegisterConstString(kErrorDetailsProperty, &error_details_);
    234   HelpRegisterConstDerivedUint16(kHTTPProxyPortProperty,
    235                                  &Service::GetHTTPProxyPort);
    236   HelpRegisterConstDerivedRpcIdentifier(kIPConfigProperty,
    237                                         &Service::GetIPConfigRpcIdentifier);
    238   HelpRegisterDerivedBool(kIsActiveProperty, &Service::IsActive, nullptr,
    239                           nullptr);
    240   // kModeProperty: Registered in WiFiService
    241 
    242   HelpRegisterDerivedString(kNameProperty,
    243                             &Service::GetNameProperty,
    244                             &Service::SetNameProperty);
    245   // kPassphraseProperty: Registered in WiFiService
    246   // kPassphraseRequiredProperty: Registered in WiFiService, WiMaxService
    247   store_.RegisterConstString(kPreviousErrorProperty,
    248                              &previous_error_);
    249   store_.RegisterConstInt32(kPreviousErrorSerialNumberProperty,
    250                             &previous_error_serial_number_);
    251   HelpRegisterDerivedInt32(kPriorityProperty,
    252                            &Service::GetPriority,
    253                            &Service::SetPriority);
    254   HelpRegisterDerivedInt32(kPriorityWithinTechnologyProperty,
    255                            &Service::GetPriorityWithinTechnology,
    256                            &Service::SetPriorityWithinTechnology);
    257   HelpRegisterDerivedString(kProfileProperty,
    258                             &Service::GetProfileRpcId,
    259                             &Service::SetProfileRpcId);
    260   HelpRegisterDerivedString(kProxyConfigProperty,
    261                             &Service::GetProxyConfig,
    262                             &Service::SetProxyConfig);
    263   store_.RegisterBool(kSaveCredentialsProperty, &save_credentials_);
    264   HelpRegisterConstDerivedString(kTetheringProperty,
    265                                  &Service::GetTethering);
    266   HelpRegisterDerivedString(kTypeProperty,
    267                             &Service::CalculateTechnology,
    268                             nullptr);
    269   // kSecurityProperty: Registered in WiFiService
    270   HelpRegisterDerivedString(kStateProperty,
    271                             &Service::CalculateState,
    272                             nullptr);
    273   store_.RegisterConstUint8(kSignalStrengthProperty, &strength_);
    274   store_.RegisterString(kUIDataProperty, &ui_data_);
    275   HelpRegisterConstDerivedStrings(kDiagnosticsDisconnectsProperty,
    276                                   &Service::GetDisconnectsProperty);
    277   HelpRegisterConstDerivedStrings(kDiagnosticsMisconnectsProperty,
    278                                   &Service::GetMisconnectsProperty);
    279   store_.RegisterConstInt32(kConnectionIdProperty, &connection_id_);
    280   store_.RegisterBool(kDnsAutoFallbackProperty, &is_dns_auto_fallback_allowed_);
    281   store_.RegisterBool(kLinkMonitorDisableProperty, &link_monitor_disabled_);
    282   store_.RegisterBool(kManagedCredentialsProperty, &managed_credentials_);
    283 
    284   HelpRegisterObservedDerivedBool(kVisibleProperty,
    285                                   &Service::GetVisibleProperty,
    286                                   nullptr,
    287                                   nullptr);
    288 
    289   store_.RegisterConstString(kPortalDetectionFailedPhaseProperty,
    290                              &portal_detection_failure_phase_);
    291   store_.RegisterConstString(kPortalDetectionFailedStatusProperty,
    292                              &portal_detection_failure_status_);
    293 
    294   metrics_->RegisterService(*this);
    295 
    296   static_ip_parameters_.PlumbPropertyStore(&store_);
    297 
    298   IgnoreParameterForConfigure(kTypeProperty);
    299   IgnoreParameterForConfigure(kProfileProperty);
    300 
    301   dhcp_properties_->InitPropertyStore(&store_);
    302 
    303   LOG(INFO) << Technology::NameFromIdentifier(technology) << " service "
    304             << unique_name_ << " constructed.";
    305 }
    306 
    307 Service::~Service() {
    308   metrics_->DeregisterService(*this);
    309   LOG(INFO) << "Service " << unique_name_ << " destroyed.";
    310 }
    311 
    312 void Service::AutoConnect() {
    313   const char* reason = nullptr;
    314   if (IsAutoConnectable(&reason)) {
    315     Error error;
    316     LOG(INFO) << "Auto-connecting to service " << unique_name_;
    317     ThrottleFutureAutoConnects();
    318     Connect(&error, __func__);
    319   } else {
    320     if (reason == kAutoConnConnected || reason == kAutoConnBusy) {
    321       SLOG(this, 1)
    322           << "Suppressed autoconnect to service " << unique_name_ << " "
    323           << "(" << reason << ")";
    324     } else {
    325       LOG(INFO) << "Suppressed autoconnect to service " << unique_name_ << " "
    326                 << "(" << reason << ")";
    327     }
    328   }
    329 }
    330 
    331 void Service::Connect(Error* /*error*/, const char* reason) {
    332   LOG(INFO) << "Connect to service " << unique_name() <<": " << reason;
    333   ClearExplicitlyDisconnected();
    334   // Clear any failure state from a previous connect attempt.
    335   if (state() == kStateFailure)
    336     SetState(kStateIdle);
    337 }
    338 
    339 void Service::Disconnect(Error* /*error*/, const char* reason) {
    340   string log_message = base::StringPrintf(
    341       "Disconnecting from service %s: %s", unique_name_.c_str(), reason);
    342   if (IsActive(nullptr)) {
    343     LOG(INFO) << log_message;
    344   } else {
    345     SLOG(this, 1) << log_message;
    346   }
    347 }
    348 
    349 void Service::DisconnectWithFailure(ConnectFailure failure,
    350                                     Error* error,
    351                                     const char* reason) {
    352   Disconnect(error, reason);
    353   SetFailure(failure);
    354 }
    355 
    356 void Service::UserInitiatedDisconnect(Error* error) {
    357   Disconnect(error, "D-Bus RPC");
    358   explicitly_disconnected_ = true;
    359 }
    360 
    361 void Service::UserInitiatedConnect(Error* error) {
    362   Connect(error, "D-Bus RPC");
    363   is_in_user_connect_ = true;
    364 }
    365 
    366 void Service::ActivateCellularModem(const string& /*carrier*/,
    367                                     Error* error,
    368                                     const ResultCallback& /*callback*/) {
    369   Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
    370                         "Service doesn't support cellular modem activation.");
    371 }
    372 
    373 void Service::CompleteCellularActivation(Error* error) {
    374   Error::PopulateAndLog(
    375       FROM_HERE, error, Error::kNotSupported,
    376       "Service doesn't support cellular activation completion.");
    377 }
    378 
    379 bool Service::IsActive(Error* /*error*/) {
    380   return state() != kStateUnknown &&
    381     state() != kStateIdle &&
    382     state() != kStateFailure;
    383 }
    384 
    385 // static
    386 bool Service::IsConnectedState(ConnectState state) {
    387   return (state == kStateConnected ||
    388           state == kStatePortal ||
    389           state == kStateOnline);
    390 }
    391 
    392 // static
    393 bool Service::IsConnectingState(ConnectState state) {
    394   return (state == kStateAssociating ||
    395           state == kStateConfiguring);
    396 }
    397 
    398 bool Service::IsConnected() const {
    399   return IsConnectedState(state());
    400 }
    401 
    402 bool Service::IsConnecting() const {
    403   return IsConnectingState(state());
    404 }
    405 
    406 void Service::SetState(ConnectState state) {
    407   if (state == state_) {
    408     return;
    409   }
    410 
    411   LOG(INFO) << "Service " << unique_name_ << ": state "
    412             << ConnectStateToString(state_) << " -> "
    413             << ConnectStateToString(state);
    414 
    415   // Metric reporting for result of user-initiated connection attempt.
    416   if (is_in_user_connect_ && ((state == kStateConnected) ||
    417       (state == kStateFailure) || (state == kStateIdle))) {
    418     ReportUserInitiatedConnectionResult(state);
    419     is_in_user_connect_ = false;
    420   }
    421 
    422   if (state == kStateFailure) {
    423     NoteDisconnectEvent();
    424   }
    425 
    426   previous_state_ = state_;
    427   state_ = state;
    428   if (state != kStateFailure) {
    429     failure_ = kFailureUnknown;
    430     SetErrorDetails(kErrorDetailsNone);
    431   }
    432   if (state == kStateConnected) {
    433     failed_time_ = 0;
    434     has_ever_connected_ = true;
    435     SaveToProfile();
    436     // When we succeed in connecting, forget that connects failed in the past.
    437     // Give services one chance at a fast autoconnect retry by resetting the
    438     // cooldown to 0 to indicate that the last connect was successful.
    439     auto_connect_cooldown_milliseconds_  = 0;
    440     reenable_auto_connect_task_.Cancel();
    441   }
    442   UpdateErrorProperty();
    443   manager_->UpdateService(this);
    444   metrics_->NotifyServiceStateChanged(*this, state);
    445   adaptor_->EmitStringChanged(kStateProperty, GetStateString());
    446 }
    447 
    448 void Service::SetPortalDetectionFailure(const string& phase,
    449                                         const string& status) {
    450   portal_detection_failure_phase_ = phase;
    451   portal_detection_failure_status_ = status;
    452   adaptor_->EmitStringChanged(kPortalDetectionFailedPhaseProperty, phase);
    453   adaptor_->EmitStringChanged(kPortalDetectionFailedStatusProperty, status);
    454 }
    455 
    456 void Service::ReEnableAutoConnectTask() {
    457   // Kill the thing blocking AutoConnect().
    458   reenable_auto_connect_task_.Cancel();
    459   // Post to the manager, giving it an opportunity to AutoConnect again.
    460   manager_->UpdateService(this);
    461 }
    462 
    463 void Service::ThrottleFutureAutoConnects() {
    464   if (auto_connect_cooldown_milliseconds_ > 0) {
    465     LOG(INFO) << "Throttling future autoconnects to service " << unique_name_
    466               << ". Next autoconnect in "
    467               << auto_connect_cooldown_milliseconds_ << " milliseconds.";
    468     reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
    469                                            weak_ptr_factory_.GetWeakPtr()));
    470     dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
    471                                  auto_connect_cooldown_milliseconds_);
    472   }
    473   auto_connect_cooldown_milliseconds_ =
    474       std::min(kMaxAutoConnectCooldownTimeMilliseconds,
    475                std::max(kMinAutoConnectCooldownTimeMilliseconds,
    476                         auto_connect_cooldown_milliseconds_ *
    477                         kAutoConnectCooldownBackoffFactor));
    478 }
    479 
    480 void Service::SaveFailure() {
    481   previous_error_ = ConnectFailureToString(failure_);
    482   ++previous_error_serial_number_;
    483 }
    484 
    485 void Service::SetFailure(ConnectFailure failure) {
    486   failure_ = failure;
    487   SaveFailure();
    488   failed_time_ = time(nullptr);
    489   UpdateErrorProperty();
    490   SetState(kStateFailure);
    491 }
    492 
    493 void Service::SetFailureSilent(ConnectFailure failure) {
    494   NoteDisconnectEvent();
    495   // Note that order matters here, since SetState modifies |failure_| and
    496   // |failed_time_|.
    497   SetState(kStateIdle);
    498   failure_ = failure;
    499   SaveFailure();
    500   UpdateErrorProperty();
    501   failed_time_ = time(nullptr);
    502 }
    503 
    504 string Service::GetRpcIdentifier() const {
    505   return adaptor_->GetRpcIdentifier();
    506 }
    507 
    508 string Service::GetLoadableStorageIdentifier(
    509     const StoreInterface& storage) const {
    510   return IsLoadableFrom(storage) ? GetStorageIdentifier() : "";
    511 }
    512 
    513 bool Service::IsLoadableFrom(const StoreInterface& storage) const {
    514   return storage.ContainsGroup(GetStorageIdentifier());
    515 }
    516 
    517 bool Service::Load(StoreInterface* storage) {
    518   const string id = GetStorageIdentifier();
    519   if (!storage->ContainsGroup(id)) {
    520     LOG(WARNING) << "Service is not available in the persistent store: " << id;
    521     return false;
    522   }
    523 
    524   auto_connect_ = IsAutoConnectByDefault();
    525   retain_auto_connect_ =
    526       storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
    527   // The legacy "Favorite" flag will override retain_auto_connect_ if present.
    528   storage->GetBool(id, kStorageFavorite, &retain_auto_connect_);
    529 
    530   LoadString(storage, id, kStorageCheckPortal, kCheckPortalAuto,
    531              &check_portal_);
    532   LoadString(storage, id, kStorageGUID, "", &guid_);
    533   if (!storage->GetInt(id, kStoragePriority, &priority_)) {
    534     priority_ = kPriorityNone;
    535   }
    536   if (!storage->GetInt(id, kStoragePriorityWithinTechnology,
    537                        &priority_within_technology_)) {
    538     priority_within_technology_ = kPriorityNone;
    539   }
    540   LoadString(storage, id, kStorageProxyConfig, "", &proxy_config_);
    541   storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
    542   LoadString(storage, id, kStorageUIData, "", &ui_data_);
    543 
    544   storage->GetInt(id, kStorageConnectionId, &connection_id_);
    545   storage->GetBool(id, kStorageDNSAutoFallback, &is_dns_auto_fallback_allowed_);
    546   storage->GetBool(id, kStorageLinkMonitorDisabled, &link_monitor_disabled_);
    547   if (!storage->GetBool(id, kStorageManagedCredentials,
    548                         &managed_credentials_)) {
    549     managed_credentials_ = false;
    550   }
    551 
    552   static_ip_parameters_.Load(storage, id);
    553 
    554 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
    555   // Call OnEapCredentialsChanged with kReasonCredentialsLoaded to avoid
    556   // resetting the has_ever_connected value.
    557   if (mutable_eap()) {
    558     mutable_eap()->Load(storage, id);
    559     OnEapCredentialsChanged(kReasonCredentialsLoaded);
    560   }
    561 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
    562 
    563   ClearExplicitlyDisconnected();
    564 
    565   // Read has_ever_connected_ value from stored profile
    566   // now that the credentials have been loaded.
    567   storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
    568 
    569   dhcp_properties_->Load(storage, id);
    570   return true;
    571 }
    572 
    573 bool Service::Unload() {
    574   auto_connect_ = IsAutoConnectByDefault();
    575   retain_auto_connect_ = false;
    576   check_portal_ = kCheckPortalAuto;
    577   ClearExplicitlyDisconnected();
    578   guid_ = "";
    579   has_ever_connected_ = false;
    580   priority_ = kPriorityNone;
    581   priority_within_technology_ = kPriorityNone;
    582   proxy_config_ = "";
    583   save_credentials_ = true;
    584   ui_data_ = "";
    585   connection_id_ = 0;
    586   is_dns_auto_fallback_allowed_ = false;
    587   link_monitor_disabled_ = false;
    588   managed_credentials_ = false;
    589 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
    590   if (mutable_eap()) {
    591     mutable_eap()->Reset();
    592   }
    593   ClearEAPCertification();
    594 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
    595   Error error;  // Ignored.
    596   Disconnect(&error, __func__);
    597   return false;
    598 }
    599 
    600 void Service::Remove(Error* /*error*/) {
    601   manager()->RemoveService(this);
    602   // |this| may no longer be valid now.
    603 }
    604 
    605 bool Service::Save(StoreInterface* storage) {
    606   const string id = GetStorageIdentifier();
    607 
    608   storage->SetString(id, kStorageType, GetTechnologyString());
    609 
    610   if (retain_auto_connect_) {
    611     storage->SetBool(id, kStorageAutoConnect, auto_connect_);
    612   } else {
    613     storage->DeleteKey(id, kStorageAutoConnect);
    614   }
    615 
    616   // Remove this legacy flag.
    617   storage->DeleteKey(id, kStorageFavorite);
    618 
    619   if (check_portal_ == kCheckPortalAuto) {
    620     storage->DeleteKey(id, kStorageCheckPortal);
    621   } else {
    622     storage->SetString(id, kStorageCheckPortal, check_portal_);
    623   }
    624 
    625   SaveString(storage, id, kStorageGUID, guid_, false, true);
    626   storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
    627   storage->SetString(id, kStorageName, friendly_name_);
    628   if (priority_ != kPriorityNone) {
    629     storage->SetInt(id, kStoragePriority, priority_);
    630   } else {
    631     storage->DeleteKey(id, kStoragePriority);
    632   }
    633   if (priority_within_technology_ != kPriorityNone) {
    634     storage->SetInt(id, kStoragePriorityWithinTechnology,
    635                     priority_within_technology_);
    636   } else {
    637     storage->DeleteKey(id, kStoragePriorityWithinTechnology);
    638   }
    639   SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
    640   storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
    641   SaveString(storage, id, kStorageUIData, ui_data_, false, true);
    642 
    643   storage->SetInt(id, kStorageConnectionId, connection_id_);
    644   storage->SetBool(id, kStorageDNSAutoFallback, is_dns_auto_fallback_allowed_);
    645   storage->SetBool(id, kStorageLinkMonitorDisabled, link_monitor_disabled_);
    646   storage->SetBool(id, kStorageManagedCredentials, managed_credentials_);
    647 
    648   static_ip_parameters_.Save(storage, id);
    649 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
    650   if (eap()) {
    651     eap()->Save(storage, id, save_credentials_);
    652   }
    653 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
    654   dhcp_properties_->Save(storage, id);
    655   return true;
    656 }
    657 
    658 void Service::Configure(const KeyValueStore& args, Error* error) {
    659   for (const auto it : args.properties()) {
    660     if (it.second.IsTypeCompatible<bool>()) {
    661       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    662         SLOG(this, 5) << "Ignoring bool property: " << it.first;
    663         continue;
    664       }
    665       SLOG(this, 5) << "Configuring bool property: " << it.first;
    666       Error set_error;
    667       store_.SetBoolProperty(it.first, it.second.Get<bool>(), &set_error);
    668       if (error->IsSuccess() && set_error.IsFailure()) {
    669         error->CopyFrom(set_error);
    670       }
    671     } else if (it.second.IsTypeCompatible<int32_t>()) {
    672       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    673         SLOG(this, 5) << "Ignoring int32_t property: " << it.first;
    674         continue;
    675       }
    676       SLOG(this, 5) << "Configuring int32_t property: " << it.first;
    677       Error set_error;
    678       store_.SetInt32Property(it.first, it.second.Get<int32_t>(), &set_error);
    679       if (error->IsSuccess() && set_error.IsFailure()) {
    680         error->CopyFrom(set_error);
    681       }
    682     } else if (it.second.IsTypeCompatible<KeyValueStore>()) {
    683       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    684         SLOG(this, 5) << "Ignoring key value store property: " << it.first;
    685         continue;
    686       }
    687       SLOG(this, 5) << "Configuring key value store property: " << it.first;
    688       Error set_error;
    689       store_.SetKeyValueStoreProperty(it.first,
    690                                       it.second.Get<KeyValueStore>(),
    691                                       &set_error);
    692       if (error->IsSuccess() && set_error.IsFailure()) {
    693         error->CopyFrom(set_error);
    694       }
    695     } else if (it.second.IsTypeCompatible<string>()) {
    696       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    697         SLOG(this, 5) << "Ignoring string property: " << it.first;
    698         continue;
    699       }
    700       SLOG(this, 5) << "Configuring string property: " << it.first;
    701       Error set_error;
    702       store_.SetStringProperty(it.first, it.second.Get<string>(), &set_error);
    703       if (error->IsSuccess() && set_error.IsFailure()) {
    704         error->CopyFrom(set_error);
    705       }
    706     } else if (it.second.IsTypeCompatible<Strings>()) {
    707       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    708         SLOG(this, 5) << "Ignoring strings property: " << it.first;
    709         continue;
    710       }
    711       SLOG(this, 5) << "Configuring strings property: " << it.first;
    712       Error set_error;
    713       store_.SetStringsProperty(it.first, it.second.Get<Strings>(), &set_error);
    714       if (error->IsSuccess() && set_error.IsFailure()) {
    715         error->CopyFrom(set_error);
    716       }
    717     } else if (it.second.IsTypeCompatible<Stringmap>()) {
    718       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
    719         SLOG(this, 5) << "Ignoring stringmap property: " << it.first;
    720         continue;
    721       }
    722       SLOG(this, 5) << "Configuring stringmap property: " << it.first;
    723       Error set_error;
    724       store_.SetStringmapProperty(it.first,
    725                                   it.second.Get<Stringmap>(),
    726                                   &set_error);
    727       if (error->IsSuccess() && set_error.IsFailure()) {
    728         error->CopyFrom(set_error);
    729       }
    730     }
    731   }
    732 }
    733 
    734 bool Service::DoPropertiesMatch(const KeyValueStore& args) const {
    735   for (const auto& it : args.properties()) {
    736     if (it.second.IsTypeCompatible<bool>()) {
    737       SLOG(this, 5) << "Checking bool property: " << it.first;
    738       Error get_error;
    739       bool value;
    740       if (!store_.GetBoolProperty(it.first, &value, &get_error) ||
    741           value != it.second.Get<bool>()) {
    742         return false;
    743       }
    744     } else if (it.second.IsTypeCompatible<int32_t>()) {
    745       SLOG(this, 5) << "Checking int32 property: " << it.first;
    746       Error get_error;
    747       int32_t value;
    748       if (!store_.GetInt32Property(it.first, &value, &get_error) ||
    749           value != it.second.Get<int32_t>()) {
    750         return false;
    751       }
    752     } else if (it.second.IsTypeCompatible<string>()) {
    753       SLOG(this, 5) << "Checking string property: " << it.first;
    754       Error get_error;
    755       string value;
    756       if (!store_.GetStringProperty(it.first, &value, &get_error) ||
    757           value != it.second.Get<string>()) {
    758         return false;
    759       }
    760     } else if (it.second.IsTypeCompatible<Strings>()) {
    761       SLOG(this, 5) << "Checking strings property: " << it.first;
    762       Error get_error;
    763       Strings value;
    764       if (!store_.GetStringsProperty(it.first, &value, &get_error) ||
    765           value != it.second.Get<Strings>()) {
    766         return false;
    767       }
    768     } else if (it.second.IsTypeCompatible<Stringmap>()) {
    769       SLOG(this, 5) << "Checking stringmap property: " << it.first;
    770       Error get_error;
    771       Stringmap value;
    772       if (!store_.GetStringmapProperty(it.first, &value, &get_error) ||
    773           value != it.second.Get<Stringmap>()) {
    774         return false;
    775       }
    776     } else if (it.second.IsTypeCompatible<KeyValueStore>()) {
    777       SLOG(this, 5) << "Checking key value store property: " << it.first;
    778       Error get_error;
    779       KeyValueStore value;
    780       if (!store_.GetKeyValueStoreProperty(it.first, &value, &get_error) ||
    781           value != it.second.Get<KeyValueStore>()) {
    782         return false;
    783       }
    784     }
    785   }
    786   return true;
    787 }
    788 
    789 bool Service::IsRemembered() const {
    790   return profile_ && !manager_->IsServiceEphemeral(this);
    791 }
    792 
    793 bool Service::IsDependentOn(const ServiceRefPtr& b) const {
    794   if (!connection_ || !b || !b->connection()) {
    795     return false;
    796   }
    797   return connection_->GetLowerConnection() == b->connection();
    798 }
    799 
    800 void Service::EnableAndRetainAutoConnect() {
    801   if (retain_auto_connect_) {
    802     // We do not want to clobber the value of auto_connect_ (it may
    803     // be user-set). So return early.
    804     return;
    805   }
    806 
    807   SetAutoConnect(true);
    808   RetainAutoConnect();
    809 }
    810 
    811 void Service::SetConnection(const ConnectionRefPtr& connection) {
    812   if (connection.get()) {
    813     // TODO(pstew): Make this function testable by using a factory here.
    814     // http://crbug.com/216664
    815     http_proxy_.reset(new HTTPProxy(connection));
    816     http_proxy_->Start(dispatcher_, sockets_.get());
    817     Error unused_error;
    818     connection->set_tethering(GetTethering(&unused_error));
    819   } else {
    820     http_proxy_.reset();
    821     static_ip_parameters_.ClearSavedParameters();
    822   }
    823   connection_ = connection;
    824   NotifyIPConfigChanges();
    825 }
    826 
    827 void Service::NotifyIPConfigChanges() {
    828   Error error;
    829   string ipconfig = GetIPConfigRpcIdentifier(&error);
    830   if (error.IsSuccess()) {
    831     adaptor_->EmitRpcIdentifierChanged(kIPConfigProperty, ipconfig);
    832   }
    833 }
    834 
    835 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
    836 bool Service::Is8021xConnectable() const {
    837   return eap() && eap()->IsConnectable();
    838 }
    839 
    840 bool Service::AddEAPCertification(const string& name, size_t depth) {
    841   if (depth >= kEAPMaxCertificationElements) {
    842     LOG(WARNING) << "Ignoring certification " << name
    843                  << " because depth " << depth
    844                  << " exceeds our maximum of "
    845                  << kEAPMaxCertificationElements;
    846     return false;
    847   }
    848 
    849   if (depth >= remote_certification_.size()) {
    850     remote_certification_.resize(depth + 1);
    851   } else if (name == remote_certification_[depth]) {
    852     return true;
    853   }
    854 
    855   remote_certification_[depth] = name;
    856   LOG(INFO) << "Received certification for "
    857             << name
    858             << " at depth "
    859             << depth;
    860   return true;
    861 }
    862 
    863 void Service::ClearEAPCertification() {
    864   remote_certification_.clear();
    865 }
    866 
    867 void Service::SetEapCredentials(EapCredentials* eap) {
    868   // This operation must be done at most once for the lifetime of the service.
    869   CHECK(eap && !eap_);
    870 
    871   eap_.reset(eap);
    872   eap_->InitPropertyStore(mutable_store());
    873 }
    874 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
    875 
    876 bool Service::HasStaticIPAddress() const {
    877   return static_ip_parameters().ContainsAddress();
    878 }
    879 
    880 bool Service::HasStaticNameServers() const {
    881   return static_ip_parameters().ContainsNameServers();
    882 }
    883 
    884 void Service::SetAutoConnect(bool connect) {
    885   if (auto_connect() == connect) {
    886     return;
    887   }
    888   auto_connect_ = connect;
    889   adaptor_->EmitBoolChanged(kAutoConnectProperty, auto_connect());
    890 }
    891 
    892 // static
    893 // Note: keep in sync with ERROR_* constants in
    894 // android/system/connectivity/shill/IService.aidl.
    895 const char* Service::ConnectFailureToString(const ConnectFailure& state) {
    896   switch (state) {
    897     case kFailureUnknown:
    898       return "Unknown";
    899     case kFailureAAA:
    900       return kErrorAaaFailed;
    901     case kFailureActivation:
    902       return kErrorActivationFailed;
    903     case kFailureBadPassphrase:
    904       return kErrorBadPassphrase;
    905     case kFailureBadWEPKey:
    906       return kErrorBadWEPKey;
    907     case kFailureConnect:
    908       return kErrorConnectFailed;
    909     case kFailureDNSLookup:
    910       return kErrorDNSLookupFailed;
    911     case kFailureDHCP:
    912       return kErrorDhcpFailed;
    913     case kFailureEAPAuthentication:
    914       return kErrorEapAuthenticationFailed;
    915     case kFailureEAPLocalTLS:
    916       return kErrorEapLocalTlsFailed;
    917     case kFailureEAPRemoteTLS:
    918       return kErrorEapRemoteTlsFailed;
    919     case kFailureHTTPGet:
    920       return kErrorHTTPGetFailed;
    921     case kFailureInternal:
    922       return kErrorInternal;
    923     case kFailureIPSecCertAuth:
    924       return kErrorIpsecCertAuthFailed;
    925     case kFailureIPSecPSKAuth:
    926       return kErrorIpsecPskAuthFailed;
    927     case kFailureNeedEVDO:
    928       return kErrorNeedEvdo;
    929     case kFailureNeedHomeNetwork:
    930       return kErrorNeedHomeNetwork;
    931     case kFailureOTASP:
    932       return kErrorOtaspFailed;
    933     case kFailureOutOfRange:
    934       return kErrorOutOfRange;
    935     case kFailurePinMissing:
    936       return kErrorPinMissing;
    937     case kFailurePPPAuth:
    938       return kErrorPppAuthFailed;
    939     case kFailureMax:
    940       NOTREACHED();
    941   }
    942   return "Invalid";
    943 }
    944 
    945 // static
    946 const char* Service::ConnectStateToString(const ConnectState& state) {
    947   switch (state) {
    948     case kStateUnknown:
    949       return "Unknown";
    950     case kStateIdle:
    951       return "Idle";
    952     case kStateAssociating:
    953       return "Associating";
    954     case kStateConfiguring:
    955       return "Configuring";
    956     case kStateConnected:
    957       return "Connected";
    958     case kStatePortal:
    959       return "Portal";
    960     case kStateFailure:
    961       return "Failure";
    962     case kStateOnline:
    963       return "Online";
    964   }
    965   return "Invalid";
    966 }
    967 
    968 string Service::GetTechnologyString() const {
    969   return Technology::NameFromIdentifier(technology());
    970 }
    971 
    972 string Service::CalculateTechnology(Error* /*error*/) {
    973   return GetTechnologyString();
    974 }
    975 
    976 void Service::NoteDisconnectEvent() {
    977   SLOG(this, 2) << __func__;
    978   // Ignore the event if it's user-initiated explicit disconnect.
    979   if (explicitly_disconnected_) {
    980     SLOG(this, 2) << "Explicit disconnect ignored.";
    981     return;
    982   }
    983   // Ignore the event if manager is not running (e.g., service disconnects on
    984   // shutdown).
    985   if (!manager_->running()) {
    986     SLOG(this, 2) << "Disconnect while manager stopped ignored.";
    987     return;
    988   }
    989   // Ignore the event if the system is suspending.
    990   PowerManager* power_manager = manager_->power_manager();
    991   if (!power_manager || power_manager->suspending()) {
    992     SLOG(this, 2) << "Disconnect in transitional power state ignored.";
    993     return;
    994   }
    995   int period = 0;
    996   EventHistory* events = nullptr;
    997   // Sometimes services transition to Idle before going into a failed state so
    998   // take into account the last non-idle state.
    999   ConnectState state = state_ == kStateIdle ? previous_state_ : state_;
   1000   if (IsConnectedState(state)) {
   1001     LOG(INFO) << "Noting an unexpected connection drop.";
   1002     period = kDisconnectsMonitorSeconds;
   1003     events = &disconnects_;
   1004   } else if (IsConnectingState(state)) {
   1005     LOG(INFO) << "Noting an unexpected failure to connect.";
   1006     period = kMisconnectsMonitorSeconds;
   1007     events = &misconnects_;
   1008   } else {
   1009     SLOG(this, 2)
   1010         << "Not connected or connecting, state transition ignored.";
   1011     return;
   1012   }
   1013   events->RecordEventAndExpireEventsBefore(period,
   1014                                            EventHistory::kClockTypeMonotonic);
   1015 }
   1016 
   1017 void Service::ReportUserInitiatedConnectionResult(ConnectState state) {
   1018   // Report stats for wifi only for now.
   1019   if (technology_ != Technology::kWifi)
   1020     return;
   1021 
   1022   int result;
   1023   switch (state) {
   1024     case kStateConnected:
   1025       result = Metrics::kUserInitiatedConnectionResultSuccess;
   1026       break;
   1027     case kStateFailure:
   1028       result = Metrics::kUserInitiatedConnectionResultFailure;
   1029       metrics_->NotifyUserInitiatedConnectionFailureReason(
   1030           Metrics::kMetricWifiUserInitiatedConnectionFailureReason, failure_);
   1031       break;
   1032     case kStateIdle:
   1033       // This assumes the device specific class (wifi, cellular) will advance
   1034       // the service's state from idle to other state after connection attempt
   1035       // is initiated for the given service.
   1036       result = Metrics::kUserInitiatedConnectionResultAborted;
   1037       break;
   1038     default:
   1039       return;
   1040   }
   1041 
   1042   metrics_->NotifyUserInitiatedConnectionResult(
   1043       Metrics::kMetricWifiUserInitiatedConnectionResult, result);
   1044 }
   1045 
   1046 bool Service::HasRecentConnectionIssues() {
   1047   disconnects_.ExpireEventsBefore(kDisconnectsMonitorSeconds,
   1048                                   EventHistory::kClockTypeMonotonic);
   1049   misconnects_.ExpireEventsBefore(kMisconnectsMonitorSeconds,
   1050                                   EventHistory::kClockTypeMonotonic);
   1051   return !disconnects_.Empty() || !misconnects_.Empty();
   1052 }
   1053 
   1054 // static
   1055 bool Service::DecideBetween(int a, int b, bool* decision) {
   1056   if (a == b)
   1057     return false;
   1058   *decision = (a > b);
   1059   return true;
   1060 }
   1061 
   1062 uint16_t Service::SecurityLevel() {
   1063   return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_;
   1064 }
   1065 
   1066 // static
   1067 bool Service::Compare(Manager* manager,
   1068                       ServiceRefPtr a,
   1069                       ServiceRefPtr b,
   1070                       bool compare_connectivity_state,
   1071                       const vector<Technology::Identifier>& tech_order,
   1072                       const char** reason) {
   1073   bool ret;
   1074 
   1075   if (compare_connectivity_state && a->state() != b->state()) {
   1076     if (DecideBetween(a->IsOnline(), b->IsOnline(), &ret)) {
   1077       *reason = kServiceSortIsOnline;
   1078       return ret;
   1079     }
   1080 
   1081     if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
   1082       *reason = kServiceSortIsConnected;
   1083       return ret;
   1084     }
   1085 
   1086     if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
   1087       *reason = kServiceSortIsPortalled;
   1088       return ret;
   1089     }
   1090 
   1091     if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
   1092       *reason = kServiceSortIsConnecting;
   1093       return ret;
   1094     }
   1095 
   1096     if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
   1097       *reason = kServiceSortIsFailed;
   1098       return ret;
   1099     }
   1100   }
   1101 
   1102   if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
   1103     *reason = kServiceSortConnectable;
   1104     return ret;
   1105   }
   1106 
   1107   if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
   1108     *reason = kServiceSortDependency;
   1109     return ret;
   1110   }
   1111 
   1112   // Ignore the auto-connect property if both services are connected
   1113   // already. This allows connected non-autoconnectable VPN services to be
   1114   // sorted higher than other connected services based on technology order.
   1115   if (!a->IsConnected() &&
   1116       DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
   1117     *reason = kServiceSortAutoConnect;
   1118     return ret;
   1119   }
   1120 
   1121   if (DecideBetween(a->has_ever_connected() || a->managed_credentials_,
   1122                     b->has_ever_connected() || b->managed_credentials_,
   1123                     &ret)) {
   1124     *reason = kServiceSortHasEverConnected;
   1125     return ret;
   1126   }
   1127 
   1128   if (DecideBetween(a->priority(), b->priority(), &ret)) {
   1129     *reason = kServiceSortPriority;
   1130     return ret;
   1131   }
   1132 
   1133   // TODO(pstew): Below this point we are making value judgements on
   1134   // services that are not related to anything intrinsic or
   1135   // user-specified.  These heuristics should be richer (contain
   1136   // historical information, for example) and be subject to user
   1137   // customization.
   1138   for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
   1139        it != tech_order.end();
   1140        ++it) {
   1141     if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
   1142       *reason = kServiceSortTechnology;
   1143       return ret;
   1144     }
   1145   }
   1146 
   1147   if (DecideBetween(a->priority_within_technology(),
   1148                     b->priority_within_technology(), &ret)) {
   1149     *reason = kServiceSortPriorityWithinTechnology;
   1150     return ret;
   1151   }
   1152 
   1153   if (DecideBetween(a->SecurityLevel(), b->SecurityLevel(), &ret)) {
   1154     *reason = kServiceSortSecurity;
   1155     return ret;
   1156   }
   1157 
   1158   // If the profiles for the two services are different,
   1159   // we want to pick the highest priority one.  The
   1160   // ephemeral profile is explicitly tested for since it is not
   1161   // listed in the manager profiles_ list.
   1162   if (a->profile() != b->profile()) {
   1163     *reason = kServiceSortProfileOrder;
   1164     if (manager->IsServiceEphemeral(b)) {
   1165       return true;
   1166     } else if (manager->IsServiceEphemeral(a)) {
   1167       return false;
   1168     } else if (manager->IsProfileBefore(b->profile(), a->profile())) {
   1169       return true;
   1170     } else {
   1171       return false;
   1172     }
   1173   }
   1174 
   1175   if (DecideBetween(a->strength(), b->strength(), &ret)) {
   1176     *reason = kServiceSortEtc;
   1177     return ret;
   1178   }
   1179 
   1180   *reason = kServiceSortSerialNumber;
   1181   return a->serial_number_ < b->serial_number_;
   1182 }
   1183 
   1184 const ProfileRefPtr& Service::profile() const { return profile_; }
   1185 
   1186 void Service::set_profile(const ProfileRefPtr& p) { profile_ = p; }
   1187 
   1188 void Service::SetProfile(const ProfileRefPtr& p) {
   1189   SLOG(this, 2) << "SetProfile from "
   1190                 << (profile_ ? profile_->GetFriendlyName() : "(none)")
   1191                 << " to " << (p ? p->GetFriendlyName() : "(none)")
   1192                 << ".";
   1193   if (profile_ == p) {
   1194     return;
   1195   }
   1196   profile_ = p;
   1197   Error error;
   1198   string profile_rpc_id = GetProfileRpcId(&error);
   1199   if (!error.IsSuccess()) {
   1200     return;
   1201   }
   1202   adaptor_->EmitStringChanged(kProfileProperty, profile_rpc_id);
   1203 }
   1204 
   1205 void Service::OnPropertyChanged(const string& property) {
   1206   SLOG(this, 1) << __func__ << " " << property;
   1207 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
   1208   if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
   1209     OnEapCredentialsChanged(kReasonPropertyUpdate);
   1210   }
   1211 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
   1212   SaveToProfile();
   1213   if ((property == kCheckPortalProperty ||
   1214        property == kProxyConfigProperty) &&
   1215       (state_ == kStateConnected ||
   1216        state_ == kStatePortal ||
   1217        state_ == kStateOnline)) {
   1218     manager_->RecheckPortalOnService(this);
   1219   }
   1220 }
   1221 
   1222 void Service::OnAfterResume() {
   1223   // Forget old autoconnect failures across suspend/resume.
   1224   auto_connect_cooldown_milliseconds_  = 0;
   1225   reenable_auto_connect_task_.Cancel();
   1226   // Forget if the user disconnected us, we might be able to connect now.
   1227   ClearExplicitlyDisconnected();
   1228 }
   1229 
   1230 void Service::OnDarkResume() {
   1231   // Nothing to do in the general case.
   1232 }
   1233 
   1234 string Service::GetIPConfigRpcIdentifier(Error* error) const {
   1235   if (!connection_) {
   1236     error->Populate(Error::kNotFound);
   1237     return control_interface_->NullRPCIdentifier();
   1238   }
   1239 
   1240   string id = connection_->ipconfig_rpc_identifier();
   1241 
   1242   if (id.empty()) {
   1243     // Do not return an empty IPConfig.
   1244     error->Populate(Error::kNotFound);
   1245     return control_interface_->NullRPCIdentifier();
   1246   }
   1247 
   1248   return id;
   1249 }
   1250 
   1251 void Service::SetConnectable(bool connectable) {
   1252   if (connectable_ == connectable)
   1253     return;
   1254   connectable_ = connectable;
   1255   adaptor_->EmitBoolChanged(kConnectableProperty, connectable_);
   1256 }
   1257 
   1258 void Service::SetConnectableFull(bool connectable) {
   1259   if (connectable_ == connectable) {
   1260     return;
   1261   }
   1262   SetConnectable(connectable);
   1263   if (manager_->HasService(this)) {
   1264     manager_->UpdateService(this);
   1265   }
   1266 }
   1267 
   1268 string Service::GetStateString() const {
   1269   // TODO(benchan): We may want to rename shill::kState* to avoid name clashing
   1270   // with Service::kState*.
   1271   switch (state()) {
   1272     case kStateIdle:
   1273       return shill::kStateIdle;
   1274     case kStateAssociating:
   1275       return shill::kStateAssociation;
   1276     case kStateConfiguring:
   1277       return shill::kStateConfiguration;
   1278     case kStateConnected:
   1279       return shill::kStateReady;
   1280     case kStateFailure:
   1281       return shill::kStateFailure;
   1282     case kStatePortal:
   1283       return shill::kStatePortal;
   1284     case kStateOnline:
   1285       return shill::kStateOnline;
   1286     case kStateUnknown:
   1287     default:
   1288       return "";
   1289   }
   1290 }
   1291 
   1292 string Service::CalculateState(Error* /*error*/) {
   1293   return GetStateString();
   1294 }
   1295 
   1296 bool Service::IsAutoConnectable(const char** reason) const {
   1297   if (manager_->IsTechnologyAutoConnectDisabled(technology_)) {
   1298     *reason = kAutoConnTechnologyNotConnectable;
   1299     return false;
   1300   }
   1301 
   1302   if (!connectable()) {
   1303     *reason = kAutoConnNotConnectable;
   1304     return false;
   1305   }
   1306 
   1307   if (IsConnected()) {
   1308     *reason = kAutoConnConnected;
   1309     return false;
   1310   }
   1311 
   1312   if (IsConnecting()) {
   1313     *reason = kAutoConnConnecting;
   1314     return false;
   1315   }
   1316 
   1317   if (explicitly_disconnected_) {
   1318     *reason = kAutoConnExplicitDisconnect;
   1319     return false;
   1320   }
   1321 
   1322   if (!reenable_auto_connect_task_.IsCancelled()) {
   1323     *reason = kAutoConnThrottled;
   1324     return false;
   1325   }
   1326 
   1327   if (!Technology::IsPrimaryConnectivityTechnology(technology_) &&
   1328       !manager_->IsConnected()) {
   1329     *reason = kAutoConnOffline;
   1330     return false;
   1331   }
   1332 
   1333   return true;
   1334 }
   1335 
   1336 bool Service::IsPortalDetectionDisabled() const {
   1337   return check_portal_ == kCheckPortalFalse;
   1338 }
   1339 
   1340 bool Service::IsPortalDetectionAuto() const {
   1341   return check_portal_ == kCheckPortalAuto;
   1342 }
   1343 
   1344 void Service::HelpRegisterDerivedBool(
   1345     const string& name,
   1346     bool(Service::*get)(Error* error),
   1347     bool(Service::*set)(const bool&, Error*),
   1348     void(Service::*clear)(Error*)) {
   1349   store_.RegisterDerivedBool(
   1350       name,
   1351       BoolAccessor(new CustomAccessor<Service, bool>(this, get, set, clear)));
   1352 }
   1353 
   1354 void Service::HelpRegisterDerivedInt32(
   1355     const string& name,
   1356     int32_t(Service::*get)(Error* error),
   1357     bool(Service::*set)(const int32_t&, Error*)) {
   1358   store_.RegisterDerivedInt32(
   1359       name,
   1360       Int32Accessor(new CustomAccessor<Service, int32_t>(this, get, set)));
   1361 }
   1362 
   1363 void Service::HelpRegisterDerivedString(
   1364     const string& name,
   1365     string(Service::*get)(Error* error),
   1366     bool(Service::*set)(const string&, Error*)) {
   1367   store_.RegisterDerivedString(
   1368       name,
   1369       StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
   1370 }
   1371 
   1372 void Service::HelpRegisterConstDerivedRpcIdentifier(
   1373     const string& name,
   1374     RpcIdentifier(Service::*get)(Error*) const) {
   1375   store_.RegisterDerivedRpcIdentifier(
   1376       name,
   1377       RpcIdentifierAccessor(new CustomReadOnlyAccessor<Service, RpcIdentifier>(
   1378           this, get)));
   1379 }
   1380 
   1381 void Service::HelpRegisterConstDerivedUint16(
   1382     const string& name,
   1383     uint16_t(Service::*get)(Error*) const) {
   1384   store_.RegisterDerivedUint16(
   1385       name,
   1386       Uint16Accessor(new CustomReadOnlyAccessor<Service, uint16_t>(this, get)));
   1387 }
   1388 
   1389 void Service::HelpRegisterConstDerivedStrings(
   1390     const string& name, Strings(Service::*get)(Error* error) const) {
   1391   store_.RegisterDerivedStrings(
   1392       name,
   1393       StringsAccessor(new CustomReadOnlyAccessor<Service, Strings>(this, get)));
   1394 }
   1395 
   1396 void Service::HelpRegisterConstDerivedString(
   1397     const string& name, string(Service::*get)(Error* error) const) {
   1398   store_.RegisterDerivedString(
   1399       name,
   1400       StringAccessor(new CustomReadOnlyAccessor<Service, string>(this, get)));
   1401 }
   1402 
   1403 void Service::HelpRegisterObservedDerivedBool(
   1404     const string& name,
   1405     bool(Service::*get)(Error* error),
   1406     bool(Service::*set)(const bool&, Error*),
   1407     void(Service::*clear)(Error*)) {
   1408   BoolAccessor accessor(
   1409       new CustomAccessor<Service, bool>(this, get, set, clear));
   1410   store_.RegisterDerivedBool(name, accessor);
   1411   property_change_notifier_->AddBoolPropertyObserver(name, accessor);
   1412 }
   1413 
   1414 // static
   1415 void Service::LoadString(StoreInterface* storage,
   1416                          const string& id,
   1417                          const string& key,
   1418                          const string& default_value,
   1419                          string* value) {
   1420   if (!storage->GetString(id, key, value)) {
   1421     *value = default_value;
   1422   }
   1423 }
   1424 
   1425 // static
   1426 void Service::SaveString(StoreInterface* storage,
   1427                          const string& id,
   1428                          const string& key,
   1429                          const string& value,
   1430                          bool crypted,
   1431                          bool save) {
   1432   if (value.empty() || !save) {
   1433     storage->DeleteKey(id, key);
   1434     return;
   1435   }
   1436   if (crypted) {
   1437     storage->SetCryptedString(id, key, value);
   1438     return;
   1439   }
   1440   storage->SetString(id, key, value);
   1441 }
   1442 
   1443 map<string, string> Service::GetLoadableProfileEntries() {
   1444   return manager_->GetLoadableProfileEntriesForService(this);
   1445 }
   1446 
   1447 void Service::IgnoreParameterForConfigure(const string& parameter) {
   1448   parameters_ignored_for_configure_.insert(parameter);
   1449 }
   1450 
   1451 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
   1452 const string& Service::GetEAPKeyManagement() const {
   1453   CHECK(eap());
   1454   return eap()->key_management();
   1455 }
   1456 
   1457 void Service::SetEAPKeyManagement(const string& key_management) {
   1458   CHECK(mutable_eap());
   1459   mutable_eap()->SetKeyManagement(key_management, nullptr);
   1460 }
   1461 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
   1462 
   1463 bool Service::GetAutoConnect(Error* /*error*/) {
   1464   return auto_connect();
   1465 }
   1466 
   1467 bool Service::SetAutoConnectFull(const bool& connect, Error* /*error*/) {
   1468   LOG(INFO) << "Service " << unique_name() << ": AutoConnect="
   1469             << auto_connect() << "->" << connect;
   1470   if (!retain_auto_connect_) {
   1471     RetainAutoConnect();
   1472     // Irrespective of an actual change in the |kAutoConnectPropety|, we must
   1473     // flush the current value of the property to the profile.
   1474     if (IsRemembered()) {
   1475       SaveToProfile();
   1476     }
   1477   }
   1478 
   1479   if (auto_connect() == connect) {
   1480     return false;
   1481   }
   1482 
   1483   SetAutoConnect(connect);
   1484   manager_->UpdateService(this);
   1485   return true;
   1486 }
   1487 
   1488 void Service::ClearAutoConnect(Error* /*error*/) {
   1489   if (auto_connect()) {
   1490     SetAutoConnect(false);
   1491     manager_->UpdateService(this);
   1492   }
   1493 
   1494   retain_auto_connect_ = false;
   1495 }
   1496 
   1497 string Service::GetCheckPortal(Error* error) {
   1498   return check_portal_;
   1499 }
   1500 
   1501 bool Service::SetCheckPortal(const string& check_portal, Error* error) {
   1502   if (check_portal != kCheckPortalFalse &&
   1503       check_portal != kCheckPortalTrue &&
   1504       check_portal != kCheckPortalAuto) {
   1505     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   1506                           base::StringPrintf(
   1507                               "Invalid Service CheckPortal property value: %s",
   1508                               check_portal.c_str()));
   1509     return false;
   1510   }
   1511   if (check_portal == check_portal_) {
   1512     return false;
   1513   }
   1514   check_portal_ = check_portal;
   1515   return true;
   1516 }
   1517 
   1518 string Service::GetGuid(Error* error) {
   1519   return guid_;
   1520 }
   1521 
   1522 bool Service::SetGuid(const string& guid, Error* /*error*/) {
   1523   if (guid_ == guid) {
   1524     return false;
   1525   }
   1526   guid_ = guid;
   1527   adaptor_->EmitStringChanged(kGuidProperty, guid_);
   1528   return true;
   1529 }
   1530 
   1531 void Service::RetainAutoConnect() {
   1532   retain_auto_connect_ = true;
   1533 }
   1534 
   1535 void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
   1536                           bool endpoint_auth) {
   1537   crypto_algorithm_ = crypto_algorithm;
   1538   key_rotation_ = key_rotation;
   1539   endpoint_auth_ = endpoint_auth;
   1540 }
   1541 
   1542 string Service::GetNameProperty(Error* /*error*/) {
   1543   return friendly_name_;
   1544 }
   1545 
   1546 bool Service::SetNameProperty(const string& name, Error* error) {
   1547   if (name != friendly_name_) {
   1548     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   1549                           base::StringPrintf(
   1550                               "Service %s Name property cannot be modified.",
   1551                               unique_name_.c_str()));
   1552     return false;
   1553   }
   1554   return false;
   1555 }
   1556 
   1557 void Service::SetHasEverConnected(bool has_ever_connected) {
   1558   if (has_ever_connected_ == has_ever_connected)
   1559     return;
   1560   has_ever_connected_ = has_ever_connected;
   1561 }
   1562 
   1563 int32_t Service::GetPriority(Error* error) {
   1564   return priority_;
   1565 }
   1566 
   1567 bool Service::SetPriority(const int32_t& priority, Error* error) {
   1568   if (priority_ == priority) {
   1569     return false;
   1570   }
   1571   priority_ = priority;
   1572   adaptor_->EmitIntChanged(kPriorityProperty, priority_);
   1573   return true;
   1574 }
   1575 
   1576 int32_t Service::GetPriorityWithinTechnology(Error* error) {
   1577   return priority_within_technology_;
   1578 }
   1579 
   1580 bool Service::SetPriorityWithinTechnology(const int32_t& priority,
   1581                                           Error* error) {
   1582   if (priority_within_technology_ == priority) {
   1583     return false;
   1584   }
   1585   priority_within_technology_ = priority;
   1586   adaptor_->EmitIntChanged(kPriorityWithinTechnologyProperty,
   1587                            priority_within_technology_);
   1588   return true;
   1589 }
   1590 
   1591 string Service::GetProfileRpcId(Error* error) {
   1592   if (!profile_) {
   1593     // This happens in some unit tests where profile_ is not set.
   1594     error->Populate(Error::kNotFound);
   1595     return "";
   1596   }
   1597   return profile_->GetRpcIdentifier();
   1598 }
   1599 
   1600 bool Service::SetProfileRpcId(const string& profile, Error* error) {
   1601   if (profile_ && profile_->GetRpcIdentifier() == profile) {
   1602     return false;
   1603   }
   1604   ProfileConstRefPtr old_profile = profile_;
   1605   // No need to Emit afterwards, since SetProfileForService will call
   1606   // into SetProfile (if the profile actually changes).
   1607   manager_->SetProfileForService(this, profile, error);
   1608   // Can't just use error.IsSuccess(), because that also requires saving
   1609   // the profile to succeed. (See Profile::AdoptService)
   1610   return (profile_ != old_profile);
   1611 }
   1612 
   1613 uint16_t Service::GetHTTPProxyPort(Error* /*error*/) const {
   1614   if (http_proxy_.get()) {
   1615     return static_cast<uint16_t>(http_proxy_->proxy_port());
   1616   }
   1617   return 0;
   1618 }
   1619 
   1620 string Service::GetProxyConfig(Error* error) {
   1621   return proxy_config_;
   1622 }
   1623 
   1624 bool Service::SetProxyConfig(const string& proxy_config, Error* error) {
   1625   if (proxy_config_ == proxy_config)
   1626     return false;
   1627   proxy_config_ = proxy_config;
   1628   adaptor_->EmitStringChanged(kProxyConfigProperty, proxy_config_);
   1629   return true;
   1630 }
   1631 
   1632 string Service::GetTethering(Error* error) const {
   1633   // The "Tethering" property isn't supported by the Service base class, and
   1634   // therefore should not be listed in the properties returned by
   1635   // the GetProperties() RPC method.
   1636   error->Populate(Error::kNotSupported);
   1637   return "";
   1638 }
   1639 
   1640 
   1641 void Service::NotifyPropertyChanges() {
   1642   property_change_notifier_->UpdatePropertyObservers();
   1643 }
   1644 
   1645 Strings Service::GetDisconnectsProperty(Error* /*error*/) const {
   1646   return disconnects_.ExtractWallClockToStrings();
   1647 }
   1648 
   1649 Strings Service::GetMisconnectsProperty(Error* /*error*/) const {
   1650   return misconnects_.ExtractWallClockToStrings();
   1651 }
   1652 
   1653 bool Service::GetVisibleProperty(Error* /*error*/) {
   1654   return IsVisible();
   1655 }
   1656 
   1657 void Service::SaveToProfile() {
   1658   if (profile_.get() && profile_->GetConstStorage()) {
   1659     profile_->UpdateService(this);
   1660   }
   1661 }
   1662 
   1663 void Service::SetFriendlyName(const string& friendly_name) {
   1664   if (friendly_name == friendly_name_)
   1665     return;
   1666   friendly_name_ = friendly_name;
   1667   adaptor()->EmitStringChanged(kNameProperty, friendly_name_);
   1668 }
   1669 
   1670 void Service::SetStrength(uint8_t strength) {
   1671   if (strength == strength_) {
   1672     return;
   1673   }
   1674   strength_ = strength;
   1675   adaptor_->EmitUint8Changed(kSignalStrengthProperty, strength);
   1676 }
   1677 
   1678 void Service::SetErrorDetails(const string& details) {
   1679   if (error_details_ == details) {
   1680     return;
   1681   }
   1682   error_details_ = details;
   1683   adaptor_->EmitStringChanged(kErrorDetailsProperty, error_details_);
   1684 }
   1685 
   1686 void Service::UpdateErrorProperty() {
   1687   const string error(ConnectFailureToString(failure_));
   1688   if (error == error_) {
   1689     return;
   1690   }
   1691   error_ = error;
   1692   adaptor_->EmitStringChanged(kErrorProperty, error);
   1693 }
   1694 
   1695 void Service::ClearExplicitlyDisconnected() {
   1696   if (explicitly_disconnected_) {
   1697     explicitly_disconnected_ = false;
   1698     manager_->UpdateService(this);
   1699   }
   1700 }
   1701 
   1702 }  // namespace shill
   1703