blob: 065eac3c4af2bcd37de4ae0987eee0664401c087 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 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//
Gilad Arnold55f39b72014-01-28 12:51:45 -080016
Alex Deymo63784a52014-05-28 10:46:14 -070017#include "update_engine/update_manager/real_shill_provider.h"
Gilad Arnold55f39b72014-01-28 12:51:45 -080018
Gilad Arnold5ef9c482014-03-03 13:51:02 -080019#include <string>
20
21#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070022#include <base/strings/stringprintf.h>
Gilad Arnold5ef9c482014-03-03 13:51:02 -080023#include <chromeos/dbus/service_constants.h>
24
Alex Deymob8803bb2015-08-19 23:14:49 -070025#include "shill/dbus-proxies.h"
26
Alex Deymo30534502015-07-20 15:06:33 -070027using org::chromium::flimflam::ManagerProxyInterface;
28using org::chromium::flimflam::ServiceProxyInterface;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080029using std::string;
30
Alex Deymo63784a52014-05-28 10:46:14 -070031namespace chromeos_update_manager {
Gilad Arnold55f39b72014-01-28 12:51:45 -080032
Alex Deymo30534502015-07-20 15:06:33 -070033ConnectionType RealShillProvider::ParseConnectionType(const string& type_str) {
34 if (type_str == shill::kTypeEthernet) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070035 return ConnectionType::kEthernet;
Alex Deymo30534502015-07-20 15:06:33 -070036 } else if (type_str == shill::kTypeWifi) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070037 return ConnectionType::kWifi;
Alex Deymo30534502015-07-20 15:06:33 -070038 } else if (type_str == shill::kTypeWimax) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070039 return ConnectionType::kWimax;
Alex Deymo30534502015-07-20 15:06:33 -070040 } else if (type_str == shill::kTypeBluetooth) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070041 return ConnectionType::kBluetooth;
Alex Deymo30534502015-07-20 15:06:33 -070042 } else if (type_str == shill::kTypeCellular) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070043 return ConnectionType::kCellular;
Alex Deymo30534502015-07-20 15:06:33 -070044 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -070045 return ConnectionType::kUnknown;
46}
47
48ConnectionTethering RealShillProvider::ParseConnectionTethering(
Alex Deymo30534502015-07-20 15:06:33 -070049 const string& tethering_str) {
50 if (tethering_str == shill::kTetheringNotDetectedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070051 return ConnectionTethering::kNotDetected;
Alex Deymo30534502015-07-20 15:06:33 -070052 } else if (tethering_str == shill::kTetheringSuspectedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070053 return ConnectionTethering::kSuspected;
Alex Deymo30534502015-07-20 15:06:33 -070054 } else if (tethering_str == shill::kTetheringConfirmedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070055 return ConnectionTethering::kConfirmed;
Alex Deymo30534502015-07-20 15:06:33 -070056 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -070057 return ConnectionTethering::kUnknown;
58}
59
Alex Deymo42c30c32014-04-24 18:41:18 -070060bool RealShillProvider::Init() {
Alex Deymo30534502015-07-20 15:06:33 -070061 ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
62 if (!manager_proxy)
Gilad Arnold5ef9c482014-03-03 13:51:02 -080063 return false;
Gilad Arnold55f39b72014-01-28 12:51:45 -080064
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070065 // Subscribe to the manager's PropertyChanged signal.
Alex Deymo30534502015-07-20 15:06:33 -070066 manager_proxy->RegisterPropertyChangedSignalHandler(
67 base::Bind(&RealShillProvider::OnManagerPropertyChanged,
68 base::Unretained(this)),
69 base::Bind(&RealShillProvider::OnSignalConnected,
70 base::Unretained(this)));
Gilad Arnold5ef9c482014-03-03 13:51:02 -080071
Gilad Arnoldef120fa2014-04-09 12:52:10 -070072 // Attempt to read initial connection status. Even if this fails because shill
73 // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
74 // signal as soon as it comes up, so this is not a critical step.
Alex Deymo30534502015-07-20 15:06:33 -070075 chromeos::VariantDictionary properties;
76 chromeos::ErrorPtr error;
77 if (!manager_proxy->GetProperties(&properties, &error))
78 return true;
79
80 const auto& prop_default_service =
81 properties.find(shill::kDefaultServiceProperty);
82 if (prop_default_service != properties.end()) {
83 OnManagerPropertyChanged(prop_default_service->first,
84 prop_default_service->second);
Gilad Arnold5ef9c482014-03-03 13:51:02 -080085 }
86
Gilad Arnoldef120fa2014-04-09 12:52:10 -070087 return true;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080088}
89
Alex Deymo30534502015-07-20 15:06:33 -070090void RealShillProvider::OnManagerPropertyChanged(const string& name,
91 const chromeos::Any& value) {
92 if (name == shill::kDefaultServiceProperty)
93 ProcessDefaultService(value.TryGet<dbus::ObjectPath>().value());
Gilad Arnold5ef9c482014-03-03 13:51:02 -080094}
95
Alex Deymo30534502015-07-20 15:06:33 -070096void RealShillProvider::OnSignalConnected(const string& interface_name,
97 const string& signal_name,
98 bool successful) {
99 if (!successful) {
100 LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
101 << signal_name;
Gilad Arnold5ef9c482014-03-03 13:51:02 -0800102 }
Gilad Arnold5ef9c482014-03-03 13:51:02 -0800103}
104
Alex Deymo30534502015-07-20 15:06:33 -0700105bool RealShillProvider::ProcessDefaultService(
106 const string& default_service_path) {
107 // We assume that if the service path didn't change, then the connection
108 // type and the tethering status of it also didn't change.
109 if (default_service_path_ == default_service_path)
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700110 return true;
111
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700112 // Update the connection status.
Alex Deymo30534502015-07-20 15:06:33 -0700113 default_service_path_ = default_service_path;
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700114 bool is_connected = (default_service_path_ != "/");
115 var_is_connected_.SetValue(is_connected);
116 var_conn_last_changed_.SetValue(clock_->GetWallclockTime());
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700117
Alex Deymo30534502015-07-20 15:06:33 -0700118 if (!is_connected) {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700119 var_conn_type_.UnsetValue();
120 var_conn_tethering_.UnsetValue();
Alex Deymo30534502015-07-20 15:06:33 -0700121 return true;
122 }
123
124 // We create and dispose the ServiceProxyInterface on every request.
125 std::unique_ptr<ServiceProxyInterface> service =
126 shill_proxy_->GetServiceForPath(default_service_path_);
127
128 // Get the connection properties synchronously.
129 chromeos::VariantDictionary properties;
130 chromeos::ErrorPtr error;
131 if (!service->GetProperties(&properties, &error)) {
132 var_conn_type_.UnsetValue();
133 var_conn_tethering_.UnsetValue();
134 return false;
135 }
136
137 // Get the connection tethering mode.
138 const auto& prop_tethering = properties.find(shill::kTetheringProperty);
139 if (prop_tethering == properties.end()) {
140 // Remove the value if not present on the service. This most likely means an
141 // error in shill and the policy will handle it, but we will print a log
142 // message as well for accessing an unused variable.
143 var_conn_tethering_.UnsetValue();
144 LOG(ERROR) << "Could not find connection type (" << default_service_path_
145 << ")";
146 } else {
147 // If the property doesn't contain a string value, the empty string will
148 // become kUnknown.
149 var_conn_tethering_.SetValue(
150 ParseConnectionTethering(prop_tethering->second.TryGet<string>()));
151 }
152
153 // Get the connection type.
154 const auto& prop_type = properties.find(shill::kTypeProperty);
155 if (prop_type == properties.end()) {
156 var_conn_type_.UnsetValue();
157 LOG(ERROR) << "Could not find connection tethering mode ("
158 << default_service_path_ << ")";
159 } else {
160 string type_str = prop_type->second.TryGet<string>();
161 if (type_str == shill::kTypeVPN) {
162 const auto& prop_physical =
163 properties.find(shill::kPhysicalTechnologyProperty);
164 if (prop_physical == properties.end()) {
165 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
166 << " connection (service: " << default_service_path
167 << "). Using default kUnknown value.";
168 var_conn_type_.SetValue(ConnectionType::kUnknown);
169 } else {
170 var_conn_type_.SetValue(
171 ParseConnectionType(prop_physical->second.TryGet<string>()));
172 }
173 } else {
174 var_conn_type_.SetValue(ParseConnectionType(type_str));
175 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700176 }
Gilad Arnolddf3dd242014-04-09 07:15:51 -0700177
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700178 return true;
179}
180
Alex Deymo63784a52014-05-28 10:46:14 -0700181} // namespace chromeos_update_manager