Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 [¤t, this](const dbus::ObjectPath& device_path) { | 398 [¤t, 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 Loading... | |
| 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 Loading... | |
| 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(¬ifying_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 Loading... | |
| 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 |
| OLD | NEW |