Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Unified Diff: athena/resource_manager/resource_manager_impl.cc

Issue 536013002: Decoupling visibility states from webcontent, adding visibility management in ResourceManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
index 74e5baf75329a2c6fa703856de34e782fb82223a..42351a0a6121fc75105487f56eb478a1218b9a2b 100644
--- a/athena/resource_manager/resource_manager_impl.cc
+++ b/athena/resource_manager/resource_manager_impl.cc
@@ -17,13 +17,15 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
namespace athena {
class ResourceManagerImpl : public ResourceManager,
public WindowManagerObserver,
public ActivityManagerObserver,
- public MemoryPressureObserver {
+ public MemoryPressureObserver,
+ public aura::WindowObserver {
public:
ResourceManagerImpl(ResourceManagerDelegate* delegate);
virtual ~ResourceManagerImpl();
@@ -31,6 +33,20 @@ class ResourceManagerImpl : public ResourceManager,
// ResourceManager:
virtual void SetMemoryPressureAndStopMonitoring(
MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
+ virtual void Pause(bool pause) OVERRIDE {
+ if (pause) {
+ if (!pause_)
+ queued_command_ = false;
+ ++pause_;
+ } else {
+ DCHECK(pause_);
+ --pause_;
+ if (!pause && queued_command_) {
+ UpdateActivityOrder();
+ ManageResource();
+ }
+ }
+ }
// ActivityManagerObserver:
virtual void OnActivityStarted(Activity* activity) OVERRIDE;
@@ -39,13 +55,17 @@ class ResourceManagerImpl : public ResourceManager,
// WindowManagerObserver:
virtual void OnOverviewModeEnter() OVERRIDE;
virtual void OnOverviewModeExit() OVERRIDE;
- virtual void OnActivityOrderHasChanged() OVERRIDE;
+ virtual void OnSplitViewModeEnter() OVERRIDE;
+ virtual void OnSplitViewModeExit() OVERRIDE;
// MemoryPressureObserver:
virtual void OnMemoryPressure(
MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
virtual ResourceManagerDelegate* GetDelegate() OVERRIDE;
+ // aura::WindowObserver:
+ virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
+
private:
// Manage the resources for our activities.
void ManageResource();
@@ -69,17 +89,44 @@ class ResourceManagerImpl : public ResourceManager,
// 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_splitview_mode_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl);
};
namespace {
ResourceManagerImpl* instance = NULL;
+
+// 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_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN),
- memory_pressure_notifier_(new MemoryPressureNotifier(this)) {
+ memory_pressure_notifier_(new MemoryPressureNotifier(this)),
+ pause_(false),
+ queued_command_(false),
+ activity_order_changed_(false),
+ in_overview_mode_(false),
+ in_splitview_mode_(false) {
WindowManager::GetInstance()->AddObserver(this);
ActivityManager::Get()->AddObserver(this);
}
@@ -87,6 +134,9 @@ ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate)
ResourceManagerImpl::~ResourceManagerImpl() {
ActivityManager::Get()->RemoveObserver(this);
WindowManager::GetInstance()->RemoveObserver(this);
+
+ while (!activity_list_.empty())
+ OnActivityEnding(activity_list_.front());
}
void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring(
@@ -102,28 +152,58 @@ void ResourceManagerImpl::OnActivityStarted(Activity* activity) {
UpdateActivityOrder();
// Update the activity states.
ManageResource();
+ // Remember that the activity order has changed.
+ activity_order_changed_ = true;
+ activity->GetWindow()->AddObserver(this);
}
void ResourceManagerImpl::OnActivityEnding(Activity* activity) {
+ DCHECK(activity->GetWindow());
+ activity->GetWindow()->RemoveObserver(this);
// Remove the activity from the list again.
std::vector<Activity*>::iterator it =
std::find(activity_list_.begin(), activity_list_.end(), activity);
DCHECK(it != activity_list_.end());
activity_list_.erase(it);
+ // Remember that the activity order has changed.
+ activity_order_changed_ = true;
}
void ResourceManagerImpl::OnOverviewModeEnter() {
- // Nothing to do here.
+ in_overview_mode_ = true;
}
void ResourceManagerImpl::OnOverviewModeExit() {
- // Nothing to do here.
+ in_overview_mode_ = false;
+ // Reorder the activities.
+ UpdateActivityOrder();
+}
+
+void ResourceManagerImpl::OnSplitViewModeEnter() {
+ // Re-apply the memory pressure to make sure enough items are visible.
+ in_splitview_mode_ = true;
+ ManageResource();
}
-void ResourceManagerImpl::OnActivityOrderHasChanged() {
+
+void ResourceManagerImpl::OnSplitViewModeExit() {
+ // We don't do immediately something yet. The next ManageResource call will
+ // come soon.
+ in_splitview_mode_ = false;
+}
+
+void ResourceManagerImpl::OnWindowStackingChanged(aura::Window* window) {
+ // TODO(skuhne): This needs to be changed to some WindowListProvider observer
+ // if we decouple window order from activity order.
+
+ // No need to do anything while being in overview mode.
+ if (in_overview_mode_)
+ return;
+
// As long as we have to manage the list of activities ourselves, we need to
// order it here.
UpdateActivityOrder();
+
// Manage the resources of each activity.
ManageResource();
}
@@ -142,6 +222,12 @@ void ResourceManagerImpl::ManageResource() {
// If there is none or only one app running we cannot do anything.
if (activity_list_.size() <= 1U)
return;
+
+ if (pause_) {
+ queued_command_ = true;
+ return;
+ }
+
// 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.
@@ -161,16 +247,69 @@ void ResourceManagerImpl::ManageResource() {
max_running_activities = 7;
break;
case MEMORY_PRESSURE_LOW:
- // No need to do anything yet.
- return;
+ // This doesn't really matter. We do not change anything but turning
+ // activities visible.
+ max_running_activities = 10000;
+ break;
+ }
+
+ // The first n activities should be trated 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 = 1 + (in_splitview_mode_ ? 1 : 0);
+
+ // Restart and / or bail if the order of activities changes due to our calls.
+ 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.
+ size_t index = 0;
+ while (index < activity_list_.size()) {
+ Activity* activity = activity_list_[index];
+ Activity::ActivityState state = activity->GetCurrentState();
+
+ // The first |kMaxVisibleActivities| entries should be visible, all others
+ // invisible or at a lower activity state.
+ if (index < max_activities ||
+ (state == Activity::ACTIVITY_INVISIBLE ||
+ state == Activity::ACTIVITY_VISIBLE)) {
+ Activity::ActivityState visiblity_state =
+ index < 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 make visible.
+ if (visiblity_state != state &&
+ (current_memory_pressure_ != MEMORY_PRESSURE_LOW ||
+ visiblity_state == Activity::ACTIVITY_VISIBLE))
+ activity->SetCurrentState(visiblity_state);
+ }
+
+ // See which index we should handle next.
+ if (activity_order_changed_) {
+ activity_order_changed_ = false;
+ index = 0;
+ } else {
+ ++index;
+ }
}
+
+ // No need to remove anything.
+ if (current_memory_pressure_ == MEMORY_PRESSURE_LOW)
+ return;
+
+ // Check if/which activity we want to unload.
Activity* oldest_media_activity = NULL;
std::vector<Activity*> unloadable_activities;
for (std::vector<Activity*>::iterator it = activity_list_.begin();
it != activity_list_.end(); ++it) {
- // The activity should not be unloaded or visible.
- if ((*it)->GetCurrentState() != Activity::ACTIVITY_UNLOADED &&
- !(*it)->IsVisible()) {
+ Activity::ActivityState state = (*it)->GetCurrentState();
+ // The activity should neither be unloaded nor visible.
+ if (state != Activity::ACTIVITY_UNLOADED &&
+ state != Activity::ACTIVITY_VISIBLE) {
if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) {
// Does not play media - so we can unload this immediately.
unloadable_activities.push_back(*it);
@@ -179,17 +318,20 @@ void ResourceManagerImpl::ManageResource() {
}
}
}
+
if (unloadable_activities.size() > max_running_activities) {
unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED);
return;
} else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) {
if (oldest_media_activity) {
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.
@@ -203,14 +345,16 @@ void ResourceManagerImpl::ManageResource() {
}
void ResourceManagerImpl::UpdateActivityOrder() {
+ queued_command_ = true;
if (activity_list_.empty())
return;
std::vector<Activity*> new_activity_list;
const aura::Window::Windows children =
activity_list_[0]->GetWindow()->parent()->children();
// Find the first window in the container which is part of the application.
- for (aura::Window::Windows::const_iterator child_iterator = children.begin();
- child_iterator != children.end(); ++child_iterator) {
+ for (aura::Window::Windows::const_reverse_iterator child_iterator =
+ children.rbegin();
+ child_iterator != children.rend(); ++child_iterator) {
for (std::vector<Activity*>::iterator activity_iterator =
activity_list_.begin();
activity_iterator != activity_list_.end(); ++activity_iterator) {
@@ -224,6 +368,9 @@ void ResourceManagerImpl::UpdateActivityOrder() {
// At this point the old list should be empty and we can swap the lists.
DCHECK(!activity_list_.size());
activity_list_ = new_activity_list;
+
+ // Remember that the activity order has changed.
+ activity_order_changed_ = true;
}
// static
« no previous file with comments | « athena/resource_manager/public/resource_manager.h ('k') | athena/resource_manager/resource_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698