blob: 4d067fd44ec1cd5e257aee7f405c1583fcf758bb [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>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070023#include <brillo/type_name_undecorate.h>
Alex Deymod6deb1d2015-08-28 15:54:37 -070024#include <shill/dbus-constants.h>
25#include <shill/dbus-proxies.h>
Alex Deymob8803bb2015-08-19 23:14:49 -070026
Amin Hassani0468a762020-11-17 23:53:48 -080027using chromeos_update_engine::SystemState;
Sen Jiang255e22b2016-05-20 16:15:29 -070028using chromeos_update_engine::connection_utils::ParseConnectionType;
Alex Deymo30534502015-07-20 15:06:33 -070029using org::chromium::flimflam::ManagerProxyInterface;
30using org::chromium::flimflam::ServiceProxyInterface;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080031using std::string;
32
Alex Deymo63784a52014-05-28 10:46:14 -070033namespace chromeos_update_manager {
Gilad Arnold55f39b72014-01-28 12:51:45 -080034
Alex Deymo42c30c32014-04-24 18:41:18 -070035bool RealShillProvider::Init() {
Alex Deymo30534502015-07-20 15:06:33 -070036 ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
37 if (!manager_proxy)
Gilad Arnold5ef9c482014-03-03 13:51:02 -080038 return false;
Gilad Arnold55f39b72014-01-28 12:51:45 -080039
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070040 // Subscribe to the manager's PropertyChanged signal.
Alex Deymo30534502015-07-20 15:06:33 -070041 manager_proxy->RegisterPropertyChangedSignalHandler(
42 base::Bind(&RealShillProvider::OnManagerPropertyChanged,
43 base::Unretained(this)),
44 base::Bind(&RealShillProvider::OnSignalConnected,
45 base::Unretained(this)));
Gilad Arnold5ef9c482014-03-03 13:51:02 -080046
Gilad Arnoldef120fa2014-04-09 12:52:10 -070047 // Attempt to read initial connection status. Even if this fails because shill
48 // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
49 // signal as soon as it comes up, so this is not a critical step.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070050 brillo::VariantDictionary properties;
51 brillo::ErrorPtr error;
Alex Deymo30534502015-07-20 15:06:33 -070052 if (!manager_proxy->GetProperties(&properties, &error))
53 return true;
54
55 const auto& prop_default_service =
56 properties.find(shill::kDefaultServiceProperty);
57 if (prop_default_service != properties.end()) {
58 OnManagerPropertyChanged(prop_default_service->first,
59 prop_default_service->second);
Gilad Arnold5ef9c482014-03-03 13:51:02 -080060 }
61
Gilad Arnoldef120fa2014-04-09 12:52:10 -070062 return true;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080063}
64
Alex Deymo30534502015-07-20 15:06:33 -070065void RealShillProvider::OnManagerPropertyChanged(const string& name,
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070066 const brillo::Any& value) {
Alex Deymo758dd532015-09-09 15:21:22 -070067 if (name == shill::kDefaultServiceProperty) {
68 dbus::ObjectPath service_path = value.TryGet<dbus::ObjectPath>();
69 if (!service_path.IsValid()) {
70 LOG(WARNING) << "Got an invalid DefaultService path. The property value "
71 "contains a "
Alex Vakulenkodf6d9f42015-10-23 11:24:46 -070072 << value.GetUndecoratedTypeName()
Alex Deymo758dd532015-09-09 15:21:22 -070073 << ", read as the object path: '" << service_path.value()
74 << "'";
75 }
76 ProcessDefaultService(service_path);
77 }
Gilad Arnold5ef9c482014-03-03 13:51:02 -080078}
79
Alex Deymo30534502015-07-20 15:06:33 -070080void RealShillProvider::OnSignalConnected(const string& interface_name,
81 const string& signal_name,
82 bool successful) {
83 if (!successful) {
84 LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
85 << signal_name;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080086 }
Gilad Arnold5ef9c482014-03-03 13:51:02 -080087}
88
Alex Deymo30534502015-07-20 15:06:33 -070089bool RealShillProvider::ProcessDefaultService(
Alex Deymo758dd532015-09-09 15:21:22 -070090 const dbus::ObjectPath& default_service_path) {
Alex Deymo30534502015-07-20 15:06:33 -070091 // We assume that if the service path didn't change, then the connection
92 // type and the tethering status of it also didn't change.
93 if (default_service_path_ == default_service_path)
Gilad Arnoldef120fa2014-04-09 12:52:10 -070094 return true;
95
Gilad Arnoldd3df25f2014-04-22 08:39:48 -070096 // Update the connection status.
Alex Deymo30534502015-07-20 15:06:33 -070097 default_service_path_ = default_service_path;
Amin Hassani4b717432019-01-14 16:24:20 -080098 bool is_connected =
99 (default_service_path_.IsValid() && default_service_path_.value() != "/");
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700100 var_is_connected_.SetValue(is_connected);
Amin Hassani0468a762020-11-17 23:53:48 -0800101 var_conn_last_changed_.SetValue(
102 SystemState::Get()->clock()->GetWallclockTime());
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700103
Alex Deymo30534502015-07-20 15:06:33 -0700104 if (!is_connected) {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700105 var_conn_type_.UnsetValue();
106 var_conn_tethering_.UnsetValue();
Alex Deymo30534502015-07-20 15:06:33 -0700107 return true;
108 }
109
110 // We create and dispose the ServiceProxyInterface on every request.
111 std::unique_ptr<ServiceProxyInterface> service =
112 shill_proxy_->GetServiceForPath(default_service_path_);
113
114 // Get the connection properties synchronously.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700115 brillo::VariantDictionary properties;
116 brillo::ErrorPtr error;
Alex Deymo30534502015-07-20 15:06:33 -0700117 if (!service->GetProperties(&properties, &error)) {
118 var_conn_type_.UnsetValue();
119 var_conn_tethering_.UnsetValue();
120 return false;
121 }
122
123 // Get the connection tethering mode.
124 const auto& prop_tethering = properties.find(shill::kTetheringProperty);
125 if (prop_tethering == properties.end()) {
126 // Remove the value if not present on the service. This most likely means an
127 // error in shill and the policy will handle it, but we will print a log
128 // message as well for accessing an unused variable.
129 var_conn_tethering_.UnsetValue();
Alex Deymo758dd532015-09-09 15:21:22 -0700130 LOG(ERROR) << "Could not find connection type (service: "
131 << default_service_path_.value() << ")";
Alex Deymo30534502015-07-20 15:06:33 -0700132 } else {
133 // If the property doesn't contain a string value, the empty string will
134 // become kUnknown.
135 var_conn_tethering_.SetValue(
Sen Jiang255e22b2016-05-20 16:15:29 -0700136 chromeos_update_engine::connection_utils::ParseConnectionTethering(
137 prop_tethering->second.TryGet<string>()));
Alex Deymo30534502015-07-20 15:06:33 -0700138 }
139
140 // Get the connection type.
141 const auto& prop_type = properties.find(shill::kTypeProperty);
142 if (prop_type == properties.end()) {
143 var_conn_type_.UnsetValue();
Alex Deymo758dd532015-09-09 15:21:22 -0700144 LOG(ERROR) << "Could not find connection tethering mode (service: "
145 << default_service_path_.value() << ")";
Alex Deymo30534502015-07-20 15:06:33 -0700146 } else {
147 string type_str = prop_type->second.TryGet<string>();
148 if (type_str == shill::kTypeVPN) {
149 const auto& prop_physical =
150 properties.find(shill::kPhysicalTechnologyProperty);
151 if (prop_physical == properties.end()) {
152 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
Alex Deymo758dd532015-09-09 15:21:22 -0700153 << " connection (service: " << default_service_path_.value()
Alex Deymo30534502015-07-20 15:06:33 -0700154 << "). Using default kUnknown value.";
Sen Jiang255e22b2016-05-20 16:15:29 -0700155 var_conn_type_.SetValue(
156 chromeos_update_engine::ConnectionType::kUnknown);
Alex Deymo30534502015-07-20 15:06:33 -0700157 } else {
158 var_conn_type_.SetValue(
159 ParseConnectionType(prop_physical->second.TryGet<string>()));
160 }
161 } else {
162 var_conn_type_.SetValue(ParseConnectionType(type_str));
163 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700164 }
Gilad Arnolddf3dd242014-04-09 07:15:51 -0700165
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700166 return true;
167}
168
Alex Deymo63784a52014-05-28 10:46:14 -0700169} // namespace chromeos_update_manager