1 //
2 // Copyright (C) 2015 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 #include <time.h>
17
18 #include <base/message_loop/message_loop.h>
19
20 #include "proxy_dbus_client.h"
21
22 const char ProxyDbusClient::kCommonLogScopes[] =
23 "connection+dbus+device+link+manager+portal+service";
24 const int ProxyDbusClient::kLogLevel = -4;
25 const char ProxyDbusClient::kDbusErrorObjectUnknown[] =
26 "org.freedesktop.DBus.Error.UnknownObject";
27
28 namespace {
GetPropertyValueFromProxy(Proxy * proxy,const std::string & property_name,brillo::Any * property_value)29 template<typename Proxy> bool GetPropertyValueFromProxy(
30 Proxy* proxy,
31 const std::string& property_name,
32 brillo::Any* property_value) {
33 CHECK(property_value);
34 brillo::VariantDictionary proxy_properties;
35 brillo::ErrorPtr error;
36 CHECK(proxy->GetProperties(&proxy_properties, &error));
37 if (proxy_properties.find(property_name) == proxy_properties.end()) {
38 return false;
39 }
40 *property_value = proxy_properties[property_name];
41 return true;
42 }
43
IsProxyPropertyValueIn(Proxy * proxy,const std::string & property_name,const std::vector<brillo::Any> & expected_values,base::Time wait_start_time,bool * is_success,brillo::Any * final_value,long * elapsed_time_milliseconds)44 template<typename Proxy> void IsProxyPropertyValueIn(
45 Proxy* proxy,
46 const std::string& property_name,
47 const std::vector<brillo::Any>& expected_values,
48 base::Time wait_start_time,
49 bool* is_success,
50 brillo::Any* final_value,
51 long* elapsed_time_milliseconds) {
52 brillo::Any property_value;
53 *is_success = false;
54 if ((GetPropertyValueFromProxy<Proxy>(proxy, property_name, &property_value)) &&
55 (std::find(expected_values.begin(), expected_values.end(),
56 property_value) != expected_values.end())) {
57 *is_success = true;
58 }
59 if (final_value) {
60 *final_value = property_value;
61 }
62 if (elapsed_time_milliseconds) {
63 *elapsed_time_milliseconds =
64 (base::Time::Now() - wait_start_time).InMilliseconds();
65 }
66 }
67
68 // This is invoked when the dbus detects a change in one of
69 // the properties of the proxy. We need to check if the property
70 // we're interested in has reached one of the expected values.
PropertyChangedSignalCallback(const std::string & watched_property_name,const std::vector<brillo::Any> & expected_values,const std::string & changed_property_name,const brillo::Any & new_property_value)71 void PropertyChangedSignalCallback(
72 const std::string& watched_property_name,
73 const std::vector<brillo::Any>& expected_values,
74 const std::string& changed_property_name,
75 const brillo::Any& new_property_value) {
76 if ((watched_property_name == changed_property_name) &&
77 (std::find(expected_values.begin(), expected_values.end(),
78 new_property_value) != expected_values.end())) {
79 // Unblock the waiting function by stopping the message loop.
80 base::MessageLoop::current()->QuitNow();
81 }
82 }
83
84 // This is invoked to indicate whether dbus successfully connected our
85 // signal callback or not.
PropertyChangedOnConnectedCallback(const std::string &,const std::string &,const std::string &,bool success)86 void PropertyChangedOnConnectedCallback(
87 const std::string& /* watched_property_name */,
88 const std::string& /* interface */,
89 const std::string& /* signal_name */,
90 bool success) {
91 CHECK(success);
92 }
93
94 template<typename Proxy>
HelpRegisterPropertyChangedSignalHandler(Proxy * proxy,dbus::ObjectProxy::OnConnectedCallback on_connected_callback,const DbusPropertyChangeCallback & signal_callback)95 void HelpRegisterPropertyChangedSignalHandler(
96 Proxy* proxy,
97 dbus::ObjectProxy::OnConnectedCallback on_connected_callback,
98 const DbusPropertyChangeCallback& signal_callback) {
99 // Re-order |on_connected_callback| and |signal_callback|, to meet
100 // the requirements of RegisterPropertyChangedSignalHandler().
101 proxy->RegisterPropertyChangedSignalHandler(
102 signal_callback, on_connected_callback);
103 }
104
105 template<typename OutValueType, typename ConditionChangeCallbackType>
WaitForCondition(base::Callback<void (base::Time,bool *,OutValueType *,long *)> condition_termination_checker,base::Callback<ConditionChangeCallbackType> condition_change_callback,base::Callback<void (const base::Callback<ConditionChangeCallbackType> &)> condition_change_callback_registrar,long timeout_milliseconds,bool * is_success,OutValueType * out_value,long * elapsed_time_milliseconds)106 void WaitForCondition(
107 base::Callback<void(base::Time, bool*, OutValueType*, long*)>
108 condition_termination_checker,
109 base::Callback<ConditionChangeCallbackType> condition_change_callback,
110 base::Callback<void(const base::Callback<ConditionChangeCallbackType>&)>
111 condition_change_callback_registrar,
112 long timeout_milliseconds,
113 bool* is_success,
114 OutValueType* out_value,
115 long* elapsed_time_milliseconds) {
116 CHECK(is_success);
117 const base::Time wait_start_time(base::Time::Now());
118 const base::TimeDelta timeout(
119 base::TimeDelta::FromMilliseconds(timeout_milliseconds));
120 base::CancelableClosure wait_timeout_callback;
121 base::CancelableCallback<ConditionChangeCallbackType> change_callback;
122
123 condition_termination_checker.Run(
124 wait_start_time, is_success, out_value, elapsed_time_milliseconds);
125 if (*is_success) {
126 return;
127 }
128
129 wait_timeout_callback.Reset(base::MessageLoop::QuitWhenIdleClosure());
130 change_callback.Reset(condition_change_callback);
131
132 condition_change_callback_registrar.Run(change_callback.callback());
133
134 // Add timeout, in case we never hit the expected condition.
135 base::MessageLoop::current()->PostDelayedTask(
136 FROM_HERE,
137 wait_timeout_callback.callback(),
138 timeout);
139
140 // Wait for the condition to occur within |timeout_milliseconds|.
141 base::MessageLoop::current()->Run();
142
143 wait_timeout_callback.Cancel();
144 change_callback.Cancel();
145
146 // We could have reached here either because we timed out or
147 // because we reached the condition.
148 condition_termination_checker.Run(
149 wait_start_time, is_success, out_value, elapsed_time_milliseconds);
150 }
151 } // namespace
152
ProxyDbusClient(scoped_refptr<dbus::Bus> bus)153 ProxyDbusClient::ProxyDbusClient(scoped_refptr<dbus::Bus> bus)
154 : dbus_bus_(bus),
155 shill_manager_proxy_(dbus_bus_),
156 weak_ptr_factory_(this) {
157 }
158
SetLogging(Technology tech)159 void ProxyDbusClient::SetLogging(Technology tech) {
160 std::string log_scopes(kCommonLogScopes);
161 switch (tech) {
162 case TECHNOLOGY_CELLULAR:
163 log_scopes += "+cellular";
164 break;
165 case TECHNOLOGY_ETHERNET:
166 log_scopes += "+ethernet";
167 break;
168 case TECHNOLOGY_VPN:
169 log_scopes += "+vpn";
170 break;
171 case TECHNOLOGY_WIFI:
172 log_scopes += "+wifi";
173 break;
174 case TECHNOLOGY_WIMAX:
175 log_scopes += "+wimax";
176 break;
177 }
178 SetLoggingInternal(kLogLevel, log_scopes);
179 }
180
GetDeviceProxies()181 std::vector<std::unique_ptr<DeviceProxy>> ProxyDbusClient::GetDeviceProxies() {
182 return GetProxies<DeviceProxy>(shill::kDevicesProperty);
183 }
184
GetServiceProxies()185 std::vector<std::unique_ptr<ServiceProxy>> ProxyDbusClient::GetServiceProxies() {
186 return GetProxies<ServiceProxy>(shill::kServicesProperty);
187 }
188
GetProfileProxies()189 std::vector<std::unique_ptr<ProfileProxy>> ProxyDbusClient::GetProfileProxies() {
190 return GetProxies<ProfileProxy>(shill::kProfilesProperty);
191 }
192
GetMatchingDeviceProxy(const brillo::VariantDictionary & expected_properties)193 std::unique_ptr<DeviceProxy> ProxyDbusClient::GetMatchingDeviceProxy(
194 const brillo::VariantDictionary& expected_properties) {
195 return GetMatchingProxy<DeviceProxy>(shill::kDevicesProperty, expected_properties);
196 }
197
GetMatchingServiceProxy(const brillo::VariantDictionary & expected_properties)198 std::unique_ptr<ServiceProxy> ProxyDbusClient::GetMatchingServiceProxy(
199 const brillo::VariantDictionary& expected_properties) {
200 return GetMatchingProxy<ServiceProxy>(shill::kServicesProperty, expected_properties);
201 }
202
GetMatchingProfileProxy(const brillo::VariantDictionary & expected_properties)203 std::unique_ptr<ProfileProxy> ProxyDbusClient::GetMatchingProfileProxy(
204 const brillo::VariantDictionary& expected_properties) {
205 return GetMatchingProxy<ProfileProxy>(shill::kProfilesProperty, expected_properties);
206 }
207
GetPropertyValueFromDeviceProxy(DeviceProxy * proxy,const std::string & property_name,brillo::Any * property_value)208 bool ProxyDbusClient::GetPropertyValueFromDeviceProxy(
209 DeviceProxy* proxy,
210 const std::string& property_name,
211 brillo::Any* property_value) {
212 return GetPropertyValueFromProxy<DeviceProxy>(
213 proxy, property_name, property_value);
214 }
215
GetPropertyValueFromServiceProxy(ServiceProxy * proxy,const std::string & property_name,brillo::Any * property_value)216 bool ProxyDbusClient::GetPropertyValueFromServiceProxy(
217 ServiceProxy* proxy,
218 const std::string& property_name,
219 brillo::Any* property_value) {
220 return GetPropertyValueFromProxy<ServiceProxy>(
221 proxy, property_name, property_value);
222 }
223
GetPropertyValueFromProfileProxy(ProfileProxy * proxy,const std::string & property_name,brillo::Any * property_value)224 bool ProxyDbusClient::GetPropertyValueFromProfileProxy(
225 ProfileProxy* proxy,
226 const std::string& property_name,
227 brillo::Any* property_value) {
228 return GetPropertyValueFromProxy<ProfileProxy>(
229 proxy, property_name, property_value);
230 }
231
WaitForDeviceProxyPropertyValueIn(const dbus::ObjectPath & object_path,const std::string & property_name,const std::vector<brillo::Any> & expected_values,long timeout_milliseconds,brillo::Any * final_value,long * elapsed_time_milliseconds)232 bool ProxyDbusClient::WaitForDeviceProxyPropertyValueIn(
233 const dbus::ObjectPath& object_path,
234 const std::string& property_name,
235 const std::vector<brillo::Any>& expected_values,
236 long timeout_milliseconds,
237 brillo::Any* final_value,
238 long* elapsed_time_milliseconds) {
239 return WaitForProxyPropertyValueIn<DeviceProxy>(
240 object_path, property_name, expected_values, timeout_milliseconds,
241 final_value, elapsed_time_milliseconds);
242 }
243
WaitForServiceProxyPropertyValueIn(const dbus::ObjectPath & object_path,const std::string & property_name,const std::vector<brillo::Any> & expected_values,long timeout_milliseconds,brillo::Any * final_value,long * elapsed_time_milliseconds)244 bool ProxyDbusClient::WaitForServiceProxyPropertyValueIn(
245 const dbus::ObjectPath& object_path,
246 const std::string& property_name,
247 const std::vector<brillo::Any>& expected_values,
248 long timeout_milliseconds,
249 brillo::Any* final_value,
250 long* elapsed_time_milliseconds) {
251 return WaitForProxyPropertyValueIn<ServiceProxy>(
252 object_path, property_name, expected_values, timeout_milliseconds,
253 final_value, elapsed_time_milliseconds);
254 }
255
WaitForProfileProxyPropertyValueIn(const dbus::ObjectPath & object_path,const std::string & property_name,const std::vector<brillo::Any> & expected_values,long timeout_milliseconds,brillo::Any * final_value,long * elapsed_time_milliseconds)256 bool ProxyDbusClient::WaitForProfileProxyPropertyValueIn(
257 const dbus::ObjectPath& object_path,
258 const std::string& property_name,
259 const std::vector<brillo::Any>& expected_values,
260 long timeout_milliseconds,
261 brillo::Any* final_value,
262 long* elapsed_time_milliseconds) {
263 return WaitForProxyPropertyValueIn<ProfileProxy>(
264 object_path, property_name, expected_values, timeout_milliseconds,
265 final_value, elapsed_time_milliseconds);
266 }
267
GetServiceProxy(const brillo::VariantDictionary & expected_properties)268 std::unique_ptr<ServiceProxy> ProxyDbusClient::GetServiceProxy(
269 const brillo::VariantDictionary& expected_properties) {
270 dbus::ObjectPath service_path;
271 brillo::ErrorPtr error;
272 if (!shill_manager_proxy_.GetService(
273 expected_properties, &service_path, &error)) {
274 return nullptr;
275 }
276 return std::unique_ptr<ServiceProxy>(
277 new ServiceProxy(dbus_bus_, service_path));
278 }
279
GetActiveProfileProxy()280 std::unique_ptr<ProfileProxy> ProxyDbusClient::GetActiveProfileProxy() {
281 return GetProxyForObjectPath<ProfileProxy>(GetObjectPathForActiveProfile());
282 }
283
WaitForMatchingServiceProxy(const brillo::VariantDictionary & service_properties,const std::string & service_type,long timeout_milliseconds,int rescan_interval_milliseconds,long * elapsed_time_milliseconds)284 std::unique_ptr<ServiceProxy> ProxyDbusClient::WaitForMatchingServiceProxy(
285 const brillo::VariantDictionary& service_properties,
286 const std::string& service_type,
287 long timeout_milliseconds,
288 int rescan_interval_milliseconds,
289 long* elapsed_time_milliseconds) {
290 auto condition_termination_checker =
291 base::Bind(&ProxyDbusClient::IsMatchingServicePresent,
292 weak_ptr_factory_.GetWeakPtr(),
293 service_properties);
294 auto condition_change_callback =
295 base::Bind(&ProxyDbusClient::FindServiceOrRestartScan,
296 weak_ptr_factory_.GetWeakPtr(),
297 service_properties,
298 service_type);
299 auto condition_change_callback_registrar =
300 base::Bind(&ProxyDbusClient::InitiateScanForService,
301 weak_ptr_factory_.GetWeakPtr(),
302 base::TimeDelta::FromMilliseconds(rescan_interval_milliseconds),
303 service_type);
304
305 std::unique_ptr<ServiceProxy> service_proxy;
306 bool is_success;
307 WaitForCondition(
308 condition_termination_checker, condition_change_callback,
309 condition_change_callback_registrar,
310 timeout_milliseconds, &is_success, &service_proxy, elapsed_time_milliseconds);
311 return service_proxy;
312 }
313
ConfigureService(const brillo::VariantDictionary & config_params)314 bool ProxyDbusClient::ConfigureService(
315 const brillo::VariantDictionary& config_params) {
316 dbus::ObjectPath service_path;
317 brillo::ErrorPtr error;
318 return shill_manager_proxy_.ConfigureService(
319 config_params, &service_path, &error);
320 }
321
ConfigureServiceByGuid(const std::string & guid,const brillo::VariantDictionary & config_params)322 bool ProxyDbusClient::ConfigureServiceByGuid(
323 const std::string& guid,
324 const brillo::VariantDictionary& config_params) {
325 dbus::ObjectPath service_path;
326 brillo::ErrorPtr error;
327 brillo::VariantDictionary guid_config_params(config_params);
328 guid_config_params[shill::kGuidProperty] = guid;
329 return shill_manager_proxy_.ConfigureService(
330 guid_config_params, &service_path, &error);
331 }
332
ConnectService(const dbus::ObjectPath & object_path,long timeout_milliseconds)333 bool ProxyDbusClient::ConnectService(
334 const dbus::ObjectPath& object_path,
335 long timeout_milliseconds) {
336 auto proxy = GetProxyForObjectPath<ServiceProxy>(object_path);
337 brillo::ErrorPtr error;
338 if (!proxy->Connect(&error)) {
339 return false;
340 }
341 const std::vector<brillo::Any> expected_values = {
342 brillo::Any(std::string(shill::kStatePortal)),
343 brillo::Any(std::string(shill::kStateOnline)) };
344 return WaitForProxyPropertyValueIn<ServiceProxy>(
345 object_path, shill::kStateProperty, expected_values,
346 timeout_milliseconds, nullptr, nullptr);
347 }
348
DisconnectService(const dbus::ObjectPath & object_path,long timeout_milliseconds)349 bool ProxyDbusClient::DisconnectService(
350 const dbus::ObjectPath& object_path,
351 long timeout_milliseconds) {
352 auto proxy = GetProxyForObjectPath<ServiceProxy>(object_path);
353 brillo::ErrorPtr error;
354 if (!proxy->Disconnect(&error)) {
355 return false;
356 }
357 const std::vector<brillo::Any> expected_values = {
358 brillo::Any(std::string(shill::kStateIdle)) };
359 return WaitForProxyPropertyValueIn<ServiceProxy>(
360 object_path, shill::kStateProperty, expected_values,
361 timeout_milliseconds, nullptr, nullptr);
362 }
363
CreateProfile(const std::string & profile_name)364 bool ProxyDbusClient::CreateProfile(const std::string& profile_name) {
365 dbus::ObjectPath profile_path;
366 brillo::ErrorPtr error;
367 return shill_manager_proxy_.CreateProfile(
368 profile_name, &profile_path, &error);
369 }
370
RemoveProfile(const std::string & profile_name)371 bool ProxyDbusClient::RemoveProfile(const std::string& profile_name) {
372 brillo::ErrorPtr error;
373 return shill_manager_proxy_.RemoveProfile(profile_name, &error);
374 }
375
PushProfile(const std::string & profile_name)376 bool ProxyDbusClient::PushProfile(const std::string& profile_name) {
377 dbus::ObjectPath profile_path;
378 brillo::ErrorPtr error;
379 return shill_manager_proxy_.PushProfile(
380 profile_name, &profile_path, &error);
381 }
382
PopProfile(const std::string & profile_name)383 bool ProxyDbusClient::PopProfile(const std::string& profile_name) {
384 brillo::ErrorPtr error;
385 return shill_manager_proxy_.PopProfile(profile_name, &error);
386 }
387
PopAnyProfile()388 bool ProxyDbusClient::PopAnyProfile() {
389 brillo::ErrorPtr error;
390 return shill_manager_proxy_.PopAnyProfile(&error);
391 }
392
RequestServiceScan(const std::string & service_type)393 bool ProxyDbusClient::RequestServiceScan(const std::string& service_type) {
394 brillo::ErrorPtr error;
395 return shill_manager_proxy_.RequestScan(service_type, &error);
396 }
397
GetServiceOrder(std::string * order)398 bool ProxyDbusClient::GetServiceOrder(std::string* order) {
399 brillo::ErrorPtr error;
400 return shill_manager_proxy_.GetServiceOrder(order, &error);
401 }
402
SetServiceOrder(const std::string & order)403 bool ProxyDbusClient::SetServiceOrder(const std::string& order) {
404 brillo::ErrorPtr error;
405 return shill_manager_proxy_.SetServiceOrder(order, &error);
406 }
407
SetSchedScan(bool enable)408 bool ProxyDbusClient::SetSchedScan(bool enable) {
409 brillo::ErrorPtr error;
410 return shill_manager_proxy_.SetSchedScan(enable, &error);
411 }
412
GetPropertyValueFromManager(const std::string & property_name,brillo::Any * property_value)413 bool ProxyDbusClient::GetPropertyValueFromManager(
414 const std::string& property_name,
415 brillo::Any* property_value) {
416 return GetPropertyValueFromProxy(
417 &shill_manager_proxy_, property_name, property_value);
418 }
419
GetObjectPathForActiveProfile()420 dbus::ObjectPath ProxyDbusClient::GetObjectPathForActiveProfile() {
421 brillo::Any property_value;
422 if (!GetPropertyValueFromManager(
423 shill::kActiveProfileProperty, &property_value)) {
424 return dbus::ObjectPath();
425 }
426 return dbus::ObjectPath(property_value.Get<std::string>());
427 }
428
SetLoggingInternal(int level,const std::string & tags)429 bool ProxyDbusClient::SetLoggingInternal(int level, const std::string& tags) {
430 bool is_success = true;
431 brillo::ErrorPtr error;
432 is_success &= shill_manager_proxy_.SetDebugLevel(level, &error);
433 is_success &= shill_manager_proxy_.SetDebugTags(tags, &error);
434 return is_success;
435 }
436
437 template<typename Proxy>
GetProxyForObjectPath(const dbus::ObjectPath & object_path)438 std::unique_ptr<Proxy> ProxyDbusClient::GetProxyForObjectPath(
439 const dbus::ObjectPath& object_path) {
440 return std::unique_ptr<Proxy>(new Proxy(dbus_bus_, object_path));
441 }
442
443 // Templated functions to return the object path property_name based on
444 template<typename Proxy>
GetProxies(const std::string & object_paths_property_name)445 std::vector<std::unique_ptr<Proxy>> ProxyDbusClient::GetProxies(
446 const std::string& object_paths_property_name) {
447 brillo::Any object_paths;
448 if (!GetPropertyValueFromManager(object_paths_property_name, &object_paths)) {
449 return std::vector<std::unique_ptr<Proxy>>();
450 }
451 std::vector<std::unique_ptr<Proxy>> proxies;
452 for (const auto& object_path :
453 object_paths.Get<std::vector<dbus::ObjectPath>>()) {
454 proxies.emplace_back(GetProxyForObjectPath<Proxy>(object_path));
455 }
456 return proxies;
457 }
458
459 template<typename Proxy>
GetMatchingProxy(const std::string & object_paths_property_name,const brillo::VariantDictionary & expected_properties)460 std::unique_ptr<Proxy> ProxyDbusClient::GetMatchingProxy(
461 const std::string& object_paths_property_name,
462 const brillo::VariantDictionary& expected_properties) {
463 for (auto& proxy : GetProxies<Proxy>(object_paths_property_name)) {
464 brillo::VariantDictionary proxy_properties;
465 brillo::ErrorPtr error;
466 if (!proxy->GetProperties(&proxy_properties, &error)) {
467 // Ignore unknown object path errors since we might be using some proxies
468 // for objects which may have been destroyed since.
469 CHECK(error->GetCode() == kDbusErrorObjectUnknown);
470 continue;
471 }
472 bool all_expected_properties_matched = true;
473 for (const auto& expected_property : expected_properties) {
474 if (proxy_properties[expected_property.first] != expected_property.second) {
475 all_expected_properties_matched = false;
476 break;
477 }
478 }
479 if (all_expected_properties_matched) {
480 return std::move(proxy);
481 }
482 }
483 return nullptr;
484 }
485
486 template<typename Proxy>
WaitForProxyPropertyValueIn(const dbus::ObjectPath & object_path,const std::string & property_name,const std::vector<brillo::Any> & expected_values,long timeout_milliseconds,brillo::Any * final_value,long * elapsed_time_milliseconds)487 bool ProxyDbusClient::WaitForProxyPropertyValueIn(
488 const dbus::ObjectPath& object_path,
489 const std::string& property_name,
490 const std::vector<brillo::Any>& expected_values,
491 long timeout_milliseconds,
492 brillo::Any* final_value,
493 long* elapsed_time_milliseconds) {
494 // Creates a local proxy using |object_path| instead of accepting the proxy
495 // from the caller since we cannot deregister the signal property change
496 // callback associated.
497 auto proxy = GetProxyForObjectPath<Proxy>(object_path);
498 auto condition_termination_checker =
499 base::Bind(&IsProxyPropertyValueIn<Proxy>,
500 proxy.get(),
501 property_name,
502 expected_values);
503 auto condition_change_callback =
504 base::Bind(&PropertyChangedSignalCallback,
505 property_name,
506 expected_values);
507 auto condition_change_callback_registrar =
508 base::Bind(&HelpRegisterPropertyChangedSignalHandler<Proxy>,
509 base::Unretained(proxy.get()),
510 base::Bind(&PropertyChangedOnConnectedCallback,
511 property_name));
512 bool is_success;
513 WaitForCondition(
514 condition_termination_checker, condition_change_callback,
515 condition_change_callback_registrar,
516 timeout_milliseconds, &is_success, final_value, elapsed_time_milliseconds);
517 return is_success;
518 }
519
IsMatchingServicePresent(const brillo::VariantDictionary & service_properties,base::Time wait_start_time,bool * is_success,std::unique_ptr<ServiceProxy> * service_proxy_out,long * elapsed_time_milliseconds)520 void ProxyDbusClient::IsMatchingServicePresent(
521 const brillo::VariantDictionary& service_properties,
522 base::Time wait_start_time,
523 bool* is_success,
524 std::unique_ptr<ServiceProxy>* service_proxy_out,
525 long* elapsed_time_milliseconds) {
526 auto service_proxy = GetMatchingServiceProxy(service_properties);
527 *is_success = false;
528 if (service_proxy) {
529 *is_success = true;
530 }
531 if (service_proxy_out) {
532 *service_proxy_out = std::move(service_proxy);
533 }
534 if (elapsed_time_milliseconds) {
535 *elapsed_time_milliseconds =
536 (base::Time::Now() - wait_start_time).InMilliseconds();
537 }
538 }
539
FindServiceOrRestartScan(const brillo::VariantDictionary & service_properties,const std::string & service_type)540 void ProxyDbusClient::FindServiceOrRestartScan(
541 const brillo::VariantDictionary& service_properties,
542 const std::string& service_type) {
543 if (GetMatchingServiceProxy(service_properties)) {
544 base::MessageLoop::current()->QuitNow();
545 } else {
546 RestartScanForService(service_type);
547 }
548 }
549
InitiateScanForService(base::TimeDelta rescan_interval,const std::string & service_type,const base::Closure & timer_callback)550 void ProxyDbusClient::InitiateScanForService(
551 base::TimeDelta rescan_interval,
552 const std::string& service_type,
553 const base::Closure& timer_callback) {
554 // Create a new timer instance for repeatedly calling the provided
555 // |timer_callback|. |WaitForCondition| will cancel |timer_callback|'s
556 // enclosing CancelableCallback when it exits and hence we need to
557 // use the same reference when we repeatedly schedule |timer_callback|.
558 wait_for_service_timer_.reset(
559 new base::Timer(FROM_HERE, rescan_interval, timer_callback, false));
560 RestartScanForService(service_type);
561 }
562
RestartScanForService(const std::string & service_type)563 void ProxyDbusClient::RestartScanForService(
564 const std::string& service_type) {
565 RequestServiceScan(service_type);
566 wait_for_service_timer_->Reset();
567 }
568