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>
233f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/type_name_undecorate.h>
24d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-constants.h>
25d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-proxies.h>
26b8803bbfe96abce0ae792a93bc975d478d98d16aAlex Deymo
27255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiangusing chromeos_update_engine::connection_utils::ParseConnectionType;
28305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ManagerProxyInterface;
29305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ServiceProxyInterface;
305ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnoldusing std::string;
315ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
3263784a578dd26880454d70797519358a2326291bAlex Deymonamespace chromeos_update_manager {
3355f39b7043fae6b7c27188d0cd797946098b42efGilad Arnold
3442c30c376cb7b0b459ff0cbf3ac23fe87ea64f4dAlex Deymobool RealShillProvider::Init() {
35305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
36305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy)
375ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold    return false;
385ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
39beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold  // Subscribe to the manager's PropertyChanged signal.
40305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  manager_proxy->RegisterPropertyChangedSignalHandler(
41305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      base::Bind(&RealShillProvider::OnManagerPropertyChanged,
42305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                 base::Unretained(this)),
43305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      base::Bind(&RealShillProvider::OnSignalConnected,
44305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                 base::Unretained(this)));
455ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
46ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // Attempt to read initial connection status. Even if this fails because shill
47ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
48ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  // signal as soon as it comes up, so this is not a critical step.
493f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
503f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
51305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy->GetProperties(&properties, &error))
52305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return true;
53305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
54305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_default_service =
55305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      properties.find(shill::kDefaultServiceProperty);
56305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_default_service != properties.end()) {
57305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    OnManagerPropertyChanged(prop_default_service->first,
58305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                             prop_default_service->second);
595ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold  }
605ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
61ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  return true;
625ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
635ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
64305345001d85ca2282112c2a30fe75c7a4773491Alex Deymovoid RealShillProvider::OnManagerPropertyChanged(const string& name,
653f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                                                 const brillo::Any& value) {
66758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  if (name == shill::kDefaultServiceProperty) {
67758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    dbus::ObjectPath service_path = value.TryGet<dbus::ObjectPath>();
68758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    if (!service_path.IsValid()) {
69758dd53cf503adbcb049909f25f54603d411be09Alex Deymo      LOG(WARNING) << "Got an invalid DefaultService path. The property value "
70758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                      "contains a "
71df6d9f499db5e3c3dc68926586704d6a5f908496Alex Vakulenko                   << value.GetUndecoratedTypeName()
72758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                   << ", read as the object path: '" << service_path.value()
73758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                   << "'";
74758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    }
75758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    ProcessDefaultService(service_path);
76758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  }
775ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
785ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
79305345001d85ca2282112c2a30fe75c7a4773491Alex Deymovoid RealShillProvider::OnSignalConnected(const string& interface_name,
80305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                          const string& signal_name,
81305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                          bool successful) {
82305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!successful) {
83305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
84305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo               << signal_name;
855ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold  }
865ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold}
875ef9c48aa07b14d6e0a2171fee4f295f6b3d2895Gilad Arnold
88305345001d85ca2282112c2a30fe75c7a4773491Alex Deymobool RealShillProvider::ProcessDefaultService(
89758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    const dbus::ObjectPath& default_service_path) {
90305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We assume that if the service path didn't change, then the connection
91305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // type and the tethering status of it also didn't change.
92305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (default_service_path_ == default_service_path)
93ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold    return true;
94ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
95d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  // Update the connection status.
96305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  default_service_path_ = default_service_path;
97758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  bool is_connected = (default_service_path_.IsValid() &&
98758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                       default_service_path_.value() != "/");
99d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  var_is_connected_.SetValue(is_connected);
100d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold  var_conn_last_changed_.SetValue(clock_->GetWallclockTime());
101ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
102305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!is_connected) {
103305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_type_.UnsetValue();
104305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.UnsetValue();
105305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return true;
106305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
107ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
108305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We create and dispose the ServiceProxyInterface on every request.
109305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  std::unique_ptr<ServiceProxyInterface> service =
110305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      shill_proxy_->GetServiceForPath(default_service_path_);
111ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold
112305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection properties synchronously.
1133f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
1143f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
115305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!service->GetProperties(&properties, &error)) {
116d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold    var_conn_type_.UnsetValue();
117d3df25fb62011b3f76d33545467c71de3aca771dGilad Arnold    var_conn_tethering_.UnsetValue();
118305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
119ef120fac0ff6364aaa8c6d05339065f118be25acGilad Arnold  }
120df3dd2438aef108ac66dc42a4eabae8c79ee88a3Gilad Arnold
121305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection tethering mode.
122305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
123305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_tethering == properties.end()) {
124305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Remove the value if not present on the service. This most likely means an
125305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // error in shill and the policy will handle it, but we will print a log
126305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // message as well for accessing an unused variable.
127305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.UnsetValue();
128758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    LOG(ERROR) << "Could not find connection type (service: "
129758dd53cf503adbcb049909f25f54603d411be09Alex Deymo               << default_service_path_.value() << ")";
130305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
131305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // If the property doesn't contain a string value, the empty string will
132305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // become kUnknown.
133305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_tethering_.SetValue(
134255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang        chromeos_update_engine::connection_utils::ParseConnectionTethering(
135255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang            prop_tethering->second.TryGet<string>()));
136305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
137beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
138305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Get the connection type.
139305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_type = properties.find(shill::kTypeProperty);
140305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_type == properties.end()) {
141305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    var_conn_type_.UnsetValue();
142758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    LOG(ERROR) << "Could not find connection tethering mode (service: "
143758dd53cf503adbcb049909f25f54603d411be09Alex Deymo               << default_service_path_.value() << ")";
144305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
145305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    string type_str = prop_type->second.TryGet<string>();
146305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    if (type_str == shill::kTypeVPN) {
147305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      const auto& prop_physical =
148305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo          properties.find(shill::kPhysicalTechnologyProperty);
149305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      if (prop_physical == properties.end()) {
150305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
151758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                   << " connection (service: " << default_service_path_.value()
152305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                   << "). Using default kUnknown value.";
153255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang        var_conn_type_.SetValue(
154255e22b82af3a52218eaea66acc734ec25cfeab6Sen Jiang            chromeos_update_engine::ConnectionType::kUnknown);
155305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      } else {
156305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        var_conn_type_.SetValue(
157305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo            ParseConnectionType(prop_physical->second.TryGet<string>()));
158305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      }
159305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    } else {
160305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      var_conn_type_.SetValue(ParseConnectionType(type_str));
161305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    }
162305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
163beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
164305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  return true;
165beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold}
166beb39e9e5fcfae13f2c97b4ee7214484de2d3728Gilad Arnold
16763784a578dd26880454d70797519358a2326291bAlex Deymo}  // namespace chromeos_update_manager
168