| Index: device/wake_lock/wake_lock_service_impl.cc
|
| diff --git a/device/wake_lock/wake_lock_service_impl.cc b/device/wake_lock/wake_lock_service_impl.cc
|
| index ae998aa62f4e27a29e65b60d5c0d3b5eb1c6c026..3b8a1a8515e2058e283b77cd3c4be92c1d1f72ce 100644
|
| --- a/device/wake_lock/wake_lock_service_impl.cc
|
| +++ b/device/wake_lock/wake_lock_service_impl.cc
|
| @@ -6,31 +6,156 @@
|
|
|
| #include <utility>
|
|
|
| +#include "base/atomic_sequence_num.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "device/power_save_blocker/power_save_blocker.h"
|
| #include "device/wake_lock/wake_lock_service_context.h"
|
|
|
| namespace device {
|
|
|
| -WakeLockServiceImpl::WakeLockServiceImpl(WakeLockServiceContext* context)
|
| - : context_(context), wake_lock_request_outstanding_(false) {}
|
| +namespace {
|
| +
|
| +base::StaticAtomicSequenceNumber g_unique_client_id;
|
| +
|
| +} // namespace
|
| +
|
| +WakeLockServiceImpl::WakeLockServiceImpl(
|
| + WakeLockServiceContext* context,
|
| + device::PowerSaveBlocker::PowerSaveBlockerType type,
|
| + device::PowerSaveBlocker::Reason reason,
|
| + const std::string& description,
|
| + int context_id,
|
| + WakeLockContextCallback native_view_getter,
|
| + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
|
| + : context_(context),
|
| + type_(type),
|
| + reason_(reason),
|
| + description_(base::MakeUnique<std::string>(description)),
|
| + num_lock_requests_(0),
|
| +#if defined(OS_ANDROID)
|
| + context_id_(context_id),
|
| + native_view_getter_(native_view_getter),
|
| +#endif
|
| + main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + file_task_runner_(std::move(file_task_runner)),
|
| + outstanding_(false) {
|
| + frames_binding_set_.set_connection_error_handler(base::Bind(
|
| + &WakeLockServiceImpl::OnConnectionError, base::Unretained(this)));
|
| +}
|
|
|
| WakeLockServiceImpl::~WakeLockServiceImpl() {
|
| - CancelWakeLock();
|
| + if (wake_lock_) {
|
| + wake_lock_.reset();
|
| + DCHECK(context_);
|
| + context_->DecreaseWakeLockCount();
|
| + }
|
| +}
|
| +
|
| +void WakeLockServiceImpl::AddClient(mojom::WakeLockServiceRequest request) {
|
| + // Multiple frames that associate to the same WebContents share the same one
|
| + // WakeLockServiceImpl instance. Two consecutive |RequestWakeLock| requests
|
| + // from the same frame should be coalesced as one request. Everytime a new
|
| + // client is being added into the bindingSet, we create an unique client_id
|
| + // as its context, this context is used as the key of the map |outstandings_|
|
| + // which records the clients' last requested status.
|
| + int client_id = g_unique_client_id.GetNext();
|
| + frames_binding_set_.AddBinding(this, std::move(request), client_id);
|
| + outstandings_[client_id] = false;
|
| }
|
|
|
| void WakeLockServiceImpl::RequestWakeLock() {
|
| - if (wake_lock_request_outstanding_)
|
| - return;
|
| + DCHECK(main_task_runner_->RunsTasksOnCurrentThread());
|
| +
|
| + // |frames_binding_set_| empty means the requests are not from frames.
|
| + if (frames_binding_set_.empty()) {
|
| + if (outstanding_) {
|
| + return;
|
| + }
|
| + outstanding_ = true;
|
| + } else {
|
| + // If the requests are from frames, we need the Context of bindingSet to
|
| + // differenciate which binding is from which frame.
|
| + int client_id = frames_binding_set_.dispatch_context();
|
| + if (outstandings_[client_id]) {
|
| + return;
|
| + }
|
| + outstandings_[client_id] = true;
|
| + }
|
|
|
| - wake_lock_request_outstanding_ = true;
|
| - context_->RequestWakeLock();
|
| + num_lock_requests_++;
|
| + UpdateWakeLock();
|
| }
|
|
|
| void WakeLockServiceImpl::CancelWakeLock() {
|
| - if (!wake_lock_request_outstanding_)
|
| - return;
|
| + DCHECK(main_task_runner_->RunsTasksOnCurrentThread());
|
| +
|
| + if (frames_binding_set_.empty()) {
|
| + if (!outstanding_) {
|
| + return;
|
| + }
|
| + outstanding_ = false;
|
| + } else {
|
| + int client_id = frames_binding_set_.dispatch_context();
|
| + if (!outstandings_[client_id]) {
|
| + return;
|
| + }
|
| + outstandings_[client_id] = false;
|
| + if (num_lock_requests_ == 0) {
|
| + return;
|
| + }
|
| + }
|
| +
|
| + num_lock_requests_--;
|
| + UpdateWakeLock();
|
| +}
|
| +
|
| +void WakeLockServiceImpl::UpdateWakeLock() {
|
| + DCHECK(num_lock_requests_ >= 0);
|
| + if (num_lock_requests_) {
|
| + if (!wake_lock_)
|
| + CreateWakeLock();
|
| + } else {
|
| + if (wake_lock_)
|
| + RemoveWakeLock();
|
| + }
|
| +}
|
| +
|
| +void WakeLockServiceImpl::CreateWakeLock() {
|
| + DCHECK(!wake_lock_);
|
| + wake_lock_ = base::MakeUnique<device::PowerSaveBlocker>(
|
| + type_, reason_, *description_, main_task_runner_, file_task_runner_);
|
| + DCHECK(context_);
|
| + context_->IncreaseWakeLockCount();
|
| +
|
| +#if defined(OS_ANDROID)
|
| + gfx::NativeView native_view = native_view_getter_.Run(context_id_);
|
| + if (native_view) {
|
| + wake_lock_.get()->InitDisplaySleepBlocker(native_view);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +void WakeLockServiceImpl::RemoveWakeLock() {
|
| + DCHECK(wake_lock_);
|
| + wake_lock_.reset();
|
| + DCHECK(context_);
|
| + context_->DecreaseWakeLockCount();
|
| +}
|
| +
|
| +void WakeLockServiceImpl::OnConnectionError() {
|
| + int client_id = frames_binding_set_.dispatch_context();
|
| + // If the client's wakelock outstanding status is True before it crashes, we
|
| + // should decrease the num_lock_requests and call UpdateWakeLock().
|
| + if (outstandings_[client_id]) {
|
| + if (num_lock_requests_ == 0) {
|
| + return;
|
| + }
|
| + num_lock_requests_--;
|
| + UpdateWakeLock();
|
| + }
|
|
|
| - wake_lock_request_outstanding_ = false;
|
| - context_->CancelWakeLock();
|
| + // Remove the entry of client_id from map.
|
| + outstandings_.erase(client_id);
|
| }
|
|
|
| } // namespace device
|
|
|