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 |