real_shill_provider.cc revision b8803bbfe96abce0ae792a93bc975d478d98d16a
1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1655f39b7043fae6b7c27188d0cd797946098b42efGilad Arnold
1763784a578dd26880454d70797519358a2326291bAlex Deymo#include "update_engine/update_manager/real_shill_provider.h"
1855f39b7043fae6b7c27188d0cd797946098b42efGilad Arnold
195ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold#include <string>
205ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
215ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold#include <base/logging.h>
2275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h>
235ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold#include <chromeos/dbus/service_constants.h>
245ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
25b8803bbfe96abce0ae792a93bc975d478d98d16aAlex Deymo#include "shill/dbus-proxies.h"
26b8803bbfe96abce0ae792a93bc975d478d98d16aAlex Deymo
27305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ManagerProxyInterface;
28305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ServiceProxyInterface;
295ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnoldusing std::string;
305ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
3163784a578dd26880454d70797519358a2326291bAlex Deymonamespace chromeos_update_manager {
3255f39b7043fae6b7c27188d0cd797946098b42efGilad Arnold
33305345001d85ca2282112c2a30fe75c7a4773491Alex DeymoConnectionType RealShillProvider::ParseConnectionType(const string& type_str) {
34305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (type_str == shill::kTypeEthernet) {
35ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionType::kEthernet;
36305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeWifi) {
37ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionType::kWifi;
38305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeWimax) {
39ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionType::kWimax;
40305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeBluetooth) {
41ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionType::kBluetooth;
42305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeCellular) {
43ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionType::kCellular;
44305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
45ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  return ConnectionType::kUnknown;
46ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold}
47ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
48ef120fac0ff6364aaa8c6d05339065f118be25acGilad ArnoldConnectionTethering RealShillProvider::ParseConnectionTethering(
49305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    const string& tethering_str) {
50305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (tethering_str == shill::kTetheringNotDetectedState) {
51ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionTethering::kNotDetected;
52305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (tethering_str == shill::kTetheringSuspectedState) {
53ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionTethering::kSuspected;
54305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (tethering_str == shill::kTetheringConfirmedState) {
55ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return ConnectionTethering::kConfirmed;
56305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
57ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  return ConnectionTethering::kUnknown;
58ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold}
59beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
6042c30c376cb7b0b459ff0cbf3ac23fe87ea64f4dAlex Deymobool RealShillProvider::Init() {
61305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
62305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy)
635ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold    return false;
645ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
65beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold  // Subscribe to the manager's PropertyChanged signal.
66305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  manager_proxy->RegisterPropertyChangedSignalHandler(
67305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      base::Bind(&RealShillProvider::OnManagerPropertyChanged,
68305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                 base::Unretained(this)),
69305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      base::Bind(&RealShillProvider::OnSignalConnected,
70305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                 base::Unretained(this)));
715ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
72ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // Attempt to read initial connection status. Even if this fails because shill
73ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
74ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // signal as soon as it comes up, so this is not a critical step.
75305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  chromeos::VariantDictionary properties;
76305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  chromeos::ErrorPtr error;
77305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy->GetProperties(&properties, &error))
78305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return true;
79305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
80305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_default_service =
81305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      properties.find(shill::kDefaultServiceProperty);
82305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_default_service != properties.end()) {
83305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    OnManagerPropertyChanged(prop_default_service->first,
84305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                             prop_default_service->second);
855ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold  }
865ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
87ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  return true;
885ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
895ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
90305345001d85ca2282112c2a30fe75c7a4773491Alex Deymovoid RealShillProvider::OnManagerPropertyChanged(const string& name,
91305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                                 const chromeos::Any& value) {
92305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (name == shill::kDefaultServiceProperty)
93305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    ProcessDefaultService(value.TryGet<dbus::ObjectPath>().value());
945ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
955ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
96305345001d85ca2282112c2a30fe75c7a4773491Alex Deymovoid RealShillProvider::OnSignalConnected(const string& interface_name,
97305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                          const string& signal_name,
98305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                          bool successful) {
99305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!successful) {
100305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
101305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo               << signal_name;
1025ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold  }
1035ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
1045ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
105305345001d85ca2282112c2a30fe75c7a4773491Alex Deymobool RealShillProvider::ProcessDefaultService(
106305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    const string& default_service_path) {
107305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We assume that if the service path didn't change, then the connection
108305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // type and the tethering status of it also didn't change.
109305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (default_service_path_ == default_service_path)
110ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return true;
111ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
112d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  // Update the connection status.
113305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  default_service_path_ = default_service_path;
114d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  bool is_connected = (default_service_path_ != "/");
115d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  var_is_connected_.SetValue(is_connected);
116d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  var_conn_last_changed_.SetValue(clock_->GetWallclockTime());
117ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
118305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!is_connected) {
119305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_type_.UnsetValue();
120305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.UnsetValue();
121305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return true;
122305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
123ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
124305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We create and dispose the ServiceProxyInterface on every request.
125305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  std::unique_ptr<ServiceProxyInterface> service =
126305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      shill_proxy_->GetServiceForPath(default_service_path_);
127ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
128305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection properties synchronously.
129305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  chromeos::VariantDictionary properties;
130305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  chromeos::ErrorPtr error;
131305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!service->GetProperties(&properties, &error)) {
132d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold    var_conn_type_.UnsetValue();
133d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold    var_conn_tethering_.UnsetValue();
134305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
135ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  }
136df3dd2438aef108ac66dc42a4eabae8c79ee88a3Gilad Arnold
137305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection tethering mode.
138305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
139305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_tethering == properties.end()) {
140305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Remove the value if not present on the service. This most likely means an
141305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // error in shill and the policy will handle it, but we will print a log
142305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // message as well for accessing an unused variable.
143305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.UnsetValue();
144305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    LOG(ERROR) << "Could not find connection type (" << default_service_path_
145305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo               << ")";
146305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
147305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // If the property doesn't contain a string value, the empty string will
148305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // become kUnknown.
149305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.SetValue(
150305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        ParseConnectionTethering(prop_tethering->second.TryGet<string>()));
151305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
152beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
153305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection type.
154305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_type = properties.find(shill::kTypeProperty);
155305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_type == properties.end()) {
156305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_type_.UnsetValue();
157305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    LOG(ERROR) << "Could not find connection tethering mode ("
158305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo               << default_service_path_ << ")";
159305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
160305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    string type_str = prop_type->second.TryGet<string>();
161305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    if (type_str == shill::kTypeVPN) {
162305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      const auto& prop_physical =
163305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo          properties.find(shill::kPhysicalTechnologyProperty);
164305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      if (prop_physical == properties.end()) {
165305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
166305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                   << " connection (service: " << default_service_path
167305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                   << "). Using default kUnknown value.";
168305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        var_conn_type_.SetValue(ConnectionType::kUnknown);
169305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      } else {
170305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        var_conn_type_.SetValue(
171305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo            ParseConnectionType(prop_physical->second.TryGet<string>()));
172305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      }
173305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    } else {
174305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      var_conn_type_.SetValue(ParseConnectionType(type_str));
175305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    }
176305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
177beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
178305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  return true;
179beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold}
180beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
18163784a578dd26880454d70797519358a2326291bAlex Deymo}  // namespace chromeos_update_manager
182