arc_wake_lock_bridge.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include <utility>
  6. #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
  7. #include "ash/components/arc/session/arc_bridge_service.h"
  8. #include "ash/components/arc/session/arc_service_manager.h"
  9. #include "ash/components/arc/wake_lock/arc_wake_lock_bridge.h"
  10. #include "base/bind.h"
  11. #include "base/logging.h"
  12. #include "base/memory/singleton.h"
  13. #include "chromeos/dbus/power/power_policy_controller.h"
  14. #include "content/public/browser/device_service.h"
  15. #include "mojo/public/cpp/bindings/remote.h"
  16. #include "services/device/public/mojom/wake_lock_provider.mojom.h"
  17. namespace arc {
  18. namespace {
  19. constexpr char kWakeLockReason[] = "ARC";
  20. // Singleton factory for ArcWakeLockBridge.
  21. class ArcWakeLockBridgeFactory
  22. : public internal::ArcBrowserContextKeyedServiceFactoryBase<
  23. ArcWakeLockBridge,
  24. ArcWakeLockBridgeFactory> {
  25. public:
  26. // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
  27. static constexpr const char* kName = "ArcWakeLockBridgeFactory";
  28. static ArcWakeLockBridgeFactory* GetInstance() {
  29. return base::Singleton<ArcWakeLockBridgeFactory>::get();
  30. }
  31. private:
  32. friend base::DefaultSingletonTraits<ArcWakeLockBridgeFactory>;
  33. ArcWakeLockBridgeFactory() = default;
  34. ~ArcWakeLockBridgeFactory() override = default;
  35. };
  36. } // namespace
  37. // WakeLockRequester requests a wake lock from the device service in response
  38. // to wake lock requests of a given type from Android. A count is kept of
  39. // outstanding Android requests so that only a single actual wake lock is used.
  40. class ArcWakeLockBridge::WakeLockRequester {
  41. public:
  42. WakeLockRequester(device::mojom::WakeLockType type,
  43. device::mojom::WakeLockProvider* provider)
  44. : type_(type), provider_(provider) {}
  45. WakeLockRequester(const WakeLockRequester&) = delete;
  46. WakeLockRequester& operator=(const WakeLockRequester&) = delete;
  47. ~WakeLockRequester() = default;
  48. // Increments the number of outstanding requests from Android and requests a
  49. // wake lock from the device service if this is the only request.
  50. void AddRequest() {
  51. DCHECK_GE(wake_lock_count_, 0);
  52. wake_lock_count_++;
  53. if (wake_lock_count_ > 1) {
  54. DVLOG(1) << "Partial wake lock acquire. Count: " << wake_lock_count_;
  55. return;
  56. }
  57. // Initialize |wake_lock_| if this is the first time we're using it.
  58. DVLOG(1) << "Partial wake lock new acquire. Count: " << wake_lock_count_;
  59. if (!wake_lock_) {
  60. provider_->GetWakeLockWithoutContext(
  61. type_, device::mojom::WakeLockReason::kOther, kWakeLockReason,
  62. wake_lock_.BindNewPipeAndPassReceiver());
  63. }
  64. wake_lock_->RequestWakeLock();
  65. }
  66. // Decrements the number of outstanding Android requests. Cancels the device
  67. // service wake lock when the request count hits zero.
  68. void RemoveRequest() {
  69. DCHECK_GE(wake_lock_count_, 0);
  70. if (wake_lock_count_ == 0) {
  71. LOG(WARNING) << "Release without acquire. Count: " << wake_lock_count_;
  72. return;
  73. }
  74. wake_lock_count_--;
  75. if (wake_lock_count_ >= 1) {
  76. DVLOG(1) << "Partial wake release. Count: " << wake_lock_count_;
  77. return;
  78. }
  79. DCHECK(wake_lock_);
  80. DVLOG(1) << "Partial wake force release. Count: " << wake_lock_count_;
  81. wake_lock_->CancelWakeLock();
  82. }
  83. // Runs the message loop until replies have been received for all pending
  84. // requests on |wake_lock_|.
  85. void FlushForTesting() {
  86. if (wake_lock_)
  87. wake_lock_.FlushForTesting();
  88. }
  89. private:
  90. // Type of wake lock to request.
  91. const device::mojom::WakeLockType type_;
  92. // Used to get wake locks. Not owned.
  93. device::mojom::WakeLockProvider* const provider_;
  94. // Number of outstanding Android requests.
  95. int64_t wake_lock_count_ = 0;
  96. // Lazily initialized in response to first request.
  97. mojo::Remote<device::mojom::WakeLock> wake_lock_;
  98. };
  99. // static
  100. BrowserContextKeyedServiceFactory* ArcWakeLockBridge::GetFactory() {
  101. return ArcWakeLockBridgeFactory::GetInstance();
  102. }
  103. // static
  104. ArcWakeLockBridge* ArcWakeLockBridge::GetForBrowserContext(
  105. content::BrowserContext* context) {
  106. return ArcWakeLockBridgeFactory::GetForBrowserContext(context);
  107. }
  108. // static
  109. ArcWakeLockBridge* ArcWakeLockBridge::GetForBrowserContextForTesting(
  110. content::BrowserContext* context) {
  111. return ArcWakeLockBridgeFactory::GetForBrowserContextForTesting(context);
  112. }
  113. ArcWakeLockBridge::ArcWakeLockBridge(content::BrowserContext* context,
  114. ArcBridgeService* bridge_service)
  115. : arc_bridge_service_(bridge_service) {
  116. arc_bridge_service_->wake_lock()->SetHost(this);
  117. arc_bridge_service_->wake_lock()->AddObserver(this);
  118. }
  119. ArcWakeLockBridge::~ArcWakeLockBridge() {
  120. arc_bridge_service_->wake_lock()->RemoveObserver(this);
  121. arc_bridge_service_->wake_lock()->SetHost(nullptr);
  122. }
  123. void ArcWakeLockBridge::OnConnectionClosed() {
  124. DVLOG(1) << "OnConnectionClosed";
  125. wake_lock_requesters_.clear();
  126. }
  127. void ArcWakeLockBridge::FlushWakeLocksForTesting() {
  128. for (const auto& it : wake_lock_requesters_)
  129. it.second->FlushForTesting();
  130. }
  131. void ArcWakeLockBridge::AcquirePartialWakeLock(
  132. AcquirePartialWakeLockCallback callback) {
  133. GetWakeLockRequester(device::mojom::WakeLockType::kPreventAppSuspension)
  134. ->AddRequest();
  135. std::move(callback).Run(true);
  136. }
  137. void ArcWakeLockBridge::ReleasePartialWakeLock(
  138. ReleasePartialWakeLockCallback callback) {
  139. GetWakeLockRequester(device::mojom::WakeLockType::kPreventAppSuspension)
  140. ->RemoveRequest();
  141. std::move(callback).Run(true);
  142. }
  143. ArcWakeLockBridge::WakeLockRequester* ArcWakeLockBridge::GetWakeLockRequester(
  144. device::mojom::WakeLockType type) {
  145. auto it = wake_lock_requesters_.find(type);
  146. if (it != wake_lock_requesters_.end())
  147. return it->second.get();
  148. if (!wake_lock_provider_) {
  149. content::GetDeviceService().BindWakeLockProvider(
  150. wake_lock_provider_.BindNewPipeAndPassReceiver());
  151. }
  152. it = wake_lock_requesters_
  153. .emplace(type, std::make_unique<WakeLockRequester>(
  154. type, wake_lock_provider_.get()))
  155. .first;
  156. return it->second.get();
  157. }
  158. } // namespace arc