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 |