Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: device/battery/battery_status_manager_linux.cc

Issue 2795713003: Do not call GetDisplayDevice for older UPower versions. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/battery/battery_status_manager_linux.h" 5 #include "device/battery/battery_status_manager_linux.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <limits> 10 #include <limits>
11 #include <memory> 11 #include <memory>
12 #include <string> 12 #include <string>
13 #include <utility> 13 #include <utility>
14 #include <vector> 14 #include <vector>
15 15
16 #include "base/auto_reset.h"
16 #include "base/macros.h" 17 #include "base/macros.h"
17 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
18 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
20 #include "base/values.h" 21 #include "base/values.h"
21 #include "base/version.h" 22 #include "base/version.h"
22 #include "dbus/bus.h" 23 #include "dbus/bus.h"
23 #include "dbus/message.h" 24 #include "dbus/message.h"
24 #include "dbus/object_path.h" 25 #include "dbus/object_path.h"
25 #include "dbus/object_proxy.h" 26 #include "dbus/object_proxy.h"
(...skipping 28 matching lines...) Expand all
54 UPowerProperties::~UPowerProperties() {} 55 UPowerProperties::~UPowerProperties() {}
55 56
56 base::Version UPowerProperties::daemon_version() { 57 base::Version UPowerProperties::daemon_version() {
57 return (daemon_version_.is_valid() || daemon_version_.GetAndBlock()) 58 return (daemon_version_.is_valid() || daemon_version_.GetAndBlock())
58 ? base::Version(daemon_version_.value()) 59 ? base::Version(daemon_version_.value())
59 : base::Version(); 60 : base::Version();
60 } 61 }
61 62
62 class UPowerObject { 63 class UPowerObject {
63 public: 64 public:
64 typedef dbus::PropertySet::PropertyChangedCallback PropertyChangedCallback; 65 using PropertyChangedCallback = dbus::PropertySet::PropertyChangedCallback;
65 66
66 UPowerObject(dbus::Bus* dbus, 67 UPowerObject(dbus::Bus* dbus,
67 const PropertyChangedCallback property_changed_callback); 68 const PropertyChangedCallback property_changed_callback);
68 ~UPowerObject(); 69 ~UPowerObject();
69 70
70 std::vector<dbus::ObjectPath> EnumerateDevices(); 71 std::vector<dbus::ObjectPath> EnumerateDevices();
71 dbus::ObjectPath GetDisplayDevice(); 72 dbus::ObjectPath GetDisplayDevice();
72 73
73 dbus::ObjectProxy* proxy() { return proxy_; } 74 dbus::ObjectProxy* proxy() { return proxy_; }
74 UPowerProperties* properties() { return properties_.get(); } 75 UPowerProperties* properties() { return properties_.get(); }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 : default_value; 219 : default_value;
219 } 220 }
220 221
221 uint32_t BatteryProperties::type(uint32_t default_value) { 222 uint32_t BatteryProperties::type(uint32_t default_value) {
222 return (type_.is_valid() || type_.GetAndBlock()) ? type_.value() 223 return (type_.is_valid() || type_.GetAndBlock()) ? type_.value()
223 : default_value; 224 : default_value;
224 } 225 }
225 226
226 class BatteryObject { 227 class BatteryObject {
227 public: 228 public:
228 typedef dbus::PropertySet::PropertyChangedCallback PropertyChangedCallback; 229 using PropertyChangedCallback = dbus::PropertySet::PropertyChangedCallback;
229 230
230 BatteryObject(dbus::Bus* dbus, 231 BatteryObject(dbus::Bus* dbus,
231 const dbus::ObjectPath& device_path, 232 const dbus::ObjectPath& device_path,
232 const PropertyChangedCallback& property_changed_callback); 233 const PropertyChangedCallback& property_changed_callback);
233 ~BatteryObject(); 234 ~BatteryObject();
234 235
235 bool IsValid(); 236 bool IsValid();
236 237
237 dbus::ObjectProxy* proxy() { return proxy_; } 238 dbus::ObjectProxy* proxy() { return proxy_; }
238 BatteryProperties* properties() { return properties_.get(); } 239 BatteryProperties* properties() { return properties_.get(); }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 328
328 void StartListening() { 329 void StartListening() {
329 DCHECK(OnWatcherThread()); 330 DCHECK(OnWatcherThread());
330 331
331 if (upower_) 332 if (upower_)
332 return; 333 return;
333 334
334 if (!system_bus_) 335 if (!system_bus_)
335 InitDBus(); 336 InitDBus();
336 337
337 upower_.reset(new UPowerObject(system_bus_.get(), 338 upower_ = base::MakeUnique<UPowerObject>(
338 UPowerObject::PropertyChangedCallback())); 339 system_bus_.get(), UPowerObject::PropertyChangedCallback());
339 upower_->proxy()->ConnectToSignal( 340 upower_->proxy()->ConnectToSignal(
340 kUPowerServiceName, kUPowerSignalDeviceAdded, 341 kUPowerServiceName, kUPowerSignalDeviceAdded,
341 base::Bind(&BatteryStatusNotificationThread::DeviceAdded, 342 base::Bind(&BatteryStatusNotificationThread::DeviceAdded,
342 base::Unretained(this)), 343 base::Unretained(this)),
343 base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, 344 base::Bind(&BatteryStatusNotificationThread::OnSignalConnected,
344 base::Unretained(this))); 345 base::Unretained(this)));
345 upower_->proxy()->ConnectToSignal( 346 upower_->proxy()->ConnectToSignal(
346 kUPowerServiceName, kUPowerSignalDeviceRemoved, 347 kUPowerServiceName, kUPowerSignalDeviceRemoved,
347 base::Bind(&BatteryStatusNotificationThread::DeviceRemoved, 348 base::Bind(&BatteryStatusNotificationThread::DeviceRemoved,
348 base::Unretained(this)), 349 base::Unretained(this)),
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 // - Or it may be a new device; then the previously monitored BatteryObject 391 // - Or it may be a new device; then the previously monitored BatteryObject
391 // instance (if any) is released on leaving this function. 392 // instance (if any) is released on leaving this function.
392 // - Or we may not find a battery device; then on leaving this function 393 // - Or we may not find a battery device; then on leaving this function
393 // battery_ will be nullptr and the previously monitored BatteryObject 394 // battery_ will be nullptr and the previously monitored BatteryObject
394 // instance (if any) is no longer a battery and will be released. 395 // instance (if any) is no longer a battery and will be released.
395 std::unique_ptr<BatteryObject> current = std::move(battery_); 396 std::unique_ptr<BatteryObject> current = std::move(battery_);
396 auto UseCurrentOrCreateBattery = 397 auto UseCurrentOrCreateBattery =
397 [&current, this](const dbus::ObjectPath& device_path) { 398 [&current, this](const dbus::ObjectPath& device_path) {
398 if (current && current->proxy()->object_path() == device_path) 399 if (current && current->proxy()->object_path() == device_path)
399 return std::move(current); 400 return std::move(current);
400 else 401 return CreateBattery(device_path);
401 return CreateBattery(device_path);
402 }; 402 };
403 403
404 dbus::ObjectPath display_device_path = upower_->GetDisplayDevice(); 404 dbus::ObjectPath display_device_path;
405 if (!IsDaemonVersionBelow_0_99())
406 display_device_path = upower_->GetDisplayDevice();
405 if (display_device_path.IsValid()) { 407 if (display_device_path.IsValid()) {
406 std::unique_ptr<BatteryObject> battery = 408 auto battery = UseCurrentOrCreateBattery(display_device_path);
407 UseCurrentOrCreateBattery(display_device_path);
408 if (battery->IsValid()) 409 if (battery->IsValid())
409 battery_ = std::move(battery); 410 battery_ = std::move(battery);
410 } 411 }
411 412
412 if (!battery_) { 413 if (!battery_) {
413 int num_batteries = 0; 414 int num_batteries = 0;
414 for (const auto& device_path : upower_->EnumerateDevices()) { 415 for (const auto& device_path : upower_->EnumerateDevices()) {
415 std::unique_ptr<BatteryObject> battery = 416 auto battery = UseCurrentOrCreateBattery(device_path);
416 UseCurrentOrCreateBattery(device_path);
417
418 if (!battery->IsValid()) 417 if (!battery->IsValid())
419 continue; 418 continue;
420 419
421 if (battery_) { 420 if (battery_) {
422 // TODO(timvolodine): add support for multiple batteries. Currently we 421 // TODO(timvolodine): add support for multiple batteries. Currently we
423 // only collect information from the first battery we encounter 422 // only collect information from the first battery we encounter
424 // (crbug.com/400780). 423 // (crbug.com/400780).
425 LOG(WARNING) << "multiple batteries found, " 424 LOG(WARNING) << "multiple batteries found, "
426 << "using status data of the first battery only."; 425 << "using status data of the first battery only.";
427 } else { 426 } else {
428 battery_ = std::move(battery); 427 battery_ = std::move(battery);
429 } 428 }
430 num_batteries++; 429 num_batteries++;
431 } 430 }
432 431
433 UpdateNumberBatteriesHistogram(num_batteries); 432 UpdateNumberBatteriesHistogram(num_batteries);
434 } 433 }
435 434
436 if (battery_) { 435 if (!battery_) {
437 battery_->properties()->ConnectSignals();
438 NotifyBatteryStatus();
439 } else {
440 callback_.Run(BatteryStatus()); 436 callback_.Run(BatteryStatus());
441 return; 437 return;
442 } 438 }
443 439
440 battery_->properties()->ConnectSignals();
441 NotifyBatteryStatus();
442
444 if (IsDaemonVersionBelow_0_99()) { 443 if (IsDaemonVersionBelow_0_99()) {
445 // UPower Version 0.99 replaced the Changed signal with the 444 // UPower Version 0.99 replaced the Changed signal with the
446 // PropertyChanged signal. For older versions we need to listen 445 // PropertyChanged signal. For older versions we need to listen
447 // to the Changed signal. 446 // to the Changed signal.
448 battery_->proxy()->ConnectToSignal( 447 battery_->proxy()->ConnectToSignal(
449 kUPowerDeviceInterfaceName, kUPowerDeviceSignalChanged, 448 kUPowerDeviceInterfaceName, kUPowerDeviceSignalChanged,
450 base::Bind(&BatteryStatusNotificationThread::BatteryChanged, 449 base::Bind(&BatteryStatusNotificationThread::BatteryChanged,
451 base::Unretained(this)), 450 base::Unretained(this)),
452 base::Bind(&BatteryStatusNotificationThread::OnSignalConnected, 451 base::Bind(&BatteryStatusNotificationThread::OnSignalConnected,
453 base::Unretained(this))); 452 base::Unretained(this)));
(...skipping 15 matching lines...) Expand all
469 FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, system_bus_)); 468 FROM_HERE, base::Bind(&dbus::Bus::ShutdownAndBlock, system_bus_));
470 system_bus_ = NULL; 469 system_bus_ = NULL;
471 } 470 }
472 471
473 void OnSignalConnected(const std::string& interface_name, 472 void OnSignalConnected(const std::string& interface_name,
474 const std::string& signal_name, 473 const std::string& signal_name,
475 bool success) {} 474 bool success) {}
476 475
477 std::unique_ptr<BatteryObject> CreateBattery( 476 std::unique_ptr<BatteryObject> CreateBattery(
478 const dbus::ObjectPath& device_path) { 477 const dbus::ObjectPath& device_path) {
479 std::unique_ptr<BatteryObject> battery(new BatteryObject( 478 return base::MakeUnique<BatteryObject>(
480 system_bus_.get(), device_path, 479 system_bus_.get(), device_path,
481 base::Bind(&BatteryStatusNotificationThread::BatteryPropertyChanged, 480 base::Bind(&BatteryStatusNotificationThread::BatteryPropertyChanged,
482 base::Unretained(this)))); 481 base::Unretained(this)));
483 return battery;
484 } 482 }
485 483
486 void DeviceAdded(dbus::Signal* signal /* unused */) { 484 void DeviceAdded(dbus::Signal* signal /* unused */) {
487 // Re-iterate all devices to see if we need to monitor the added battery 485 // Re-iterate all devices to see if we need to monitor the added battery
488 // instead of the currently monitored battery. 486 // instead of the currently monitored battery.
489 FindBatteryDevice(); 487 FindBatteryDevice();
490 } 488 }
491 489
492 void DeviceRemoved(dbus::Signal* signal) { 490 void DeviceRemoved(dbus::Signal* signal) {
493 if (!battery_) 491 if (!battery_)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 return; 536 return;
539 537
540 // If the system uses a UPower daemon older than version 0.99 538 // If the system uses a UPower daemon older than version 0.99
541 // (see IsDaemonVersionBelow_0_99), then we are notified about changed 539 // (see IsDaemonVersionBelow_0_99), then we are notified about changed
542 // battery_ properties through the 'Changed' signal of the battery_ 540 // battery_ properties through the 'Changed' signal of the battery_
543 // device (see BatteryChanged()). That is implemented to invalidate all 541 // device (see BatteryChanged()). That is implemented to invalidate all
544 // battery_ properties (so they are re-fetched from the dbus). Getting 542 // battery_ properties (so they are re-fetched from the dbus). Getting
545 // the new property-value triggers a callback to BatteryPropertyChanged(). 543 // the new property-value triggers a callback to BatteryPropertyChanged().
546 // notifying_battery_status_ is set to avoid recursion and computing the 544 // notifying_battery_status_ is set to avoid recursion and computing the
547 // status too often. 545 // status too often.
548 notifying_battery_status_ = true; 546 base::AutoReset<bool> notifying_battery_status(&notifying_battery_status_,
547 true);
timvolodine 2017/04/10 12:50:58 nit: not sure if this is actually cleaner than the
Lei Zhang 2017/04/10 18:14:47 You are right. It could have potentially started o
549 callback_.Run(ComputeWebBatteryStatus(battery_->properties())); 548 callback_.Run(ComputeWebBatteryStatus(battery_->properties()));
550 notifying_battery_status_ = false;
551 } 549 }
552 550
553 BatteryStatusService::BatteryUpdateCallback callback_; 551 BatteryStatusService::BatteryUpdateCallback callback_;
554 scoped_refptr<dbus::Bus> system_bus_; 552 scoped_refptr<dbus::Bus> system_bus_;
555 std::unique_ptr<UPowerObject> upower_; 553 std::unique_ptr<UPowerObject> upower_;
556 std::unique_ptr<BatteryObject> battery_; 554 std::unique_ptr<BatteryObject> battery_;
557 bool notifying_battery_status_ = false; 555 bool notifying_battery_status_ = false;
558 556
559 DISALLOW_COPY_AND_ASSIGN(BatteryStatusNotificationThread); 557 DISALLOW_COPY_AND_ASSIGN(BatteryStatusNotificationThread);
560 }; 558 };
(...skipping 21 matching lines...) Expand all
582 notifier_thread_->task_runner()->PostTask( 580 notifier_thread_->task_runner()->PostTask(
583 FROM_HERE, base::Bind(&BatteryStatusNotificationThread::StopListening, 581 FROM_HERE, base::Bind(&BatteryStatusNotificationThread::StopListening,
584 base::Unretained(notifier_thread_.get()))); 582 base::Unretained(notifier_thread_.get())));
585 } 583 }
586 584
587 bool BatteryStatusManagerLinux::StartNotifierThreadIfNecessary() { 585 bool BatteryStatusManagerLinux::StartNotifierThreadIfNecessary() {
588 if (notifier_thread_) 586 if (notifier_thread_)
589 return true; 587 return true;
590 588
591 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); 589 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
592 notifier_thread_.reset(new BatteryStatusNotificationThread(callback_)); 590 auto notifier_thread =
593 if (!notifier_thread_->StartWithOptions(thread_options)) { 591 base::MakeUnique<BatteryStatusNotificationThread>(callback_);
594 notifier_thread_.reset(); 592 if (!notifier_thread->StartWithOptions(thread_options)) {
595 LOG(ERROR) << "Could not start the " << kBatteryNotifierThreadName 593 LOG(ERROR) << "Could not start the " << kBatteryNotifierThreadName
596 << " thread"; 594 << " thread";
597 return false; 595 return false;
598 } 596 }
597 notifier_thread_ = std::move(notifier_thread);
599 return true; 598 return true;
600 } 599 }
601 600
602 base::Thread* BatteryStatusManagerLinux::GetNotifierThreadForTesting() { 601 base::Thread* BatteryStatusManagerLinux::GetNotifierThreadForTesting() {
603 return notifier_thread_.get(); 602 return notifier_thread_.get();
604 } 603 }
605 604
606 // static 605 // static
607 std::unique_ptr<BatteryStatusManagerLinux> 606 std::unique_ptr<BatteryStatusManagerLinux>
608 BatteryStatusManagerLinux::CreateForTesting( 607 BatteryStatusManagerLinux::CreateForTesting(
609 const BatteryStatusService::BatteryUpdateCallback& callback, 608 const BatteryStatusService::BatteryUpdateCallback& callback,
610 dbus::Bus* bus) { 609 dbus::Bus* bus) {
611 std::unique_ptr<BatteryStatusManagerLinux> manager( 610 auto manager = base::MakeUnique<BatteryStatusManagerLinux>(callback);
612 new BatteryStatusManagerLinux(callback)); 611 if (!manager->StartNotifierThreadIfNecessary())
613 if (manager->StartNotifierThreadIfNecessary()) 612 return nullptr;
614 manager->notifier_thread_->SetDBusForTesting(bus); 613 manager->notifier_thread_->SetDBusForTesting(bus);
615 else
616 manager.reset();
617 return manager; 614 return manager;
618 } 615 }
619 616
620 // static 617 // static
621 std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( 618 std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create(
622 const BatteryStatusService::BatteryUpdateCallback& callback) { 619 const BatteryStatusService::BatteryUpdateCallback& callback) {
623 return std::unique_ptr<BatteryStatusManager>( 620 return base::MakeUnique<BatteryStatusManagerLinux>(callback);
624 new BatteryStatusManagerLinux(callback));
625 } 621 }
626 622
627 } // namespace device 623 } // namespace device
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698