| Index: athena/resource_manager/resource_manager_impl.cc
|
| diff --git a/athena/resource_manager/resource_manager_impl.cc b/athena/resource_manager/resource_manager_impl.cc
|
| deleted file mode 100644
|
| index 36a0edd5383b07926cfc91360210e868210a4893..0000000000000000000000000000000000000000
|
| --- a/athena/resource_manager/resource_manager_impl.cc
|
| +++ /dev/null
|
| @@ -1,440 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "athena/resource_manager/public/resource_manager.h"
|
| -
|
| -#include <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "athena/activity/public/activity.h"
|
| -#include "athena/activity/public/activity_manager.h"
|
| -#include "athena/activity/public/activity_manager_observer.h"
|
| -#include "athena/resource_manager/memory_pressure_notifier.h"
|
| -#include "athena/resource_manager/public/resource_manager_delegate.h"
|
| -#include "athena/wm/public/window_list_provider.h"
|
| -#include "athena/wm/public/window_list_provider_observer.h"
|
| -#include "athena/wm/public/window_manager.h"
|
| -#include "athena/wm/public/window_manager_observer.h"
|
| -#include "base/containers/adapters.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/time/time.h"
|
| -#include "ui/aura/window.h"
|
| -
|
| -namespace athena {
|
| -namespace {
|
| -
|
| -class ResourceManagerImpl : public ResourceManager,
|
| - public WindowManagerObserver,
|
| - public ActivityManagerObserver,
|
| - public MemoryPressureObserver,
|
| - public WindowListProviderObserver {
|
| - public:
|
| - ResourceManagerImpl(ResourceManagerDelegate* delegate);
|
| - ~ResourceManagerImpl() override;
|
| -
|
| - // ResourceManager:
|
| - virtual void SetMemoryPressureAndStopMonitoring(
|
| - MemoryPressure pressure) override;
|
| - virtual void SetWaitTimeBetweenResourceManageCalls(int time_in_ms) override {
|
| - wait_time_for_resource_deallocation_ =
|
| - base::TimeDelta::FromMilliseconds(time_in_ms);
|
| - // Reset the timeout to force the next resource call to execute immediately.
|
| - next_resource_management_time_ = base::Time::Now();
|
| - }
|
| -
|
| - virtual void Pause(bool pause) override {
|
| - if (pause) {
|
| - if (!pause_)
|
| - queued_command_ = false;
|
| - ++pause_;
|
| - } else {
|
| - DCHECK(pause_);
|
| - --pause_;
|
| - if (!pause && queued_command_)
|
| - ManageResource();
|
| - }
|
| - }
|
| -
|
| - // ActivityManagerObserver:
|
| - virtual void OnActivityStarted(Activity* activity) override;
|
| - virtual void OnActivityEnding(Activity* activity) override;
|
| - virtual void OnActivityOrderChanged() override;
|
| -
|
| - // WindowManagerObserver:
|
| - virtual void OnOverviewModeEnter() override;
|
| - virtual void OnOverviewModeExit() override;
|
| - virtual void OnSplitViewModeEnter() override;
|
| - virtual void OnSplitViewModeExit() override;
|
| -
|
| - // MemoryPressureObserver:
|
| - virtual void OnMemoryPressure(MemoryPressure pressure) override;
|
| - virtual ResourceManagerDelegate* GetDelegate() override;
|
| -
|
| - // WindowListProviderObserver:
|
| - virtual void OnWindowStackingChangedInList() override;
|
| - virtual void OnWindowAddedToList(aura::Window* added_window) override {}
|
| - virtual void OnWindowRemovedFromList(aura::Window* removed_window,
|
| - int index) override {}
|
| -
|
| - private:
|
| - // Manage the resources for our activities.
|
| - void ManageResource();
|
| -
|
| - // Check that the visibility of activities is properly set.
|
| - void UpdateVisibilityStates();
|
| -
|
| - // Check if activities can be unloaded to reduce memory pressure.
|
| - void TryToUnloadAnActivity();
|
| -
|
| - // Resources were released and a quiet period is needed before we release
|
| - // more since it takes a while to trickle through the system.
|
| - void OnResourcesReleased();
|
| -
|
| - // The memory pressure has increased, previously applied measures did not show
|
| - // effect and immediate action is required.
|
| - void OnMemoryPressureIncreased();
|
| -
|
| - // Returns true when the previous memory release was long enough ago to try
|
| - // unloading another activity.
|
| - bool AllowedToUnloadActivity();
|
| -
|
| - // The resource manager delegate.
|
| - scoped_ptr<ResourceManagerDelegate> delegate_;
|
| -
|
| - // Keeping a reference to the current memory pressure.
|
| - MemoryPressure current_memory_pressure_;
|
| -
|
| - // The memory pressure notifier.
|
| - scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_;
|
| -
|
| - // A ref counter. As long as not 0, the management is on hold.
|
| - int pause_;
|
| -
|
| - // If true, a command came in while the resource manager was paused.
|
| - bool queued_command_;
|
| -
|
| - // Used by ManageResource() to determine an activity state change while it
|
| - // changes Activity properties.
|
| - bool activity_order_changed_;
|
| -
|
| - // True if in overview mode - activity order changes will be ignored if true
|
| - // and postponed till after the overview mode is ending.
|
| - bool in_overview_mode_;
|
| -
|
| - // True if we are in split view mode.
|
| - bool in_split_view_mode_;
|
| -
|
| - // The last time the resource manager was called to release resources.
|
| - // Avoid too aggressive resource de-allocation by enforcing a wait time of
|
| - // |wait_time_for_resource_deallocation_| between executed calls.
|
| - base::Time next_resource_management_time_;
|
| -
|
| - // The wait time between two resource managing executions.
|
| - base::TimeDelta wait_time_for_resource_deallocation_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl);
|
| -};
|
| -
|
| -namespace {
|
| -ResourceManagerImpl* instance = nullptr;
|
| -
|
| -// We allow this many activities to be visible. All others must be at state of
|
| -// invisible or below.
|
| -const int kMaxVisibleActivities = 3;
|
| -
|
| -} // namespace
|
| -
|
| -ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate)
|
| - : delegate_(delegate),
|
| - current_memory_pressure_(MEMORY_PRESSURE_UNKNOWN),
|
| - memory_pressure_notifier_(new MemoryPressureNotifier(this)),
|
| - pause_(false),
|
| - queued_command_(false),
|
| - activity_order_changed_(false),
|
| - in_overview_mode_(false),
|
| - in_split_view_mode_(false),
|
| - next_resource_management_time_(base::Time::Now()),
|
| - wait_time_for_resource_deallocation_(base::TimeDelta::FromMilliseconds(
|
| - delegate_->MemoryPressureIntervalInMS())) {
|
| - WindowManager::Get()->AddObserver(this);
|
| - WindowManager::Get()->GetWindowListProvider()->AddObserver(this);
|
| - ActivityManager::Get()->AddObserver(this);
|
| -}
|
| -
|
| -ResourceManagerImpl::~ResourceManagerImpl() {
|
| - ActivityManager::Get()->RemoveObserver(this);
|
| - WindowManager::Get()->GetWindowListProvider()->RemoveObserver(this);
|
| - WindowManager::Get()->RemoveObserver(this);
|
| -}
|
| -
|
| -void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring(
|
| - MemoryPressure pressure) {
|
| - memory_pressure_notifier_->StopObserving();
|
| - OnMemoryPressure(pressure);
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnActivityStarted(Activity* activity) {
|
| - // Update the activity states.
|
| - ManageResource();
|
| - activity_order_changed_ = true;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnActivityEnding(Activity* activity) {
|
| - activity_order_changed_ = true;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnActivityOrderChanged() {
|
| - activity_order_changed_ = true;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnOverviewModeEnter() {
|
| - in_overview_mode_ = true;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnOverviewModeExit() {
|
| - in_overview_mode_ = false;
|
| - ManageResource();
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnSplitViewModeEnter() {
|
| - // Re-apply the memory pressure to make sure enough items are visible.
|
| - in_split_view_mode_ = true;
|
| - ManageResource();
|
| -}
|
| -
|
| -
|
| -void ResourceManagerImpl::OnSplitViewModeExit() {
|
| - // We don't do immediately something yet. The next ManageResource call will
|
| - // come soon.
|
| - in_split_view_mode_ = false;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnWindowStackingChangedInList() {
|
| - if (pause_) {
|
| - queued_command_ = true;
|
| - return;
|
| - }
|
| -
|
| - // No need to do anything while being in overview mode.
|
| - if (in_overview_mode_)
|
| - return;
|
| -
|
| - // Manage the resources of each activity.
|
| - ManageResource();
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnMemoryPressure(MemoryPressure pressure) {
|
| - if (pressure > current_memory_pressure_)
|
| - OnMemoryPressureIncreased();
|
| - current_memory_pressure_ = pressure;
|
| - ManageResource();
|
| -}
|
| -
|
| -ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() {
|
| - return delegate_.get();
|
| -}
|
| -
|
| -void ResourceManagerImpl::ManageResource() {
|
| - // If there is none or only one app running we cannot do anything.
|
| - if (ActivityManager::Get()->GetActivityList().size() <= 1U)
|
| - return;
|
| -
|
| - if (pause_) {
|
| - queued_command_ = true;
|
| - return;
|
| - }
|
| -
|
| - // Check that the visibility of items is properly set. Note that this might
|
| - // already trigger a release of resources. If this happens,
|
| - // AllowedToUnloadActivity() will return false.
|
| - UpdateVisibilityStates();
|
| -
|
| - // Since resource deallocation takes time, we avoid to release more resources
|
| - // in short succession. Note that we come here periodically and if one call
|
| - // is not triggering an unload, the next one will.
|
| - if (AllowedToUnloadActivity())
|
| - TryToUnloadAnActivity();
|
| -}
|
| -
|
| -void ResourceManagerImpl::UpdateVisibilityStates() {
|
| - // The first n activities should be treated as "visible", means they updated
|
| - // in overview mode and will keep their layer resources for faster switch
|
| - // times. Usually we use |kMaxVisibleActivities| items, but when the memory
|
| - // pressure gets critical we only hold as many as are really visible.
|
| - size_t max_activities = kMaxVisibleActivities;
|
| - if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL)
|
| - max_activities = in_split_view_mode_ ? 2 : 1;
|
| -
|
| - do {
|
| - activity_order_changed_ = false;
|
| -
|
| - // Change the visibility of our activities in a pre-processing step. This is
|
| - // required since it might change the order/number of activities.
|
| - // Note: We cannot use the order of items in the ActivityManager since it
|
| - // does not follow the order of windows.
|
| - size_t count = 0;
|
| - const aura::Window::Windows& windows =
|
| - WindowManager::Get()->GetWindowListProvider()->GetWindowList();
|
| - for (aura::Window::Windows::const_reverse_iterator it = windows.rbegin();
|
| - it != windows.rend(); it++) {
|
| - Activity* activity = ActivityManager::Get()->GetActivityForWindow(*it);
|
| - // It is possible that the window was not yet added to the ActivityManager
|
| - // in which case we are not interested in managing it yet.
|
| - if (!activity)
|
| - continue;
|
| - Activity::ActivityState state = activity->GetCurrentState();
|
| -
|
| - // The first |kMaxVisibleActivities| entries should be visible, all others
|
| - // invisible or at a lower activity state.
|
| - if (count < max_activities ||
|
| - (state == Activity::ACTIVITY_INVISIBLE ||
|
| - state == Activity::ACTIVITY_VISIBLE)) {
|
| - Activity::ActivityState visiblity_state =
|
| - count < max_activities ? Activity::ACTIVITY_VISIBLE :
|
| - Activity::ACTIVITY_INVISIBLE;
|
| - // Only change the state when it changes. Note that when the memory
|
| - // pressure is critical, only the primary activities (1 or 2) are made
|
| - // visible. Furthermore, in relaxed mode we only want to turn visible,
|
| - // never invisible.
|
| - if (visiblity_state != state &&
|
| - (current_memory_pressure_ != MEMORY_PRESSURE_LOW ||
|
| - visiblity_state == Activity::ACTIVITY_VISIBLE)) {
|
| - activity->SetCurrentState(visiblity_state);
|
| - // If we turned an activity invisible, we are already releasing memory
|
| - // and can hold off releasing more for now.
|
| - if (visiblity_state == Activity::ACTIVITY_INVISIBLE)
|
| - OnResourcesReleased();
|
| - }
|
| - }
|
| -
|
| - // See which count we should handle next.
|
| - if (activity_order_changed_)
|
| - break;
|
| - ++count;
|
| - }
|
| - // If we stopped iterating over the list of activities because of the change
|
| - // in ordering, then restart processing the activities from the beginning.
|
| - } while (activity_order_changed_);
|
| -}
|
| -
|
| -void ResourceManagerImpl::TryToUnloadAnActivity() {
|
| - // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis
|
| - // and running applications into account. For this first patch we only do a
|
| - // very simple "floating window" algorithm which is surely not good enough.
|
| - size_t max_running_activities = 5;
|
| - switch (current_memory_pressure_) {
|
| - case MEMORY_PRESSURE_UNKNOWN:
|
| - // If we do not know how much memory we have we assume that it must be a
|
| - // high consumption.
|
| - // Fallthrough.
|
| - case MEMORY_PRESSURE_HIGH:
|
| - max_running_activities = 5;
|
| - break;
|
| - case MEMORY_PRESSURE_CRITICAL:
|
| - max_running_activities = 0;
|
| - break;
|
| - case MEMORY_PRESSURE_MODERATE:
|
| - max_running_activities = 7;
|
| - break;
|
| - case MEMORY_PRESSURE_LOW:
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - // Check if / which activity we want to unload.
|
| - Activity* oldest_media_activity = nullptr;
|
| - Activity* oldest_unloadable_activity = nullptr;
|
| - size_t unloadable_activity_count = 0;
|
| - const ActivityList& activity_list = ActivityManager::Get()->GetActivityList();
|
| - for (Activity* activity : activity_list) {
|
| - Activity::ActivityState state = activity->GetCurrentState();
|
| - // The activity should neither be unloaded nor visible.
|
| - if (state != Activity::ACTIVITY_UNLOADED &&
|
| - state != Activity::ACTIVITY_VISIBLE) {
|
| - if (activity->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) {
|
| - // Does not play media - so we can unload this immediately.
|
| - ++unloadable_activity_count;
|
| - oldest_unloadable_activity = activity;
|
| - } else {
|
| - oldest_media_activity = activity;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (unloadable_activity_count > max_running_activities) {
|
| - CHECK(oldest_unloadable_activity);
|
| - OnResourcesReleased();
|
| - oldest_unloadable_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
|
| - return;
|
| - } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) {
|
| - if (oldest_media_activity) {
|
| - OnResourcesReleased();
|
| - oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
|
| - LOG(WARNING) << "Unloading item to releave critical memory pressure";
|
| - return;
|
| - }
|
| - LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory.";
|
| - return;
|
| - }
|
| -
|
| - if (current_memory_pressure_ != MEMORY_PRESSURE_UNKNOWN) {
|
| - // Only show this warning when the memory pressure is actually known. This
|
| - // will suppress warnings in e.g. unit tests.
|
| - LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" <<
|
| - current_memory_pressure_ <<
|
| - "), Activities (running, allowed, unloadable)=(" <<
|
| - activity_list.size() << ", " <<
|
| - max_running_activities << ", " <<
|
| - unloadable_activity_count << ")";
|
| - }
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnResourcesReleased() {
|
| - // Do not release too many activities in short succession since it takes time
|
| - // to release resources. As such wait the memory pressure interval before the
|
| - // next call.
|
| - next_resource_management_time_ = base::Time::Now() +
|
| - wait_time_for_resource_deallocation_;
|
| -}
|
| -
|
| -void ResourceManagerImpl::OnMemoryPressureIncreased() {
|
| - // By setting the timer to Now, the next call will immediately be performed.
|
| - next_resource_management_time_ = base::Time::Now();
|
| -}
|
| -
|
| -bool ResourceManagerImpl::AllowedToUnloadActivity() {
|
| - return current_memory_pressure_ != MEMORY_PRESSURE_LOW &&
|
| - base::Time::Now() >= next_resource_management_time_;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// static
|
| -void ResourceManager::Create() {
|
| - DCHECK(!instance);
|
| - instance = new ResourceManagerImpl(
|
| - ResourceManagerDelegate::CreateResourceManagerDelegate());
|
| -}
|
| -
|
| -// static
|
| -ResourceManager* ResourceManager::Get() {
|
| - return instance;
|
| -}
|
| -
|
| -// static
|
| -void ResourceManager::Shutdown() {
|
| - DCHECK(instance);
|
| - delete instance;
|
| - instance = nullptr;
|
| -}
|
| -
|
| -ResourceManager::ResourceManager() {}
|
| -
|
| -ResourceManager::~ResourceManager() {
|
| - DCHECK(instance);
|
| - instance = nullptr;
|
| -}
|
| -
|
| -} // namespace athena
|
|
|