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

Unified Diff: athena/resource_manager/resource_manager_impl.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: Aaaand another rebase 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_impl.cc
diff --git a/athena/resource_manager/resource_manager_impl.cc b/athena/resource_manager/resource_manager_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..74e5baf75329a2c6fa703856de34e782fb82223a
--- /dev/null
+++ b/athena/resource_manager/resource_manager_impl.cc
@@ -0,0 +1,255 @@
+// 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_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 SetMemoryPressureAndStopMonitoring(
+ 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.
+ 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::SetMemoryPressureAndStopMonitoring(
+ MemoryPressureObserver::MemoryPressure pressure) {
+ memory_pressure_notifier_->StopObserving();
+ 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:
+ // 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:
+ // No need to do anything yet.
+ 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);
+ return;
+ } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) {
+ if (oldest_media_activity) {
+ oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ 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_activities.size() << ")";
+ }
+}
+
+void ResourceManagerImpl::UpdateActivityOrder() {
+ 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 (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