OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "athena/activity/public/activity.h" | |
6 #include "athena/activity/public/activity_manager.h" | |
7 #include "athena/activity/public/activity_view_model.h" | |
8 #include "athena/resource_manager/memory_pressure_notifier.h" | |
9 #include "athena/resource_manager/public/resource_manager.h" | |
10 #include "athena/test/base/athena_test_base.h" | |
11 #include "athena/test/base/sample_activity.h" | |
12 #include "athena/wm/public/window_manager.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "ui/gfx/image/image_skia.h" | |
15 #include "ui/views/view.h" | |
16 #include "ui/views/widget/widget.h" | |
17 | |
18 namespace athena { | |
19 namespace test { | |
20 | |
21 namespace { | |
22 | |
23 // A dummy test app activity which works without content / ShellAppWindow. | |
24 class TestActivity : public SampleActivity { | |
25 public: | |
26 explicit TestActivity(const std::string& title) | |
27 : SampleActivity(0, 0, base::UTF8ToUTF16(title)), | |
28 media_state_(ACTIVITY_MEDIA_STATE_NONE), | |
29 is_visible_(false) {} | |
30 ~TestActivity() override {} | |
31 | |
32 void set_media_state(ActivityMediaState media_state) { | |
33 media_state_ = media_state; | |
34 } | |
35 void set_visible(bool visible) { is_visible_ = visible; } | |
36 | |
37 // Activity overrides: | |
38 virtual bool IsVisible() override { return is_visible_; } | |
39 virtual ActivityMediaState GetMediaState() override { return media_state_; } | |
40 | |
41 private: | |
42 // The current media state. | |
43 ActivityMediaState media_state_; | |
44 | |
45 // Returns if it is visible or not. | |
46 bool is_visible_; | |
47 | |
48 DISALLOW_COPY_AND_ASSIGN(TestActivity); | |
49 }; | |
50 | |
51 } // namespace | |
52 | |
53 // Our testing base. | |
54 class ResourceManagerTest : public AthenaTestBase { | |
55 public: | |
56 ResourceManagerTest() {} | |
57 ~ResourceManagerTest() override {} | |
58 | |
59 virtual void SetUp() override { | |
60 AthenaTestBase::SetUp(); | |
61 // Override the delay to be instantaneous. | |
62 ResourceManager::Get()->SetWaitTimeBetweenResourceManageCalls(0); | |
63 } | |
64 virtual void TearDown() override { | |
65 while (!activity_list_.empty()) | |
66 DeleteActivity(activity_list_[0]); | |
67 AthenaTestBase::TearDown(); | |
68 } | |
69 | |
70 TestActivity* CreateActivity(const std::string& title) { | |
71 TestActivity* activity = new TestActivity(title); | |
72 ActivityManager::Get()->AddActivity(activity); | |
73 activity->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
74 activity_list_.push_back(activity); | |
75 return activity; | |
76 } | |
77 | |
78 void DeleteActivity(Activity* activity) { | |
79 Activity::Delete(activity); | |
80 RunAllPendingInMessageLoop(); | |
81 std::vector<TestActivity*>::iterator it = std::find(activity_list_.begin(), | |
82 activity_list_.end(), | |
83 activity); | |
84 DCHECK(it != activity_list_.end()); | |
85 activity_list_.erase(it); | |
86 } | |
87 | |
88 private: | |
89 std::vector<TestActivity*> activity_list_; | |
90 | |
91 DISALLOW_COPY_AND_ASSIGN(ResourceManagerTest); | |
92 }; | |
93 | |
94 // Only creates and destroys it to see that the system gets properly shut down. | |
95 TEST_F(ResourceManagerTest, SimpleTest) { | |
96 } | |
97 | |
98 // Test that we release an activity when the memory pressure goes critical. | |
99 TEST_F(ResourceManagerTest, OnCriticalWillUnloadOneActivity) { | |
100 // Create a few dummy activities in the reverse order as we need them. | |
101 TestActivity* app_unloadable2 = CreateActivity("unloadable2"); | |
102 TestActivity* app_unloadable1 = CreateActivity("unloadable1"); | |
103 TestActivity* app_visible = CreateActivity("visible"); | |
104 app_visible->set_visible(true); | |
105 app_unloadable1->set_visible(false); | |
106 app_unloadable2->set_visible(false); | |
107 | |
108 // Set the initial visibility states. | |
109 app_visible->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
110 app_unloadable1->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
111 app_unloadable2->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
112 | |
113 // Call the resource manager and say we are in a critical memory condition. | |
114 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
115 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
116 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
117 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_unloadable1->GetCurrentState()); | |
118 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable2->GetCurrentState()); | |
119 | |
120 // Calling it a second time will release the second app. | |
121 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
122 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
123 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
124 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable1->GetCurrentState()); | |
125 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable2->GetCurrentState()); | |
126 | |
127 // Calling it once more will change nothing. | |
128 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
129 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
130 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
131 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable1->GetCurrentState()); | |
132 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable2->GetCurrentState()); | |
133 } | |
134 | |
135 // Test that media playing activities only get unloaded if there is no other | |
136 // way. | |
137 TEST_F(ResourceManagerTest, OnCriticalMediaHandling) { | |
138 // Create a few dummy activities in the reverse order as we need them. | |
139 TestActivity* app_media_locked2 = CreateActivity("medialocked2"); | |
140 TestActivity* app_unloadable = CreateActivity("unloadable2"); | |
141 TestActivity* app_media_locked1 = CreateActivity("medialocked1"); | |
142 TestActivity* app_visible = CreateActivity("visible"); | |
143 app_visible->set_visible(true); | |
144 app_unloadable->set_visible(false); | |
145 app_media_locked1->set_visible(false); | |
146 app_media_locked2->set_visible(false); | |
147 | |
148 app_media_locked1->set_media_state( | |
149 Activity::ACTIVITY_MEDIA_STATE_AUDIO_PLAYING); | |
150 app_media_locked2->set_media_state(Activity::ACTIVITY_MEDIA_STATE_RECORDING); | |
151 | |
152 // Set the initial visibility states. | |
153 app_visible->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
154 app_media_locked1->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
155 app_unloadable->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
156 app_media_locked2->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
157 | |
158 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
159 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_media_locked1->GetCurrentState()); | |
160 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_unloadable->GetCurrentState()); | |
161 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_media_locked2->GetCurrentState()); | |
162 | |
163 // Calling it with a critical situation first, it will release the non media | |
164 // locked app. | |
165 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
166 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
167 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
168 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_media_locked1->GetCurrentState()); | |
169 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable->GetCurrentState()); | |
170 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_media_locked2->GetCurrentState()); | |
171 | |
172 // Calling it the second time, the oldest media playing activity will get | |
173 // unloaded. | |
174 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
175 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
176 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
177 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_media_locked1->GetCurrentState()); | |
178 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable->GetCurrentState()); | |
179 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_media_locked2->GetCurrentState()); | |
180 | |
181 // Calling it the third time, the oldest media playing activity will get | |
182 // unloaded. | |
183 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
184 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
185 DCHECK_NE(Activity::ACTIVITY_UNLOADED, app_visible->GetCurrentState()); | |
186 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_media_locked1->GetCurrentState()); | |
187 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_unloadable->GetCurrentState()); | |
188 DCHECK_EQ(Activity::ACTIVITY_UNLOADED, app_media_locked2->GetCurrentState()); | |
189 } | |
190 | |
191 // Test the visibility of items. | |
192 TEST_F(ResourceManagerTest, VisibilityChanges) { | |
193 // Create a few dummy activities in the reverse order as we need them. | |
194 TestActivity* app4 = CreateActivity("app4"); | |
195 TestActivity* app3 = CreateActivity("app3"); | |
196 TestActivity* app2 = CreateActivity("app2"); | |
197 TestActivity* app1 = CreateActivity("app1"); | |
198 app1->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
199 app2->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
200 app3->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
201 app4->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
202 | |
203 // Applying low resource pressure should keep everything as is. | |
204 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
205 ResourceManager::MEMORY_PRESSURE_LOW); | |
206 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
207 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app2->GetCurrentState()); | |
208 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app3->GetCurrentState()); | |
209 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app4->GetCurrentState()); | |
210 | |
211 // Applying moderate resource pressure we should see 3 visible activities. | |
212 // This is testing an internal algorithm constant, but for the time being | |
213 // this should suffice. | |
214 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
215 ResourceManager::MEMORY_PRESSURE_MODERATE); | |
216 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
217 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app2->GetCurrentState()); | |
218 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app3->GetCurrentState()); | |
219 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app4->GetCurrentState()); | |
220 | |
221 // Applying higher pressure should get rid of everything unneeded. | |
222 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
223 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
224 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
225 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
226 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
227 // Note: This might very well be unloaded with this memory pressure. | |
228 EXPECT_NE(Activity::ACTIVITY_VISIBLE, app4->GetCurrentState()); | |
229 | |
230 // Once the split view mode gets turned on, more windows should become | |
231 // visible. | |
232 WindowManager::Get()->ToggleSplitViewForTest(); | |
233 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
234 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app2->GetCurrentState()); | |
235 EXPECT_NE(Activity::ACTIVITY_VISIBLE, app3->GetCurrentState()); | |
236 EXPECT_NE(Activity::ACTIVITY_VISIBLE, app4->GetCurrentState()); | |
237 | |
238 // Going back to a relaxed memory pressure should reload the old activities. | |
239 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
240 ResourceManager::MEMORY_PRESSURE_LOW); | |
241 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
242 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app2->GetCurrentState()); | |
243 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app3->GetCurrentState()); | |
244 EXPECT_NE(Activity::ACTIVITY_INVISIBLE, app4->GetCurrentState()); | |
245 } | |
246 | |
247 // Make sure that an activity which got just reduced from visible to invisible, | |
248 // does not get thrown out of memory in the same step. | |
249 TEST_F(ResourceManagerTest, NoUnloadFromVisible) { | |
250 // The timeout override in milliseconds. | |
251 const int kTimeoutOverrideInMs = 20; | |
252 // Tell the resource manager to wait for 20ms between calls. | |
253 ResourceManager::Get()->SetWaitTimeBetweenResourceManageCalls( | |
254 kTimeoutOverrideInMs); | |
255 | |
256 // Create a few dummy activities in the reverse order as we need them. | |
257 TestActivity* app2 = CreateActivity("app2"); | |
258 TestActivity* app1 = CreateActivity("app1"); | |
259 app1->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
260 app2->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
261 | |
262 // Applying low resource pressure should turn one item invisible. | |
263 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
264 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
265 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
266 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
267 | |
268 // Trying to apply the memory pressure again does not do anything. | |
269 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
270 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
271 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
272 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
273 | |
274 // Waiting and applying the pressure again should unload it. | |
275 usleep(kTimeoutOverrideInMs * 1000); | |
276 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
277 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
278 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
279 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, app2->GetCurrentState()); | |
280 } | |
281 | |
282 // Make sure that ActivityVisibility changes will be updated instantaneously | |
283 // when the ResourceManager is called for operation. | |
284 TEST_F(ResourceManagerTest, VisibilityChangeIsInstantaneous) { | |
285 // Create a few dummy activities in the reverse order as we need them. | |
286 TestActivity* app3 = CreateActivity("app3"); | |
287 TestActivity* app2 = CreateActivity("app2"); | |
288 TestActivity* app1 = CreateActivity("app1"); | |
289 app1->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
290 app2->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
291 app3->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
292 | |
293 // Tell the resource manager to wait for a long time between calls. | |
294 ResourceManager::Get()->SetWaitTimeBetweenResourceManageCalls(1000); | |
295 | |
296 // Applying higher pressure should get rid of everything unneeded. | |
297 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
298 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
299 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
300 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
301 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
302 | |
303 // Setting now one window visible again and call a second time should | |
304 // immediately change the state again. | |
305 app2->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
306 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
307 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app2->GetCurrentState()); | |
308 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
309 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
310 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
311 | |
312 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
313 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
314 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
315 } | |
316 | |
317 // Make sure that a timeout has to be reached before another resource managing | |
318 // operations can be performed. | |
319 TEST_F(ResourceManagerTest, ResourceChangeDelayed) { | |
320 // Create a few dummy activities in the reverse order as we need them. | |
321 TestActivity* app4 = CreateActivity("app4"); | |
322 TestActivity* app3 = CreateActivity("app3"); | |
323 TestActivity* app2 = CreateActivity("app2"); | |
324 TestActivity* app1 = CreateActivity("app1"); | |
325 app1->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
326 app2->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
327 app3->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
328 app4->SetCurrentState(Activity::ACTIVITY_INVISIBLE); | |
329 | |
330 // The timeout override in milliseconds. | |
331 const int kTimeoutOverrideInMs = 20; | |
332 // Tell the resource manager to wait for 20ms between calls. | |
333 ResourceManager::Get()->SetWaitTimeBetweenResourceManageCalls( | |
334 kTimeoutOverrideInMs); | |
335 // Applying higher pressure should get unload the oldest activity. | |
336 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
337 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
338 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
339 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
340 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
341 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, app4->GetCurrentState()); | |
342 // Trying to apply the resource pressure again within the timeout time should | |
343 // not trigger any operation. | |
344 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
345 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
346 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
347 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
348 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app3->GetCurrentState()); | |
349 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, app4->GetCurrentState()); | |
350 | |
351 // Passing the timeout however should allow for another call. | |
352 usleep(kTimeoutOverrideInMs * 1000); | |
353 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring( | |
354 ResourceManager::MEMORY_PRESSURE_CRITICAL); | |
355 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app1->GetCurrentState()); | |
356 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE, app2->GetCurrentState()); | |
357 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, app3->GetCurrentState()); | |
358 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, app4->GetCurrentState()); | |
359 } | |
360 | |
361 } // namespace test | |
362 } // namespace athena | |
OLD | NEW |