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.
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/athena_test_base.h"
11 #include "athena/wm/public/window_manager.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "ui/gfx/image/image_skia.h"
14 #include "ui/views/view.h"
15 #include "ui/views/widget/widget.h"
22 // A dummy test app activity which works without content / ShellAppWindow.
23 class TestActivity
: public Activity
,
24 public ActivityViewModel
{
26 TestActivity(std::string title
) : title_(base::UTF8ToUTF16(title
)),
27 view_(new views::View()),
28 current_state_(ACTIVITY_UNLOADED
),
29 media_state_(ACTIVITY_MEDIA_STATE_NONE
),
30 is_visible_(false) {};
31 virtual ~TestActivity() {}
33 void set_media_state(ActivityMediaState media_state
) {
34 media_state_
= media_state
;
36 void set_visible(bool visible
) { is_visible_
= visible
; }
38 // Activity overrides:
39 virtual ActivityViewModel
* GetActivityViewModel() OVERRIDE
{ return this; }
40 virtual void SetCurrentState(ActivityState state
) OVERRIDE
{
41 current_state_
= state
;
43 virtual ActivityState
GetCurrentState() OVERRIDE
{ return current_state_
; }
44 virtual bool IsVisible() OVERRIDE
{ return is_visible_
; }
45 virtual ActivityMediaState
GetMediaState() OVERRIDE
{ return media_state_
; }
46 virtual aura::Window
* GetWindow() OVERRIDE
{
47 return view_
->GetWidget()->GetNativeWindow();
50 // ActivityViewModel overrides:
51 virtual void Init() OVERRIDE
{}
52 virtual SkColor
GetRepresentativeColor() const OVERRIDE
{ return 0; }
53 virtual base::string16
GetTitle() const OVERRIDE
{ return title_
; }
54 virtual gfx::ImageSkia
GetIcon() const OVERRIDE
{ return gfx::ImageSkia(); }
55 virtual bool UsesFrame() const OVERRIDE
{ return true; }
56 virtual views::View
* GetContentsView() OVERRIDE
{ return view_
; }
57 virtual views::Widget
* CreateWidget() OVERRIDE
{ return NULL
; }
58 virtual void CreateOverviewModeImage() OVERRIDE
{}
59 virtual gfx::ImageSkia
GetOverviewModeImage() OVERRIDE
{ return image_
; }
60 virtual void PrepareContentsForOverview() OVERRIDE
{}
61 virtual void ResetContentsView() OVERRIDE
{}
64 // The presentation values.
65 const base::string16 title_
;
66 gfx::ImageSkia image_
;
68 // The associated view.
72 ActivityState current_state_
;
74 // The current media state.
75 ActivityMediaState media_state_
;
77 // Returns if it is visible or not.
80 DISALLOW_COPY_AND_ASSIGN(TestActivity
);
86 class ResourceManagerTest
: public AthenaTestBase
{
88 ResourceManagerTest() {}
89 virtual ~ResourceManagerTest() {}
91 virtual void TearDown() OVERRIDE
{
92 while (!activity_list_
.empty())
93 DeleteActivity(activity_list_
[0]);
94 AthenaTestBase::TearDown();
97 TestActivity
* CreateActivity(const std::string
& title
) {
98 TestActivity
* activity
= new TestActivity(title
);
99 ActivityManager::Get()->AddActivity(activity
);
100 activity
->SetCurrentState(Activity::ACTIVITY_INVISIBLE
);
101 activity_list_
.push_back(activity
);
105 void DeleteActivity(Activity
* activity
) {
106 Activity::Delete(activity
);
107 RunAllPendingInMessageLoop();
108 std::vector
<TestActivity
*>::iterator it
= std::find(activity_list_
.begin(),
109 activity_list_
.end(),
111 DCHECK(it
!= activity_list_
.end());
112 activity_list_
.erase(it
);
116 std::vector
<TestActivity
*> activity_list_
;
118 DISALLOW_COPY_AND_ASSIGN(ResourceManagerTest
);
121 // Only creates and destroys it to see that the system gets properly shut down.
122 TEST_F(ResourceManagerTest
, SimpleTest
) {
125 // Test that we release an activity when the memory pressure goes critical.
126 TEST_F(ResourceManagerTest
, OnCriticalWillUnloadOneActivity
) {
127 // Create a few dummy activities in the reverse order as we need them.
128 TestActivity
* app_unloadable2
= CreateActivity("unloadable2");
129 TestActivity
* app_unloadable1
= CreateActivity("unloadable1");
130 TestActivity
* app_visible
= CreateActivity("visible");
131 app_visible
->set_visible(true);
132 app_unloadable1
->set_visible(false);
133 app_unloadable2
->set_visible(false);
135 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
136 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_unloadable1
->GetCurrentState());
137 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_unloadable2
->GetCurrentState());
139 // Call the resource manager and say we are in a critical memory condition.
140 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
141 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
142 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
143 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_unloadable1
->GetCurrentState());
144 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable2
->GetCurrentState());
146 // Calling it a second time will release the second app.
147 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
148 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
149 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
150 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable1
->GetCurrentState());
151 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable2
->GetCurrentState());
153 // Calling it once more will change nothing.
154 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
155 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
156 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
157 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable1
->GetCurrentState());
158 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable2
->GetCurrentState());
161 // Test that media playing activities only get unloaded if there is no other
163 TEST_F(ResourceManagerTest
, OnCriticalMediaHandling
) {
164 // Create a few dummy activities in the reverse order as we need them.
165 TestActivity
* app_media_locked2
= CreateActivity("medialocked2");
166 TestActivity
* app_unloadable
= CreateActivity("unloadable2");
167 TestActivity
* app_media_locked1
= CreateActivity("medialocked1");
168 TestActivity
* app_visible
= CreateActivity("visible");
169 app_visible
->set_visible(true);
170 app_unloadable
->set_visible(false);
171 app_media_locked1
->set_visible(false);
172 app_media_locked2
->set_visible(false);
174 app_media_locked1
->set_media_state(
175 Activity::ACTIVITY_MEDIA_STATE_AUDIO_PLAYING
);
176 app_media_locked2
->set_media_state(Activity::ACTIVITY_MEDIA_STATE_RECORDING
);
178 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
179 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_media_locked1
->GetCurrentState());
180 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_unloadable
->GetCurrentState());
181 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_media_locked2
->GetCurrentState());
183 // Calling it with a critical situation first, it will release the non media
185 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
186 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
187 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
188 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_media_locked1
->GetCurrentState());
189 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable
->GetCurrentState());
190 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_media_locked2
->GetCurrentState());
192 // Calling it the second time, the oldest media playing activity will get
194 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
195 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
196 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
197 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_media_locked1
->GetCurrentState());
198 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable
->GetCurrentState());
199 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_media_locked2
->GetCurrentState());
201 // Calling it the third time, the oldest media playing activity will get
203 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
204 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
205 DCHECK_NE(Activity::ACTIVITY_UNLOADED
, app_visible
->GetCurrentState());
206 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_media_locked1
->GetCurrentState());
207 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_unloadable
->GetCurrentState());
208 DCHECK_EQ(Activity::ACTIVITY_UNLOADED
, app_media_locked2
->GetCurrentState());
211 // Test the visibility of items.
212 TEST_F(ResourceManagerTest
, VisibilityChanges
) {
213 // Create a few dummy activities in the reverse order as we need them.
214 TestActivity
* app4
= CreateActivity("app4");
215 TestActivity
* app3
= CreateActivity("app3");
216 TestActivity
* app2
= CreateActivity("app2");
217 TestActivity
* app1
= CreateActivity("app1");
218 app1
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
219 app2
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
220 app3
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
221 app4
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
223 // Applying low resource pressure should keep everything as is.
224 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
225 MemoryPressureObserver::MEMORY_PRESSURE_LOW
);
226 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app1
->GetCurrentState());
227 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app2
->GetCurrentState());
228 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app3
->GetCurrentState());
229 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app4
->GetCurrentState());
231 // Applying moderate resource pressure we should see 3 visible activities.
232 // This is testing an internal algorithm constant, but for the time being
233 // this should suffice.
234 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
235 MemoryPressureObserver::MEMORY_PRESSURE_MODERATE
);
236 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app1
->GetCurrentState());
237 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app2
->GetCurrentState());
238 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app3
->GetCurrentState());
239 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE
, app4
->GetCurrentState());
241 // Applying higher pressure should get rid of everything unneeded.
242 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
243 MemoryPressureObserver::MEMORY_PRESSURE_CRITICAL
);
244 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app1
->GetCurrentState());
245 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE
, app2
->GetCurrentState());
246 EXPECT_EQ(Activity::ACTIVITY_INVISIBLE
, app3
->GetCurrentState());
247 // Note: This might very well be unloaded with this memory pressure.
248 EXPECT_NE(Activity::ACTIVITY_VISIBLE
, app4
->GetCurrentState());
250 // Once the split view mode gets turned on, more windows should become
252 WindowManager::GetInstance()->ToggleSplitViewForTest();
253 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app1
->GetCurrentState());
254 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app2
->GetCurrentState());
255 EXPECT_NE(Activity::ACTIVITY_VISIBLE
, app3
->GetCurrentState());
256 EXPECT_NE(Activity::ACTIVITY_VISIBLE
, app4
->GetCurrentState());
258 // Going back to a relaxed memory pressure should reload the old activities.
259 ResourceManager::Get()->SetMemoryPressureAndStopMonitoring(
260 MemoryPressureObserver::MEMORY_PRESSURE_LOW
);
261 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app1
->GetCurrentState());
262 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app2
->GetCurrentState());
263 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app3
->GetCurrentState());
264 EXPECT_NE(Activity::ACTIVITY_INVISIBLE
, app4
->GetCurrentState());
268 } // namespace athena