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.
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/display/chromeos/display_layout_manager.h"
10 #include "ui/display/chromeos/test/action_logger_util.h"
11 #include "ui/display/chromeos/test/test_display_snapshot.h"
12 #include "ui/display/chromeos/test/test_native_display_delegate.h"
13 #include "ui/display/chromeos/update_display_configuration_task.h"
20 class TestSoftwareMirroringController
21 : public DisplayConfigurator::SoftwareMirroringController
{
23 TestSoftwareMirroringController() : is_enabled_(false) {}
24 ~TestSoftwareMirroringController() override
{}
26 // DisplayConfigurator::SoftwareMirroringController:
27 void SetSoftwareMirroring(bool enabled
) override
{ is_enabled_
= enabled
; }
28 bool SoftwareMirroringEnabled() const override
{ return is_enabled_
; }
33 DISALLOW_COPY_AND_ASSIGN(TestSoftwareMirroringController
);
36 class TestDisplayLayoutManager
: public DisplayLayoutManager
{
38 TestDisplayLayoutManager()
39 : should_mirror_(true),
40 display_state_(MULTIPLE_DISPLAY_STATE_INVALID
),
41 power_state_(chromeos::DISPLAY_POWER_ALL_ON
) {}
42 ~TestDisplayLayoutManager() override
{}
44 void set_should_mirror(bool should_mirror
) { should_mirror_
= should_mirror
; }
46 void set_display_state(MultipleDisplayState state
) { display_state_
= state
; }
48 void set_power_state(chromeos::DisplayPowerState state
) {
52 void set_software_mirroring_controller(
53 scoped_ptr
<DisplayConfigurator::SoftwareMirroringController
>
54 software_mirroring_controller
) {
55 software_mirroring_controller_
= software_mirroring_controller
.Pass();
58 // DisplayConfigurator::DisplayLayoutManager:
59 DisplayConfigurator::SoftwareMirroringController
*
60 GetSoftwareMirroringController() const override
{
61 return software_mirroring_controller_
.get();
64 DisplayConfigurator::StateController
* GetStateController() const override
{
68 MultipleDisplayState
GetDisplayState() const override
{
69 return display_state_
;
72 chromeos::DisplayPowerState
GetPowerState() const override
{
76 bool GetDisplayLayout(const std::vector
<DisplaySnapshot
*>& displays
,
77 MultipleDisplayState new_display_state
,
78 chromeos::DisplayPowerState new_power_state
,
79 std::vector
<DisplayConfigureRequest
>* requests
,
80 gfx::Size
* framebuffer_size
) const override
{
82 for (DisplaySnapshot
* display
: displays
) {
83 const DisplayMode
* mode
= display
->native_mode();
84 if (new_display_state
== MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
)
85 mode
= should_mirror_
? FindMirrorMode(displays
) : nullptr;
90 if (new_power_state
== chromeos::DISPLAY_POWER_ALL_ON
) {
91 requests
->push_back(DisplayConfigureRequest(display
, mode
, origin
));
93 requests
->push_back(DisplayConfigureRequest(display
, nullptr, origin
));
96 if (new_display_state
!= MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
) {
97 origin
.Offset(0, mode
->size().height());
98 framebuffer_size
->SetToMax(gfx::Size(mode
->size().width(), origin
.y()));
100 *framebuffer_size
= mode
->size();
107 DisplayConfigurator::DisplayStateList
GetDisplayStates() const override
{
109 return DisplayConfigurator::DisplayStateList();
112 bool IsMirroring() const override
{
113 return display_state_
== MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
;
117 const DisplayMode
* FindMirrorMode(
118 const std::vector
<DisplaySnapshot
*>& displays
) const {
119 const DisplayMode
* mode
= displays
[0]->native_mode();
120 for (DisplaySnapshot
* display
: displays
) {
121 if (mode
->size().GetArea() > display
->native_mode()->size().GetArea())
122 mode
= display
->native_mode();
130 MultipleDisplayState display_state_
;
132 chromeos::DisplayPowerState power_state_
;
134 scoped_ptr
<DisplayConfigurator::SoftwareMirroringController
>
135 software_mirroring_controller_
;
137 DISALLOW_COPY_AND_ASSIGN(TestDisplayLayoutManager
);
140 class UpdateDisplayConfigurationTaskTest
: public testing::Test
{
142 UpdateDisplayConfigurationTaskTest()
144 small_mode_(gfx::Size(1366, 768), false, 60.0f
),
145 big_mode_(gfx::Size(2560, 1600), false, 60.0f
),
147 configuration_status_(false),
148 display_state_(MULTIPLE_DISPLAY_STATE_INVALID
),
149 power_state_(chromeos::DISPLAY_POWER_ALL_ON
) {
150 std::vector
<const DisplayMode
*> modes
;
151 modes
.push_back(&small_mode_
);
152 displays_
[0].set_current_mode(&small_mode_
);
153 displays_
[0].set_native_mode(&small_mode_
);
154 displays_
[0].set_modes(modes
);
155 displays_
[0].set_display_id(123);
157 modes
.push_back(&big_mode_
);
158 displays_
[1].set_current_mode(&big_mode_
);
159 displays_
[1].set_native_mode(&big_mode_
);
160 displays_
[1].set_modes(modes
);
161 displays_
[1].set_display_id(456);
163 ~UpdateDisplayConfigurationTaskTest() override
{}
165 void UpdateDisplays(size_t count
) {
166 std::vector
<DisplaySnapshot
*> displays
;
167 for (size_t i
= 0; i
< count
; ++i
)
168 displays
.push_back(&displays_
[i
]);
170 delegate_
.set_outputs(displays
);
173 void ResponseCallback(bool success
,
174 const std::vector
<DisplaySnapshot
*>& displays
,
175 const gfx::Size
& framebuffer_size
,
176 MultipleDisplayState new_display_state
,
177 chromeos::DisplayPowerState new_power_state
) {
179 configuration_status_
= success
;
180 display_states_
= displays
;
181 display_state_
= new_display_state
;
182 power_state_
= new_power_state
;
185 layout_manager_
.set_display_state(display_state_
);
186 layout_manager_
.set_power_state(power_state_
);
192 TestNativeDisplayDelegate delegate_
;
193 TestDisplayLayoutManager layout_manager_
;
195 const DisplayMode small_mode_
;
196 const DisplayMode big_mode_
;
198 TestDisplaySnapshot displays_
[2];
201 bool configuration_status_
;
202 std::vector
<DisplaySnapshot
*> display_states_
;
203 MultipleDisplayState display_state_
;
204 chromeos::DisplayPowerState power_state_
;
207 DISALLOW_COPY_AND_ASSIGN(UpdateDisplayConfigurationTaskTest
);
212 TEST_F(UpdateDisplayConfigurationTaskTest
, HeadlessConfiguration
) {
214 UpdateDisplayConfigurationTask
task(
215 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_HEADLESS
,
216 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
217 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
218 base::Unretained(this)));
222 EXPECT_TRUE(configured_
);
223 EXPECT_TRUE(configuration_status_
);
224 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_HEADLESS
, display_state_
);
225 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
, power_state_
);
226 EXPECT_EQ(JoinActions(kGrab
, kUngrab
, NULL
), log_
.GetActionsAndClear());
229 TEST_F(UpdateDisplayConfigurationTaskTest
, SingleConfiguration
) {
233 UpdateDisplayConfigurationTask
task(
234 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_SINGLE
,
235 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
236 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
237 base::Unretained(this)));
241 EXPECT_TRUE(configured_
);
242 EXPECT_TRUE(configuration_status_
);
243 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE
, display_state_
);
244 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
, power_state_
);
245 EXPECT_EQ(JoinActions(
246 kGrab
, GetFramebufferAction(small_mode_
.size(), &displays_
[0],
248 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
250 log_
.GetActionsAndClear());
253 TEST_F(UpdateDisplayConfigurationTaskTest
, ExtendedConfiguration
) {
257 UpdateDisplayConfigurationTask
task(
258 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
,
259 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
260 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
261 base::Unretained(this)));
265 EXPECT_TRUE(configured_
);
266 EXPECT_TRUE(configuration_status_
);
267 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
, display_state_
);
268 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
, power_state_
);
271 kGrab
, GetFramebufferAction(gfx::Size(big_mode_
.size().width(),
272 small_mode_
.size().height() +
273 big_mode_
.size().height()),
274 &displays_
[0], &displays_
[1]).c_str(),
275 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
276 GetCrtcAction(displays_
[1], &big_mode_
,
277 gfx::Point(0, small_mode_
.size().height())).c_str(),
279 log_
.GetActionsAndClear());
282 TEST_F(UpdateDisplayConfigurationTaskTest
, MirrorConfiguration
) {
286 UpdateDisplayConfigurationTask
task(
287 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
,
288 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
289 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
290 base::Unretained(this)));
294 EXPECT_TRUE(configured_
);
295 EXPECT_TRUE(configuration_status_
);
296 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
, display_state_
);
297 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
, power_state_
);
298 EXPECT_EQ(JoinActions(
299 kGrab
, GetFramebufferAction(small_mode_
.size(), &displays_
[0],
300 &displays_
[1]).c_str(),
301 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
302 GetCrtcAction(displays_
[1], &small_mode_
, gfx::Point()).c_str(),
304 log_
.GetActionsAndClear());
307 TEST_F(UpdateDisplayConfigurationTaskTest
, FailMirrorConfiguration
) {
308 layout_manager_
.set_should_mirror(false);
312 UpdateDisplayConfigurationTask
task(
313 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
,
314 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
315 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
316 base::Unretained(this)));
320 EXPECT_TRUE(configured_
);
321 EXPECT_FALSE(configuration_status_
);
322 EXPECT_EQ(JoinActions(kGrab
, kUngrab
, NULL
), log_
.GetActionsAndClear());
325 TEST_F(UpdateDisplayConfigurationTaskTest
, FailExtendedConfiguration
) {
326 delegate_
.set_max_configurable_pixels(1);
330 UpdateDisplayConfigurationTask
task(
331 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
,
332 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
333 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
334 base::Unretained(this)));
338 EXPECT_TRUE(configured_
);
339 EXPECT_FALSE(configuration_status_
);
342 kGrab
, GetFramebufferAction(gfx::Size(big_mode_
.size().width(),
343 small_mode_
.size().height() +
344 big_mode_
.size().height()),
345 &displays_
[0], &displays_
[1]).c_str(),
346 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
347 GetCrtcAction(displays_
[1], &big_mode_
,
348 gfx::Point(0, small_mode_
.size().height())).c_str(),
349 GetCrtcAction(displays_
[1], &small_mode_
,
350 gfx::Point(0, small_mode_
.size().height())).c_str(),
352 log_
.GetActionsAndClear());
355 TEST_F(UpdateDisplayConfigurationTaskTest
, SingleChangePowerConfiguration
) {
359 UpdateDisplayConfigurationTask
task(
360 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_SINGLE
,
361 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
362 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
363 base::Unretained(this)));
367 EXPECT_TRUE(configured_
);
368 EXPECT_TRUE(configuration_status_
);
369 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE
, display_state_
);
370 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
, power_state_
);
371 EXPECT_EQ(JoinActions(
372 kGrab
, GetFramebufferAction(small_mode_
.size(), &displays_
[0],
374 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
376 log_
.GetActionsAndClear());
380 UpdateDisplayConfigurationTask
task(
381 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_SINGLE
,
382 chromeos::DISPLAY_POWER_ALL_OFF
, 0, 0, false,
383 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
384 base::Unretained(this)));
388 EXPECT_TRUE(configuration_status_
);
389 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE
, display_state_
);
390 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF
, power_state_
);
392 JoinActions(kGrab
, GetFramebufferAction(small_mode_
.size(), &displays_
[0],
394 GetCrtcAction(displays_
[0], nullptr, gfx::Point()).c_str(),
396 log_
.GetActionsAndClear());
399 TEST_F(UpdateDisplayConfigurationTaskTest
, NoopSoftwareMirrorConfiguration
) {
400 layout_manager_
.set_should_mirror(false);
401 layout_manager_
.set_software_mirroring_controller(
402 make_scoped_ptr(new TestSoftwareMirroringController()));
406 UpdateDisplayConfigurationTask
task(
407 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
,
408 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
409 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
410 base::Unretained(this)));
414 log_
.GetActionsAndClear();
417 UpdateDisplayConfigurationTask
task(
418 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
,
419 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
420 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
421 base::Unretained(this)));
425 EXPECT_TRUE(configuration_status_
);
426 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
, display_state_
);
427 EXPECT_TRUE(layout_manager_
.GetSoftwareMirroringController()
428 ->SoftwareMirroringEnabled());
429 EXPECT_EQ(JoinActions(kGrab
, kUngrab
, NULL
), log_
.GetActionsAndClear());
432 TEST_F(UpdateDisplayConfigurationTaskTest
,
433 ForceConfigurationWhileGoingToSoftwareMirror
) {
434 layout_manager_
.set_should_mirror(false);
435 layout_manager_
.set_software_mirroring_controller(
436 make_scoped_ptr(new TestSoftwareMirroringController()));
440 UpdateDisplayConfigurationTask
task(
441 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
,
442 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, false,
443 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
444 base::Unretained(this)));
448 log_
.GetActionsAndClear();
451 UpdateDisplayConfigurationTask
task(
452 &delegate_
, &layout_manager_
, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR
,
453 chromeos::DISPLAY_POWER_ALL_ON
, 0, 0, true /* force_configure */,
454 base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback
,
455 base::Unretained(this)));
459 EXPECT_TRUE(configuration_status_
);
460 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
, display_state_
);
461 EXPECT_TRUE(layout_manager_
.GetSoftwareMirroringController()
462 ->SoftwareMirroringEnabled());
465 kGrab
, GetFramebufferAction(gfx::Size(big_mode_
.size().width(),
466 small_mode_
.size().height() +
467 big_mode_
.size().height()),
468 &displays_
[0], &displays_
[1]).c_str(),
469 GetCrtcAction(displays_
[0], &small_mode_
, gfx::Point()).c_str(),
470 GetCrtcAction(displays_
[1], &big_mode_
,
471 gfx::Point(0, small_mode_
.size().height())).c_str(),
473 log_
.GetActionsAndClear());