| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "athena/resource_manager/public/resource_manager.h" | 5 #include "athena/resource_manager/public/resource_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "athena/activity/public/activity.h" | 10 #include "athena/activity/public/activity.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 // WindowListProviderObserver: | 75 // WindowListProviderObserver: |
| 76 virtual void OnWindowStackingChanged() OVERRIDE; | 76 virtual void OnWindowStackingChanged() OVERRIDE; |
| 77 virtual void OnWindowRemoved(aura::Window* removed_window, | 77 virtual void OnWindowRemoved(aura::Window* removed_window, |
| 78 int index) OVERRIDE; | 78 int index) OVERRIDE; |
| 79 | 79 |
| 80 private: | 80 private: |
| 81 // Manage the resources for our activities. | 81 // Manage the resources for our activities. |
| 82 void ManageResource(); | 82 void ManageResource(); |
| 83 | 83 |
| 84 // Check that the visibility of activities is properly set. |
| 85 void UpdateVisibilityStates(); |
| 86 |
| 87 // Check if activities can be unloaded to reduce memory pressure. |
| 88 void TryToUnloadAnActivity(); |
| 89 |
| 84 // Order our activity list to the order of activities of the stream. | 90 // Order our activity list to the order of activities of the stream. |
| 85 // TODO(skuhne): Once the ActivityManager is responsible to create this list | 91 // TODO(skuhne): Once the ActivityManager is responsible to create this list |
| 86 // for us, we can remove this code here. | 92 // for us, we can remove this code here. |
| 87 void UpdateActivityOrder(); | 93 void UpdateActivityOrder(); |
| 88 | 94 |
| 95 // Resources were released and a quiet period is needed before we release |
| 96 // more since it takes a while to trickle through the system. |
| 97 void OnResourcesReleased(); |
| 98 |
| 99 // The memory pressure has increased, previously applied measures did not show |
| 100 // effect and immediate action is required. |
| 101 void OnMemoryPressureIncreased(); |
| 102 |
| 103 // Returns true when the previous memory release was long enough ago to try |
| 104 // unloading another activity. |
| 105 bool AllowedToUnloadActivity(); |
| 106 |
| 89 // The sorted (new(front) -> old(back)) activity list. | 107 // The sorted (new(front) -> old(back)) activity list. |
| 90 // TODO(skuhne): Once the ActivityManager is responsible to create this list | 108 // TODO(skuhne): Once the ActivityManager is responsible to create this list |
| 91 // for us, we can remove this code here. | 109 // for us, we can remove this code here. |
| 92 std::vector<Activity*> activity_list_; | 110 std::vector<Activity*> activity_list_; |
| 93 | 111 |
| 94 // The resource manager delegate. | 112 // The resource manager delegate. |
| 95 scoped_ptr<ResourceManagerDelegate> delegate_; | 113 scoped_ptr<ResourceManagerDelegate> delegate_; |
| 96 | 114 |
| 97 // Keeping a reference to the current memory pressure. | 115 // Keeping a reference to the current memory pressure. |
| 98 MemoryPressureObserver::MemoryPressure current_memory_pressure_; | 116 MemoryPressureObserver::MemoryPressure current_memory_pressure_; |
| 99 | 117 |
| 100 // The memory pressure notifier. | 118 // The memory pressure notifier. |
| 101 scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_; | 119 scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_; |
| 102 | 120 |
| 103 // A ref counter. As long as not 0, the management is on hold. | 121 // A ref counter. As long as not 0, the management is on hold. |
| 104 int pause_; | 122 int pause_; |
| 105 | 123 |
| 106 // If true, a command came in while the resource manager was paused. | 124 // If true, a command came in while the resource manager was paused. |
| 107 bool queued_command_; | 125 bool queued_command_; |
| 108 | 126 |
| 109 // Used by ManageResource() to determine an activity state change while it | 127 // Used by ManageResource() to determine an activity state change while it |
| 110 // changes Activity properties. | 128 // changes Activity properties. |
| 111 bool activity_order_changed_; | 129 bool activity_order_changed_; |
| 112 | 130 |
| 113 // True if in overview mode - activity order changes will be ignored if true | 131 // True if in overview mode - activity order changes will be ignored if true |
| 114 // and postponed till after the overview mode is ending. | 132 // and postponed till after the overview mode is ending. |
| 115 bool in_overview_mode_; | 133 bool in_overview_mode_; |
| 116 | 134 |
| 117 // True if we are in split view mode. | 135 // True if we are in split view mode. |
| 118 bool in_splitview_mode_; | 136 bool in_split_view_mode_; |
| 119 | 137 |
| 120 // The last time the resource manager was called to release resources. | 138 // The last time the resource manager was called to release resources. |
| 121 // Avoid too aggressive resource de-allocation by enforcing a wait time of | 139 // Avoid too aggressive resource de-allocation by enforcing a wait time of |
| 122 // |wait_time_for_resource_deallocation_| between executed calls. | 140 // |wait_time_for_resource_deallocation_| between executed calls. |
| 123 base::Time next_resource_management_time_; | 141 base::Time next_resource_management_time_; |
| 124 | 142 |
| 125 // The wait time between two resource managing executions. | 143 // The wait time between two resource managing executions. |
| 126 base::TimeDelta wait_time_for_resource_deallocation_; | 144 base::TimeDelta wait_time_for_resource_deallocation_; |
| 127 | 145 |
| 128 DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl); | 146 DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl); |
| 129 }; | 147 }; |
| 130 | 148 |
| 131 namespace { | 149 namespace { |
| 132 ResourceManagerImpl* instance = NULL; | 150 ResourceManagerImpl* instance = NULL; |
| 133 | 151 |
| 134 // We allow this many activities to be visible. All others must be at state of | 152 // We allow this many activities to be visible. All others must be at state of |
| 135 // invisible or below. | 153 // invisible or below. |
| 136 const int kMaxVisibleActivities = 3; | 154 const int kMaxVisibleActivities = 3; |
| 137 | 155 |
| 138 } // namespace | 156 } // namespace |
| 139 | 157 |
| 140 ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate) | 158 ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate) |
| 141 : delegate_(delegate), | 159 : delegate_(delegate), |
| 142 current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN), | 160 current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN), |
| 143 memory_pressure_notifier_(new MemoryPressureNotifier(this)), | 161 memory_pressure_notifier_(new MemoryPressureNotifier(this)), |
| 144 pause_(false), | 162 pause_(false), |
| 145 queued_command_(false), | 163 queued_command_(false), |
| 146 activity_order_changed_(false), | 164 activity_order_changed_(false), |
| 147 in_overview_mode_(false), | 165 in_overview_mode_(false), |
| 148 in_splitview_mode_(false), | 166 in_split_view_mode_(false), |
| 149 next_resource_management_time_(base::Time::Now()), | 167 next_resource_management_time_(base::Time::Now()), |
| 150 wait_time_for_resource_deallocation_(base::TimeDelta::FromMilliseconds( | 168 wait_time_for_resource_deallocation_(base::TimeDelta::FromMilliseconds( |
| 151 delegate_->MemoryPressureIntervalInMS())) { | 169 delegate_->MemoryPressureIntervalInMS())) { |
| 152 WindowManager::GetInstance()->AddObserver(this); | 170 WindowManager::GetInstance()->AddObserver(this); |
| 153 WindowManager::GetInstance()->GetWindowListProvider()->AddObserver(this); | 171 WindowManager::GetInstance()->GetWindowListProvider()->AddObserver(this); |
| 154 ActivityManager::Get()->AddObserver(this); | 172 ActivityManager::Get()->AddObserver(this); |
| 155 } | 173 } |
| 156 | 174 |
| 157 ResourceManagerImpl::~ResourceManagerImpl() { | 175 ResourceManagerImpl::~ResourceManagerImpl() { |
| 158 ActivityManager::Get()->RemoveObserver(this); | 176 ActivityManager::Get()->RemoveObserver(this); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 void ResourceManagerImpl::OnOverviewModeExit() { | 216 void ResourceManagerImpl::OnOverviewModeExit() { |
| 199 in_overview_mode_ = false; | 217 in_overview_mode_ = false; |
| 200 // Reorder the activities and manage the resources again since an order change | 218 // Reorder the activities and manage the resources again since an order change |
| 201 // might have caused a visibility change. | 219 // might have caused a visibility change. |
| 202 UpdateActivityOrder(); | 220 UpdateActivityOrder(); |
| 203 ManageResource(); | 221 ManageResource(); |
| 204 } | 222 } |
| 205 | 223 |
| 206 void ResourceManagerImpl::OnSplitViewModeEnter() { | 224 void ResourceManagerImpl::OnSplitViewModeEnter() { |
| 207 // Re-apply the memory pressure to make sure enough items are visible. | 225 // Re-apply the memory pressure to make sure enough items are visible. |
| 208 in_splitview_mode_ = true; | 226 in_split_view_mode_ = true; |
| 209 ManageResource(); | 227 ManageResource(); |
| 210 } | 228 } |
| 211 | 229 |
| 212 | 230 |
| 213 void ResourceManagerImpl::OnSplitViewModeExit() { | 231 void ResourceManagerImpl::OnSplitViewModeExit() { |
| 214 // We don't do immediately something yet. The next ManageResource call will | 232 // We don't do immediately something yet. The next ManageResource call will |
| 215 // come soon. | 233 // come soon. |
| 216 in_splitview_mode_ = false; | 234 in_split_view_mode_ = false; |
| 217 } | 235 } |
| 218 | 236 |
| 219 void ResourceManagerImpl::OnWindowStackingChanged() { | 237 void ResourceManagerImpl::OnWindowStackingChanged() { |
| 220 activity_order_changed_ = true; | 238 activity_order_changed_ = true; |
| 221 if (pause_) { | 239 if (pause_) { |
| 222 queued_command_ = true; | 240 queued_command_ = true; |
| 223 return; | 241 return; |
| 224 } | 242 } |
| 225 | 243 |
| 226 // No need to do anything while being in overview mode. | 244 // No need to do anything while being in overview mode. |
| 227 if (in_overview_mode_) | 245 if (in_overview_mode_) |
| 228 return; | 246 return; |
| 229 | 247 |
| 230 // As long as we have to manage the list of activities ourselves, we need to | 248 // As long as we have to manage the list of activities ourselves, we need to |
| 231 // order it here. | 249 // order it here. |
| 232 UpdateActivityOrder(); | 250 UpdateActivityOrder(); |
| 233 | 251 |
| 234 // Manage the resources of each activity. | 252 // Manage the resources of each activity. |
| 235 ManageResource(); | 253 ManageResource(); |
| 236 } | 254 } |
| 237 | 255 |
| 238 void ResourceManagerImpl::OnWindowRemoved(aura::Window* removed_window, | 256 void ResourceManagerImpl::OnWindowRemoved(aura::Window* removed_window, |
| 239 int index) { | 257 int index) { |
| 240 } | 258 } |
| 241 | 259 |
| 242 void ResourceManagerImpl::OnMemoryPressure( | 260 void ResourceManagerImpl::OnMemoryPressure( |
| 243 MemoryPressureObserver::MemoryPressure pressure) { | 261 MemoryPressureObserver::MemoryPressure pressure) { |
| 262 if (pressure > current_memory_pressure_) |
| 263 OnMemoryPressureIncreased(); |
| 244 current_memory_pressure_ = pressure; | 264 current_memory_pressure_ = pressure; |
| 245 ManageResource(); | 265 ManageResource(); |
| 246 } | 266 } |
| 247 | 267 |
| 248 ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() { | 268 ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() { |
| 249 return delegate_.get(); | 269 return delegate_.get(); |
| 250 } | 270 } |
| 251 | 271 |
| 252 void ResourceManagerImpl::ManageResource() { | 272 void ResourceManagerImpl::ManageResource() { |
| 253 // If there is none or only one app running we cannot do anything. | 273 // If there is none or only one app running we cannot do anything. |
| 254 if (activity_list_.size() <= 1U) | 274 if (activity_list_.size() <= 1U) |
| 255 return; | 275 return; |
| 256 | 276 |
| 257 if (pause_) { | 277 if (pause_) { |
| 258 queued_command_ = true; | 278 queued_command_ = true; |
| 259 return; | 279 return; |
| 260 } | 280 } |
| 261 | 281 |
| 262 // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis | 282 // Check that the visibility of items is properly set. Note that this might |
| 263 // and running applications into account. For this first patch we only do a | 283 // already trigger a release of resources. If this happens, |
| 264 // very simple "floating window" algorithm which is surely not good enough. | 284 // AllowedToUnloadActivity() will return false. |
| 265 size_t max_running_activities = 5; | 285 UpdateVisibilityStates(); |
| 266 switch (current_memory_pressure_) { | |
| 267 case MEMORY_PRESSURE_UNKNOWN: | |
| 268 // If we do not know how much memory we have we assume that it must be a | |
| 269 // high consumption. | |
| 270 // Fallthrough. | |
| 271 case MEMORY_PRESSURE_HIGH: | |
| 272 max_running_activities = 5; | |
| 273 break; | |
| 274 case MEMORY_PRESSURE_CRITICAL: | |
| 275 max_running_activities = 0; | |
| 276 break; | |
| 277 case MEMORY_PRESSURE_MODERATE: | |
| 278 max_running_activities = 7; | |
| 279 break; | |
| 280 case MEMORY_PRESSURE_LOW: | |
| 281 // This doesn't really matter. We do not change anything but turning | |
| 282 // activities visible. | |
| 283 max_running_activities = 10000; | |
| 284 break; | |
| 285 } | |
| 286 | 286 |
| 287 // Since resource deallocation takes time, we avoid to release more resources |
| 288 // in short succession. Note that we come here periodically and if one call |
| 289 // is not triggering an unload, the next one will. |
| 290 if (AllowedToUnloadActivity()) |
| 291 TryToUnloadAnActivity(); |
| 292 } |
| 293 |
| 294 void ResourceManagerImpl::UpdateVisibilityStates() { |
| 287 // The first n activities should be treated as "visible", means they updated | 295 // The first n activities should be treated as "visible", means they updated |
| 288 // in overview mode and will keep their layer resources for faster switch | 296 // in overview mode and will keep their layer resources for faster switch |
| 289 // times. Usually we use |kMaxVisibleActivities| items, but when the memory | 297 // times. Usually we use |kMaxVisibleActivities| items, but when the memory |
| 290 // pressure gets critical we only hold as many as are really visible. | 298 // pressure gets critical we only hold as many as are really visible. |
| 291 size_t max_activities = kMaxVisibleActivities; | 299 size_t max_activities = kMaxVisibleActivities; |
| 292 if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) | 300 if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) |
| 293 max_activities = 1 + (in_splitview_mode_ ? 1 : 0); | 301 max_activities = in_split_view_mode_ ? 2 : 1; |
| 294 | 302 |
| 295 // Restart and / or bail if the order of activities changes due to our calls. | 303 // Restart and / or bail if the order of activities changes due to our calls. |
| 296 activity_order_changed_ = false; | 304 activity_order_changed_ = false; |
| 297 | 305 |
| 298 // Change the visibility of our activities in a pre-processing step. This is | 306 // Change the visibility of our activities in a pre-processing step. This is |
| 299 // required since it might change the order/number of activities. | 307 // required since it might change the order/number of activities. |
| 300 size_t index = 0; | 308 size_t index = 0; |
| 301 while (index < activity_list_.size()) { | 309 while (index < activity_list_.size()) { |
| 302 Activity* activity = activity_list_[index]; | 310 Activity* activity = activity_list_[index]; |
| 303 Activity::ActivityState state = activity->GetCurrentState(); | 311 Activity::ActivityState state = activity->GetCurrentState(); |
| 304 | 312 |
| 305 // The first |kMaxVisibleActivities| entries should be visible, all others | 313 // The first |kMaxVisibleActivities| entries should be visible, all others |
| 306 // invisible or at a lower activity state. | 314 // invisible or at a lower activity state. |
| 307 if (index < max_activities || | 315 if (index < max_activities || |
| 308 (state == Activity::ACTIVITY_INVISIBLE || | 316 (state == Activity::ACTIVITY_INVISIBLE || |
| 309 state == Activity::ACTIVITY_VISIBLE)) { | 317 state == Activity::ACTIVITY_VISIBLE)) { |
| 310 Activity::ActivityState visiblity_state = | 318 Activity::ActivityState visiblity_state = |
| 311 index < max_activities ? Activity::ACTIVITY_VISIBLE : | 319 index < max_activities ? Activity::ACTIVITY_VISIBLE : |
| 312 Activity::ACTIVITY_INVISIBLE; | 320 Activity::ACTIVITY_INVISIBLE; |
| 313 // Only change the state when it changes. Note that when the memory | 321 // Only change the state when it changes. Note that when the memory |
| 314 // pressure is critical, only the primary activities (1 or 2) are made | 322 // pressure is critical, only the primary activities (1 or 2) are made |
| 315 // visible. Furthermore, in relaxed mode we only want to turn visible, | 323 // visible. Furthermore, in relaxed mode we only want to turn visible, |
| 316 // never invisible. | 324 // never invisible. |
| 317 if (visiblity_state != state && | 325 if (visiblity_state != state && |
| 318 (current_memory_pressure_ != MEMORY_PRESSURE_LOW || | 326 (current_memory_pressure_ != MEMORY_PRESSURE_LOW || |
| 319 visiblity_state == Activity::ACTIVITY_VISIBLE)) { | 327 visiblity_state == Activity::ACTIVITY_VISIBLE)) { |
| 320 activity->SetCurrentState(visiblity_state); | 328 activity->SetCurrentState(visiblity_state); |
| 321 // If we turned an activity invisible, we should not at the same time | 329 // If we turned an activity invisible, we are already releasing memory |
| 322 // throw an activity out of memory. Thus we grant one more invisible | 330 // and can hold off releasing more for now. |
| 323 // Activity in that case. | |
| 324 if (visiblity_state == Activity::ACTIVITY_INVISIBLE) | 331 if (visiblity_state == Activity::ACTIVITY_INVISIBLE) |
| 325 max_running_activities++; | 332 OnResourcesReleased(); |
| 326 } | 333 } |
| 327 } | 334 } |
| 328 | 335 |
| 329 // See which index we should handle next. | 336 // See which index we should handle next. |
| 330 if (activity_order_changed_) { | 337 if (activity_order_changed_) { |
| 331 activity_order_changed_ = false; | 338 activity_order_changed_ = false; |
| 332 index = 0; | 339 index = 0; |
| 333 } else { | 340 } else { |
| 334 ++index; | 341 ++index; |
| 335 } | 342 } |
| 336 } | 343 } |
| 344 } |
| 337 | 345 |
| 338 // If there is only a low memory pressure, or our last call to release | 346 void ResourceManagerImpl::TryToUnloadAnActivity() { |
| 339 // resources cannot have had any impact yet, we return. | 347 // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis |
| 340 // TODO(skuhne): The upper part of this function bumps up the state (to | 348 // and running applications into account. For this first patch we only do a |
| 341 // visible) and the lower part might unload one. Going forward this algorithm | 349 // very simple "floating window" algorithm which is surely not good enough. |
| 342 // will change significantly and when it does we might want to break this into | 350 size_t max_running_activities = 5; |
| 343 // two separate pieces. | 351 switch (current_memory_pressure_) { |
| 344 if (current_memory_pressure_ == MEMORY_PRESSURE_LOW || | 352 case MEMORY_PRESSURE_UNKNOWN: |
| 345 base::Time::Now() < next_resource_management_time_) | 353 // If we do not know how much memory we have we assume that it must be a |
| 346 return; | 354 // high consumption. |
| 347 // Do not release too many activities in short succession since it takes time | 355 // Fallthrough. |
| 348 // to release resources. As such wait the memory pressure interval before the | 356 case MEMORY_PRESSURE_HIGH: |
| 349 // next call. | 357 max_running_activities = 5; |
| 350 next_resource_management_time_ = base::Time::Now() + | 358 break; |
| 351 wait_time_for_resource_deallocation_; | 359 case MEMORY_PRESSURE_CRITICAL: |
| 360 max_running_activities = 0; |
| 361 break; |
| 362 case MEMORY_PRESSURE_MODERATE: |
| 363 max_running_activities = 7; |
| 364 break; |
| 365 case MEMORY_PRESSURE_LOW: |
| 366 NOTREACHED(); |
| 367 return; |
| 368 } |
| 352 | 369 |
| 353 // Check if/which activity we want to unload. | 370 // Check if / which activity we want to unload. |
| 354 Activity* oldest_media_activity = NULL; | 371 Activity* oldest_media_activity = NULL; |
| 355 std::vector<Activity*> unloadable_activities; | 372 std::vector<Activity*> unloadable_activities; |
| 356 for (std::vector<Activity*>::iterator it = activity_list_.begin(); | 373 for (std::vector<Activity*>::iterator it = activity_list_.begin(); |
| 357 it != activity_list_.end(); ++it) { | 374 it != activity_list_.end(); ++it) { |
| 358 Activity::ActivityState state = (*it)->GetCurrentState(); | 375 Activity::ActivityState state = (*it)->GetCurrentState(); |
| 359 // The activity should neither be unloaded nor visible. | 376 // The activity should neither be unloaded nor visible. |
| 360 if (state != Activity::ACTIVITY_UNLOADED && | 377 if (state != Activity::ACTIVITY_UNLOADED && |
| 361 state != Activity::ACTIVITY_VISIBLE) { | 378 state != Activity::ACTIVITY_VISIBLE) { |
| 362 if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { | 379 if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { |
| 363 // Does not play media - so we can unload this immediately. | 380 // Does not play media - so we can unload this immediately. |
| 364 unloadable_activities.push_back(*it); | 381 unloadable_activities.push_back(*it); |
| 365 } else { | 382 } else { |
| 366 oldest_media_activity = *it; | 383 oldest_media_activity = *it; |
| 367 } | 384 } |
| 368 } | 385 } |
| 369 } | 386 } |
| 370 | 387 |
| 371 if (unloadable_activities.size() > max_running_activities) { | 388 if (unloadable_activities.size() > max_running_activities) { |
| 389 OnResourcesReleased(); |
| 372 unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED); | 390 unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED); |
| 373 return; | 391 return; |
| 374 } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) { | 392 } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) { |
| 375 if (oldest_media_activity) { | 393 if (oldest_media_activity) { |
| 394 OnResourcesReleased(); |
| 376 oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); | 395 oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); |
| 377 LOG(WARNING) << "Unloading item to releave critical memory pressure"; | 396 LOG(WARNING) << "Unloading item to releave critical memory pressure"; |
| 378 return; | 397 return; |
| 379 } | 398 } |
| 380 LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory."; | 399 LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory."; |
| 381 return; | 400 return; |
| 382 } | 401 } |
| 383 | 402 |
| 384 if (current_memory_pressure_ != MEMORY_PRESSURE_UNKNOWN) { | 403 if (current_memory_pressure_ != MEMORY_PRESSURE_UNKNOWN) { |
| 385 // Only show this warning when the memory pressure is actually known. This | 404 // Only show this warning when the memory pressure is actually known. This |
| (...skipping 29 matching lines...) Expand all Loading... |
| 415 } | 434 } |
| 416 } | 435 } |
| 417 // At this point the old list should be empty and we can swap the lists. | 436 // At this point the old list should be empty and we can swap the lists. |
| 418 DCHECK(!activity_list_.size()); | 437 DCHECK(!activity_list_.size()); |
| 419 activity_list_ = new_activity_list; | 438 activity_list_ = new_activity_list; |
| 420 | 439 |
| 421 // Remember that the activity order has changed. | 440 // Remember that the activity order has changed. |
| 422 activity_order_changed_ = true; | 441 activity_order_changed_ = true; |
| 423 } | 442 } |
| 424 | 443 |
| 444 void ResourceManagerImpl::OnResourcesReleased() { |
| 445 // Do not release too many activities in short succession since it takes time |
| 446 // to release resources. As such wait the memory pressure interval before the |
| 447 // next call. |
| 448 next_resource_management_time_ = base::Time::Now() + |
| 449 wait_time_for_resource_deallocation_; |
| 450 } |
| 451 |
| 452 void ResourceManagerImpl::OnMemoryPressureIncreased() { |
| 453 // By setting the timer to Now, the next call will immediately be performed. |
| 454 next_resource_management_time_ = base::Time::Now(); |
| 455 } |
| 456 |
| 457 bool ResourceManagerImpl::AllowedToUnloadActivity() { |
| 458 return current_memory_pressure_ != MEMORY_PRESSURE_LOW && |
| 459 base::Time::Now() >= next_resource_management_time_; |
| 460 } |
| 461 |
| 425 // static | 462 // static |
| 426 void ResourceManager::Create() { | 463 void ResourceManager::Create() { |
| 427 DCHECK(!instance); | 464 DCHECK(!instance); |
| 428 instance = new ResourceManagerImpl( | 465 instance = new ResourceManagerImpl( |
| 429 ResourceManagerDelegate::CreateResourceManagerDelegate()); | 466 ResourceManagerDelegate::CreateResourceManagerDelegate()); |
| 430 } | 467 } |
| 431 | 468 |
| 432 // static | 469 // static |
| 433 ResourceManager* ResourceManager::Get() { | 470 ResourceManager* ResourceManager::Get() { |
| 434 return instance; | 471 return instance; |
| 435 } | 472 } |
| 436 | 473 |
| 437 // static | 474 // static |
| 438 void ResourceManager::Shutdown() { | 475 void ResourceManager::Shutdown() { |
| 439 DCHECK(instance); | 476 DCHECK(instance); |
| 440 delete instance; | 477 delete instance; |
| 441 instance = NULL; | 478 instance = NULL; |
| 442 } | 479 } |
| 443 | 480 |
| 444 ResourceManager::ResourceManager() {} | 481 ResourceManager::ResourceManager() {} |
| 445 | 482 |
| 446 ResourceManager::~ResourceManager() { | 483 ResourceManager::~ResourceManager() { |
| 447 DCHECK(instance); | 484 DCHECK(instance); |
| 448 instance = NULL; | 485 instance = NULL; |
| 449 } | 486 } |
| 450 | 487 |
| 451 } // namespace athena | 488 } // namespace athena |
| OLD | NEW |