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 3fff0cfb01e1d2e8fa9256517012575f0a63f75f..8d2479629d879029f52fa3fd986d91d617a14a9d 100644 |
--- a/athena/resource_manager/resource_manager_impl.cc |
+++ b/athena/resource_manager/resource_manager_impl.cc |
@@ -16,6 +16,7 @@ |
#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" |
@@ -51,16 +52,15 @@ class ResourceManagerImpl : public ResourceManager, |
} else { |
DCHECK(pause_); |
--pause_; |
- if (!pause && queued_command_) { |
- UpdateActivityOrder(); |
+ 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; |
@@ -88,11 +88,6 @@ class ResourceManagerImpl : public ResourceManager, |
// Check if activities can be unloaded to reduce memory pressure. |
void TryToUnloadAnActivity(); |
- // Order our activity list to the order of activities of the stream. |
- // TODO(skuhne): Once the ActivityManager is responsible to create this list |
- // for us, we can remove this code here. |
- void UpdateActivityOrder(); |
- |
// 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(); |
@@ -105,11 +100,6 @@ class ResourceManagerImpl : public ResourceManager, |
// unloading another activity. |
bool AllowedToUnloadActivity(); |
- // The sorted (new(front) -> old(back)) activity list. |
- // TODO(skuhne): Once the ActivityManager is responsible to create this list |
- // for us, we can remove this code here. |
- std::vector<Activity*> activity_list_; |
- |
// The resource manager delegate. |
scoped_ptr<ResourceManagerDelegate> delegate_; |
@@ -177,9 +167,6 @@ ResourceManagerImpl::~ResourceManagerImpl() { |
ActivityManager::Get()->RemoveObserver(this); |
WindowManager::Get()->GetWindowListProvider()->RemoveObserver(this); |
WindowManager::Get()->RemoveObserver(this); |
- |
- while (!activity_list_.empty()) |
- OnActivityEnding(activity_list_.front()); |
} |
void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring( |
@@ -189,24 +176,16 @@ void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring( |
} |
void ResourceManagerImpl::OnActivityStarted(Activity* activity) { |
- // As long as we have to manage the list of activities ourselves, we need to |
- // order it here. |
- activity_list_.push_back(activity); |
- UpdateActivityOrder(); |
// Update the activity states. |
ManageResource(); |
- // Remember that the activity order has changed. |
activity_order_changed_ = true; |
} |
void ResourceManagerImpl::OnActivityEnding(Activity* activity) { |
- DCHECK(activity->GetWindow()); |
- // 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::OnActivityOrderChanged() { |
activity_order_changed_ = true; |
} |
@@ -216,9 +195,6 @@ void ResourceManagerImpl::OnOverviewModeEnter() { |
void ResourceManagerImpl::OnOverviewModeExit() { |
in_overview_mode_ = false; |
- // Reorder the activities and manage the resources again since an order change |
- // might have caused a visibility change. |
- UpdateActivityOrder(); |
ManageResource(); |
} |
@@ -236,7 +212,6 @@ void ResourceManagerImpl::OnSplitViewModeExit() { |
} |
void ResourceManagerImpl::OnWindowStackingChangedInList() { |
- activity_order_changed_ = true; |
if (pause_) { |
queued_command_ = true; |
return; |
@@ -246,10 +221,6 @@ void ResourceManagerImpl::OnWindowStackingChangedInList() { |
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(); |
} |
@@ -267,7 +238,7 @@ ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() { |
void ResourceManagerImpl::ManageResource() { |
// If there is none or only one app running we cannot do anything. |
- if (activity_list_.size() <= 1U) |
+ if (ActivityManager::Get()->GetActivities().size() <= 1U) |
return; |
if (pause_) { |
@@ -296,47 +267,46 @@ void ResourceManagerImpl::UpdateVisibilityStates() { |
if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) |
max_activities = in_split_view_mode_ ? 2 : 1; |
- // 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 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(); |
+ 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. |
+ size_t count = 0; |
+ for (Activity* activity : ActivityManager::Get()->GetActivities()) { |
+ 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 index we should handle next. |
- if (activity_order_changed_) { |
- activity_order_changed_ = false; |
- index = 0; |
- } else { |
- ++index; |
+ // 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() { |
@@ -365,25 +335,28 @@ void ResourceManagerImpl::TryToUnloadAnActivity() { |
// Check if / which activity we want to unload. |
Activity* oldest_media_activity = nullptr; |
- std::vector<Activity*> unloadable_activities; |
- for (std::vector<Activity*>::iterator it = activity_list_.begin(); |
- it != activity_list_.end(); ++it) { |
- Activity::ActivityState state = (*it)->GetCurrentState(); |
+ Activity* oldest_unloadable_activity = nullptr; |
+ size_t unloadable_activity_count = 0; |
+ const ActivityList& activity_list = ActivityManager::Get()->GetActivities(); |
+ 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 ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { |
+ if (activity->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { |
// Does not play media - so we can unload this immediately. |
- unloadable_activities.push_back(*it); |
+ ++unloadable_activity_count; |
Mr4D (OOO till 08-26)
2014/11/03 23:48:00
For the time being this is ok.
However - note that
sadrul
2014/11/04 03:43:46
Acknowledged.
|
+ oldest_unloadable_activity = activity; |
} else { |
- oldest_media_activity = *it; |
+ oldest_media_activity = activity; |
} |
} |
} |
- if (unloadable_activities.size() > max_running_activities) { |
+ if (unloadable_activity_count > max_running_activities) { |
+ CHECK(oldest_unloadable_activity); |
OnResourcesReleased(); |
- unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED); |
+ oldest_unloadable_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); |
return; |
} else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) { |
if (oldest_media_activity) { |
@@ -402,41 +375,12 @@ void ResourceManagerImpl::TryToUnloadAnActivity() { |
LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" << |
current_memory_pressure_ << |
"), Activities (running, allowed, unloadable)=(" << |
- activity_list_.size() << ", " << |
+ activity_list.size() << ", " << |
max_running_activities << ", " << |
- unloadable_activities.size() << ")"; |
+ unloadable_activity_count << ")"; |
} |
} |
-void ResourceManagerImpl::UpdateActivityOrder() { |
- queued_command_ = true; |
- if (activity_list_.empty()) |
- return; |
- std::vector<Activity*> new_activity_list; |
- const aura::Window::Windows children = |
- WindowManager::Get()->GetWindowListProvider()->GetWindowList(); |
- // Find the first window in the container which is part of the application. |
- 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) { |
- if (*child_iterator == (*activity_iterator)->GetWindow()) { |
- new_activity_list.push_back(*activity_iterator); |
- activity_list_.erase(activity_iterator); |
- break; |
- } |
- } |
- } |
- // 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; |
-} |
- |
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 |