Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // 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.
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "athena/resource_manager/public/resource_manager.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "athena/activity/public/activity.h" | |
| 11 #include "athena/activity/public/activity_manager.h" | |
| 12 #include "athena/activity/public/activity_manager_observer.h" | |
| 13 #include "athena/resource_manager/memory_pressure_notifier.h" | |
| 14 #include "athena/resource_manager/public/resource_manager_delegate.h" | |
| 15 #include "athena/wm/public/window_manager.h" | |
| 16 #include "athena/wm/public/window_manager_observer.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/memory/scoped_ptr.h" | |
| 19 #include "ui/aura/window.h" | |
| 20 | |
| 21 namespace athena { | |
| 22 | |
| 23 class ResourceManagerImpl : public ResourceManager, | |
| 24 public WindowManagerObserver, | |
| 25 public ActivityManagerObserver, | |
| 26 public MemoryPressureObserver { | |
| 27 public: | |
| 28 ResourceManagerImpl(ResourceManagerDelegate* delegate); | |
| 29 virtual ~ResourceManagerImpl(); | |
| 30 | |
| 31 // ResourceManager: | |
| 32 virtual void SetMemoryPressureForTest( | |
| 33 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE; | |
| 34 | |
| 35 // ActivityManagerObserver: | |
| 36 virtual void OnActivityStarted(Activity* activity) OVERRIDE; | |
| 37 virtual void OnActivityEnding(Activity* activity) OVERRIDE; | |
| 38 | |
| 39 // WindowManagerObserver: | |
| 40 virtual void OnOverviewModeEnter() OVERRIDE; | |
| 41 virtual void OnOverviewModeExit() OVERRIDE; | |
| 42 virtual void OnActivityOrderHasChanged() OVERRIDE; | |
| 43 | |
| 44 // MemoryPressureObserver: | |
| 45 virtual void OnMemoryPressure( | |
| 46 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE; | |
| 47 virtual ResourceManagerDelegate* GetDelegate() OVERRIDE; | |
| 48 | |
| 49 private: | |
| 50 // Manage the resources for our activities. | |
| 51 void ManageResource(); | |
| 52 | |
| 53 // Order our activity list to the order of activities of the stream. | |
| 54 // TODO(skuhne): Once the ActivityManager is responsible to create this list | |
| 55 // for us, we can remove this code here. | |
| 56 void UpdateActivityOrder(); | |
| 57 | |
| 58 // The sorted (new(front) -> old(back)) activity list. | |
| 59 // TODO(skuhne): Once the ActivityManager is responsible to create this list | |
| 60 // 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
| |
| 61 std::vector<Activity*> activity_list_; | |
| 62 | |
| 63 // The resource manager delegate. | |
| 64 scoped_ptr<ResourceManagerDelegate> delegate_; | |
| 65 | |
| 66 // Keeping a reference to the current memory pressure. | |
| 67 MemoryPressureObserver::MemoryPressure current_memory_pressure_; | |
| 68 | |
| 69 // The memory pressure notifier. | |
| 70 scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl); | |
| 73 }; | |
| 74 | |
| 75 namespace { | |
| 76 ResourceManagerImpl* instance = NULL; | |
| 77 } // namespace | |
| 78 | |
| 79 ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate) | |
| 80 : delegate_(delegate), | |
| 81 current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN), | |
| 82 memory_pressure_notifier_(new MemoryPressureNotifier(this)) { | |
| 83 WindowManager::GetInstance()->AddObserver(this); | |
| 84 ActivityManager::Get()->AddObserver(this); | |
| 85 } | |
| 86 | |
| 87 ResourceManagerImpl::~ResourceManagerImpl() { | |
| 88 ActivityManager::Get()->RemoveObserver(this); | |
| 89 WindowManager::GetInstance()->RemoveObserver(this); | |
| 90 } | |
| 91 | |
| 92 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.
| |
| 93 MemoryPressureObserver::MemoryPressure pressure) { | |
| 94 OnMemoryPressure(pressure); | |
| 95 } | |
| 96 | |
| 97 void ResourceManagerImpl::OnActivityStarted(Activity* activity) { | |
| 98 // As long as we have to manage the list of activities ourselves, we need to | |
| 99 // order it here. | |
| 100 activity_list_.push_back(activity); | |
| 101 UpdateActivityOrder(); | |
| 102 // Update the activity states. | |
| 103 ManageResource(); | |
| 104 } | |
| 105 | |
| 106 void ResourceManagerImpl::OnActivityEnding(Activity* activity) { | |
| 107 // Remove the activity from the list again. | |
| 108 std::vector<Activity*>::iterator it = | |
| 109 std::find(activity_list_.begin(), activity_list_.end(), activity); | |
| 110 DCHECK(it != activity_list_.end()); | |
| 111 activity_list_.erase(it); | |
| 112 } | |
| 113 | |
| 114 void ResourceManagerImpl::OnOverviewModeEnter() { | |
| 115 // Nothing to do here. | |
| 116 } | |
| 117 | |
| 118 void ResourceManagerImpl::OnOverviewModeExit() { | |
| 119 // Nothing to do here. | |
| 120 } | |
| 121 | |
| 122 void ResourceManagerImpl::OnActivityOrderHasChanged() { | |
| 123 // As long as we have to manage the list of activities ourselves, we need to | |
| 124 // order it here. | |
| 125 UpdateActivityOrder(); | |
| 126 // Manage the resources of each activity. | |
| 127 ManageResource(); | |
| 128 } | |
| 129 | |
| 130 void ResourceManagerImpl::OnMemoryPressure( | |
| 131 MemoryPressureObserver::MemoryPressure pressure) { | |
| 132 current_memory_pressure_ = pressure; | |
| 133 ManageResource(); | |
| 134 } | |
| 135 | |
| 136 ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() { | |
| 137 return delegate_.get(); | |
| 138 } | |
| 139 | |
| 140 void ResourceManagerImpl::ManageResource() { | |
| 141 // If there is none or only one app running we cannot do anything. | |
| 142 if (activity_list_.size() <= 1U) | |
| 143 return; | |
| 144 // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis | |
| 145 // and running applications into account. For this first patch we only do a | |
| 146 // very simple "floating window" algorithm which is surely not good enough. | |
| 147 size_t max_running_activities = 5; | |
| 148 switch (current_memory_pressure_) { | |
| 149 case MEMORY_PRESSURE_UNKNOWN: | |
| 150 max_running_activities = 5; | |
| 151 break; | |
| 152 case MEMORY_PRESSURE_CRITICAL: | |
| 153 max_running_activities = 0; | |
| 154 break; | |
| 155 case MEMORY_PRESSURE_HIGH: | |
| 156 max_running_activities = 5; | |
| 157 break; | |
| 158 case MEMORY_PRESSURE_MODERATE: | |
| 159 max_running_activities = 7; | |
| 160 break; | |
| 161 case MEMORY_PRESSURE_LOW: | |
| 162 // 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
| |
| 163 return; | |
| 164 } | |
| 165 Activity* oldest_media_activity = NULL; | |
| 166 std::vector<Activity*> unloadable_activities; | |
| 167 for (std::vector<Activity*>::iterator it = activity_list_.begin(); | |
| 168 it != activity_list_.end(); ++it) { | |
| 169 // The activity should not be unloaded or visible. | |
| 170 if ((*it)->GetCurrentState() != Activity::ACTIVITY_UNLOADED && | |
| 171 !(*it)->IsVisible()) { | |
| 172 if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { | |
| 173 // Does not play media - so we can unload this immediately. | |
| 174 unloadable_activities.push_back(*it); | |
| 175 } else { | |
| 176 oldest_media_activity = *it; | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 if (unloadable_activities.size() > max_running_activities) { | |
| 181 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.
| |
| 182 return; | |
| 183 } 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.
| |
| 184 if (oldest_media_activity) { | |
| 185 oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
| 186 return; | |
| 187 } | |
| 188 LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory."; | |
| 189 return; | |
| 190 } | |
| 191 LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" << | |
| 192 current_memory_pressure_ << | |
| 193 "), Activities (running, allowed, unloadable)=(" << | |
| 194 activity_list_.size() << ", " << | |
| 195 max_running_activities << ", " << | |
| 196 unloadable_activities.size() << ")"; | |
| 197 } | |
| 198 | |
| 199 void ResourceManagerImpl::UpdateActivityOrder() { | |
| 200 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.
| |
| 201 return; | |
| 202 std::vector<Activity*> new_activity_list; | |
| 203 const aura::Window::Windows children = | |
| 204 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.
| |
| 205 // Find the first window in the container which is part of the application. | |
| 206 for (aura::Window::Windows::const_iterator child_iterator = children.begin(); | |
| 207 child_iterator != children.end(); ++child_iterator) { | |
| 208 for (std::vector<Activity*>::iterator activity_iterator = | |
| 209 activity_list_.begin(); | |
| 210 activity_iterator != activity_list_.end(); ++activity_iterator) { | |
| 211 if (*child_iterator == (*activity_iterator)->GetWindow()) { | |
| 212 new_activity_list.push_back(*activity_iterator); | |
| 213 activity_list_.erase(activity_iterator); | |
| 214 break; | |
| 215 } | |
| 216 } | |
| 217 } | |
| 218 // At this point the old list should be empty and we can swap the lists. | |
| 219 DCHECK(!activity_list_.size()); | |
| 220 activity_list_ = new_activity_list; | |
| 221 } | |
| 222 | |
| 223 // static | |
| 224 void ResourceManager::Create() { | |
| 225 DCHECK(!instance); | |
| 226 instance = new ResourceManagerImpl( | |
| 227 ResourceManagerDelegate::CreateResourceManagerDelegate()); | |
| 228 } | |
| 229 | |
| 230 // static | |
| 231 ResourceManager* ResourceManager::Get() { | |
| 232 return instance; | |
| 233 } | |
| 234 | |
| 235 // static | |
| 236 void ResourceManager::Shutdown() { | |
| 237 DCHECK(instance); | |
| 238 delete instance; | |
| 239 instance = NULL; | |
| 240 } | |
| 241 | |
| 242 ResourceManager::ResourceManager() {} | |
| 243 | |
| 244 ResourceManager::~ResourceManager() { | |
| 245 DCHECK(instance); | |
| 246 instance = NULL; | |
| 247 } | |
| 248 | |
| 249 } // namespace athena | |
| OLD | NEW |