1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/throttle/throttle_service.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/logging.h"
namespace ash {
ThrottleService::ThrottleService(content::BrowserContext* context)
: context_(context) {}
ThrottleService::~ThrottleService() = default;
void ThrottleService::AddServiceObserver(ServiceObserver* observer) {
service_observers_.AddObserver(observer);
}
void ThrottleService::RemoveServiceObserver(ServiceObserver* observer) {
service_observers_.RemoveObserver(observer);
}
ThrottleObserver* ThrottleService::GetObserverByName(const std::string& name) {
for (auto& observer : observers_) {
if (observer->name() == name)
return observer.get();
}
return nullptr;
}
void ThrottleService::NotifyObserverStateChangedForTesting() {
OnObserverStateChanged(nullptr);
}
void ThrottleService::SetObserversForTesting(
std::vector<std::unique_ptr<ThrottleObserver>> observers) {
StopObservers();
observers_ = std::move(observers);
StartObservers();
}
bool ThrottleService::HasServiceObserverForTesting(ServiceObserver* candidate) {
return service_observers_.HasObserver(candidate);
}
void ThrottleService::AddObserver(std::unique_ptr<ThrottleObserver> observer) {
observers_.push_back(std::move(observer));
}
void ThrottleService::StartObservers() {
auto callback = base::BindRepeating(&ThrottleService::OnObserverStateChanged,
weak_ptr_factory_.GetWeakPtr());
for (auto& observer : observers_)
observer->StartObserving(context_, callback);
}
void ThrottleService::StopObservers() {
for (auto& observer : observers_)
observer->StopObserving();
}
void ThrottleService::OnObserverStateChanged(
const ThrottleObserver* changed_observer) {
DVLOG(1) << "OnObserverStateChanged: changed throttle observer is "
<< (changed_observer ? changed_observer->name() : "none");
ThrottleObserver* effective_observer = nullptr;
bool should_throttle = true;
// Check if there's an enforcing observer.
for (auto& observer : observers_) {
if (!observer->enforced())
continue;
DVLOG(1) << "Enforcing ThrottleObserver is found: name=" << observer->name()
<< ", active=" << observer->active();
should_throttle = !observer->active();
effective_observer = observer.get();
break;
}
if (!effective_observer) {
// No enforcing observer is found. Check if there are one (or more) active
// observer(s).
for (auto& observer : observers_) {
if (!observer->active())
continue;
DVLOG(1) << "Active ThrottleObserver is found: name=" << observer->name();
should_throttle = false;
if (!effective_observer)
effective_observer = observer.get();
// Do not break; here to LOG all active observers. Treat the first one as
// an effective observer.
}
if (!effective_observer)
DVLOG(1) << "All ThrottleObserver(s) are inactive";
}
if (effective_observer != last_effective_observer_) {
// If there is a new effective observer, record the duration that the last
// effective observer was active.
if (last_effective_observer_) {
RecordCpuRestrictionDisabledUMA(
last_effective_observer_->name(),
base::TimeTicks::Now() - last_throttle_transition_);
}
last_throttle_transition_ = base::TimeTicks::Now();
last_effective_observer_ = effective_observer;
}
if (should_throttle_ && (*should_throttle_ == should_throttle))
return;
// Do the actual throttling.
should_throttle_ = should_throttle;
ThrottleInstance(*should_throttle_);
for (auto& observer : service_observers_)
observer.OnThrottle(*should_throttle_);
}
} // namespace ash
|