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

Unified Diff: athena/resource_manager/resource_manager.cc

Issue 513523002: Adding Baseframework of the ResourceManager (all hooks and observers) are being put in place with a… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self nits Created 6 years, 4 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.cc
diff --git a/athena/resource_manager/resource_manager.cc b/athena/resource_manager/resource_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4742132bc0a03a5e3fbb900982cb5212584c5743
--- /dev/null
+++ b/athena/resource_manager/resource_manager.cc
@@ -0,0 +1,249 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
Jun Mukai 2014/08/27 01:21:19 In athena, usually this file is named as resoure_m
Mr4D (OOO till 08-26) 2014/08/27 16:12:14 Done.
+// 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_manager.h"
+#include "athena/wm/public/window_manager_observer.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window.h"
+
+namespace athena {
+
+class ResourceManagerImpl : public ResourceManager,
+ public WindowManagerObserver,
+ public ActivityManagerObserver,
+ public MemoryPressureObserver {
+ public:
+ ResourceManagerImpl(ResourceManagerDelegate* delegate);
+ virtual ~ResourceManagerImpl();
+
+ // ResourceManager:
+ virtual void SetMemoryPressureForTest(
+ MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
+
+ // ActivityManagerObserver:
+ virtual void OnActivityStarted(Activity* activity) OVERRIDE;
+ virtual void OnActivityEnding(Activity* activity) OVERRIDE;
+
+ // WindowManagerObserver:
+ virtual void OnOverviewModeEnter() OVERRIDE;
+ virtual void OnOverviewModeExit() OVERRIDE;
+ virtual void OnActivityOrderHasChanged() OVERRIDE;
+
+ // MemoryPressureObserver:
+ virtual void OnMemoryPressure(
+ MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
+ virtual ResourceManagerDelegate* GetDelegate() OVERRIDE;
+
+ private:
+ // Manage the resources for our activities.
+ void ManageResource();
+
+ // 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();
+
+ // 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.
Jun Mukai 2014/08/27 01:21:18 Also, it's better to be unified with WindowListPro
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 I know. I have a CL queued (480293003) which adds
Jun Mukai 2014/08/27 16:57:47 Turns out I was still confused by the difference b
+ std::vector<Activity*> activity_list_;
+
+ // The resource manager delegate.
+ scoped_ptr<ResourceManagerDelegate> delegate_;
+
+ // Keeping a reference to the current memory pressure.
+ MemoryPressureObserver::MemoryPressure current_memory_pressure_;
+
+ // The memory pressure notifier.
+ scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl);
+};
+
+namespace {
+ResourceManagerImpl* instance = NULL;
+} // namespace
+
+ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate)
+ : delegate_(delegate),
+ current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN),
+ memory_pressure_notifier_(new MemoryPressureNotifier(this)) {
+ WindowManager::GetInstance()->AddObserver(this);
+ ActivityManager::Get()->AddObserver(this);
+}
+
+ResourceManagerImpl::~ResourceManagerImpl() {
+ ActivityManager::Get()->RemoveObserver(this);
+ WindowManager::GetInstance()->RemoveObserver(this);
+}
+
+void ResourceManagerImpl::SetMemoryPressureForTest(
Jun Mukai 2014/08/27 01:21:19 It might be great to cancel memory_pressure_notifi
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 The TestResourceManagerDelegate will never report
Jun Mukai 2014/08/27 16:57:48 Acknowledged.
+ MemoryPressureObserver::MemoryPressure pressure) {
+ OnMemoryPressure(pressure);
+}
+
+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();
+}
+
+void ResourceManagerImpl::OnActivityEnding(Activity* activity) {
+ // 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);
+}
+
+void ResourceManagerImpl::OnOverviewModeEnter() {
+ // Nothing to do here.
+}
+
+void ResourceManagerImpl::OnOverviewModeExit() {
+ // Nothing to do here.
+}
+
+void ResourceManagerImpl::OnActivityOrderHasChanged() {
+ // 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();
+}
+
+void ResourceManagerImpl::OnMemoryPressure(
+ MemoryPressureObserver::MemoryPressure pressure) {
+ 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 (activity_list_.size() <= 1U)
+ 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.
+ size_t max_running_activities = 5;
+ switch (current_memory_pressure_) {
+ case MEMORY_PRESSURE_UNKNOWN:
+ max_running_activities = 5;
+ break;
+ case MEMORY_PRESSURE_CRITICAL:
+ max_running_activities = 0;
+ break;
+ case MEMORY_PRESSURE_HIGH:
+ max_running_activities = 5;
+ break;
+ case MEMORY_PRESSURE_MODERATE:
+ max_running_activities = 7;
+ break;
+ case MEMORY_PRESSURE_LOW:
+ // No need to do anything yet.
Jun Mukai 2014/08/27 01:21:19 Not sure the difference between HIGH/UNKNOWN (sett
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 I added another comment for unknown. You can find
+ return;
+ }
+ 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()) {
+ if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) {
+ // Does not play media - so we can unload this immediately.
+ unloadable_activities.push_back(*it);
+ } else {
+ oldest_media_activity = *it;
+ }
+ }
+ }
+ if (unloadable_activities.size() > max_running_activities) {
+ unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED);
Jun Mukai 2014/08/27 01:21:18 Is it enough to set the state on only the oldest u
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 The crux here is that any resource change takes ti
Jun Mukai 2014/08/27 16:57:47 Ah, I see.
+ return;
+ } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) {
Jun Mukai 2014/08/27 01:21:18 Think that there are multiple media activities and
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 That was the intent. If there is no memory left an
Jun Mukai 2014/08/27 16:57:47 Acknowledged.
+ if (oldest_media_activity) {
+ oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ return;
+ }
+ LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory.";
+ return;
+ }
+ LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" <<
+ current_memory_pressure_ <<
+ "), Activities (running, allowed, unloadable)=(" <<
+ activity_list_.size() << ", " <<
+ max_running_activities << ", " <<
+ unloadable_activities.size() << ")";
+}
+
+void ResourceManagerImpl::UpdateActivityOrder() {
+ if (!activity_list_.size())
Jun Mukai 2014/08/27 01:21:18 activity_list_.empty() is clearer to me
Mr4D (OOO till 08-26) 2014/08/27 16:12:13 Done.
+ return;
+ std::vector<Activity*> new_activity_list;
+ const aura::Window::Windows children =
+ activity_list_[0]->GetWindow()->parent()->children();;
Jun Mukai 2014/08/27 01:21:18 double semicolon at end
Mr4D (OOO till 08-26) 2014/08/27 16:12:14 Done.
+ // 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 (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;
+}
+
+// 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 = NULL;
+}
+
+ResourceManager::ResourceManager() {}
+
+ResourceManager::~ResourceManager() {
+ DCHECK(instance);
+ instance = NULL;
+}
+
+} // namespace athena

Powered by Google App Engine
This is Rietveld 408576698