Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / display / chromeos / display_configurator_unittest.cc
blob9c24cb4b1192de6ab890f23bb10d8d0a8a26f9de
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 "ui/display/chromeos/display_configurator.h"
7 #include <stdint.h>
9 #include <cmath>
10 #include <cstdarg>
11 #include <map>
12 #include <string>
13 #include <vector>
15 #include "base/compiler_specific.h"
16 #include "base/format_macros.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/strings/stringprintf.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/display/chromeos/test/test_display_snapshot.h"
22 #include "ui/display/types/chromeos/display_mode.h"
23 #include "ui/display/types/chromeos/native_display_delegate.h"
25 namespace ui {
27 namespace {
29 // Strings returned by TestNativeDisplayDelegate::GetActionsAndClear() to
30 // describe various actions that were performed.
31 const char kInitXRandR[] = "init";
32 const char kGrab[] = "grab";
33 const char kUngrab[] = "ungrab";
34 const char kSync[] = "sync";
35 const char kForceDPMS[] = "dpms";
37 // String returned by TestNativeDisplayDelegate::GetActionsAndClear() if no
38 // actions were requested.
39 const char kNoActions[] = "";
41 std::string DisplaySnapshotToString(const DisplaySnapshot& output) {
42 return base::StringPrintf("id=%" PRId64, output.display_id());
45 // Returns a string describing a TestNativeDisplayDelegate::SetBackgroundColor()
46 // call.
47 std::string GetBackgroundAction(uint32_t color_argb) {
48 return base::StringPrintf("background(0x%x)", color_argb);
51 // Returns a string describing a TestNativeDisplayDelegate::AddOutputMode()
52 // call.
53 std::string GetAddOutputModeAction(const DisplaySnapshot& output,
54 const DisplayMode* mode) {
55 return base::StringPrintf("add_mode(output=%" PRId64 ",mode=%s)",
56 output.display_id(),
57 mode->ToString().c_str());
60 // Returns a string describing a TestNativeDisplayDelegate::Configure()
61 // call.
62 std::string GetCrtcAction(const DisplaySnapshot& output,
63 const DisplayMode* mode,
64 const gfx::Point& origin) {
65 return base::StringPrintf("crtc(display=[%s],x=%d,y=%d,mode=[%s])",
66 DisplaySnapshotToString(output).c_str(),
67 origin.x(),
68 origin.y(),
69 mode ? mode->ToString().c_str() : "NULL");
72 // Returns a string describing a TestNativeDisplayDelegate::CreateFramebuffer()
73 // call.
74 std::string GetFramebufferAction(const gfx::Size& size,
75 const DisplaySnapshot* out1,
76 const DisplaySnapshot* out2) {
77 return base::StringPrintf(
78 "framebuffer(width=%d,height=%d,display1=%s,display2=%s)",
79 size.width(),
80 size.height(),
81 out1 ? DisplaySnapshotToString(*out1).c_str() : "NULL",
82 out2 ? DisplaySnapshotToString(*out2).c_str() : "NULL");
85 // Returns a string describing a TestNativeDisplayDelegate::SetHDCPState() call.
86 std::string GetSetHDCPStateAction(const DisplaySnapshot& output,
87 HDCPState state) {
88 return base::StringPrintf(
89 "set_hdcp(id=%" PRId64 ",state=%d)", output.display_id(), state);
92 // Joins a sequence of strings describing actions (e.g. kScreenDim) such
93 // that they can be compared against a string returned by
94 // ActionLogger::GetActionsAndClear(). The list of actions must be
95 // terminated by a NULL pointer.
96 std::string JoinActions(const char* action, ...) {
97 std::string actions;
99 va_list arg_list;
100 va_start(arg_list, action);
101 while (action) {
102 if (!actions.empty())
103 actions += ",";
104 actions += action;
105 action = va_arg(arg_list, const char*);
107 va_end(arg_list);
108 return actions;
111 class ActionLogger {
112 public:
113 ActionLogger() {}
115 void AppendAction(const std::string& action) {
116 if (!actions_.empty())
117 actions_ += ",";
118 actions_ += action;
121 // Returns a comma-separated string describing the actions that were
122 // requested since the previous call to GetActionsAndClear() (i.e.
123 // results are non-repeatable).
124 std::string GetActionsAndClear() {
125 std::string actions = actions_;
126 actions_.clear();
127 return actions;
130 private:
131 std::string actions_;
133 DISALLOW_COPY_AND_ASSIGN(ActionLogger);
136 class TestTouchscreenDelegate
137 : public DisplayConfigurator::TouchscreenDelegate {
138 public:
139 // Ownership of |log| remains with the caller.
140 explicit TestTouchscreenDelegate(ActionLogger* log)
141 : log_(log),
142 configure_touchscreens_(false) {}
143 virtual ~TestTouchscreenDelegate() {}
145 void set_configure_touchscreens(bool state) {
146 configure_touchscreens_ = state;
149 // DisplayConfigurator::TouchscreenDelegate implementation:
150 virtual void AssociateTouchscreens(
151 DisplayConfigurator::DisplayStateList* outputs) OVERRIDE {
152 if (configure_touchscreens_) {
153 for (size_t i = 0; i < outputs->size(); ++i)
154 (*outputs)[i].touch_device_id = i + 1;
158 private:
159 ActionLogger* log_; // Not owned.
161 bool configure_touchscreens_;
163 DISALLOW_COPY_AND_ASSIGN(TestTouchscreenDelegate);
166 class TestNativeDisplayDelegate : public NativeDisplayDelegate {
167 public:
168 // Ownership of |log| remains with the caller.
169 explicit TestNativeDisplayDelegate(ActionLogger* log)
170 : max_configurable_pixels_(0),
171 hdcp_state_(HDCP_STATE_UNDESIRED),
172 log_(log) {}
173 virtual ~TestNativeDisplayDelegate() {}
175 const std::vector<DisplaySnapshot*>& outputs() const { return outputs_; }
176 void set_outputs(const std::vector<DisplaySnapshot*>& outputs) {
177 outputs_ = outputs;
180 void set_max_configurable_pixels(int pixels) {
181 max_configurable_pixels_ = pixels;
184 void set_hdcp_state(HDCPState state) { hdcp_state_ = state; }
186 // DisplayConfigurator::Delegate overrides:
187 virtual void Initialize() OVERRIDE { log_->AppendAction(kInitXRandR); }
188 virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); }
189 virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); }
190 virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); }
191 virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE {
192 log_->AppendAction(GetBackgroundAction(color_argb));
194 virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); }
195 virtual std::vector<DisplaySnapshot*> GetDisplays() OVERRIDE {
196 return outputs_;
198 virtual void AddMode(const DisplaySnapshot& output,
199 const DisplayMode* mode) OVERRIDE {
200 log_->AppendAction(GetAddOutputModeAction(output, mode));
202 virtual bool Configure(const DisplaySnapshot& output,
203 const DisplayMode* mode,
204 const gfx::Point& origin) OVERRIDE {
205 log_->AppendAction(GetCrtcAction(output, mode, origin));
207 if (max_configurable_pixels_ == 0)
208 return true;
210 if (!mode)
211 return false;
213 return mode->size().GetArea() <= max_configurable_pixels_;
215 virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE {
216 log_->AppendAction(
217 GetFramebufferAction(size,
218 outputs_.size() >= 1 ? outputs_[0] : NULL,
219 outputs_.size() >= 2 ? outputs_[1] : NULL));
221 virtual bool GetHDCPState(const DisplaySnapshot& output,
222 HDCPState* state) OVERRIDE {
223 *state = hdcp_state_;
224 return true;
227 virtual bool SetHDCPState(const DisplaySnapshot& output,
228 HDCPState state) OVERRIDE {
229 log_->AppendAction(GetSetHDCPStateAction(output, state));
230 return true;
233 virtual std::vector<ui::ColorCalibrationProfile>
234 GetAvailableColorCalibrationProfiles(const DisplaySnapshot& output) OVERRIDE {
235 return std::vector<ui::ColorCalibrationProfile>();
238 virtual bool SetColorCalibrationProfile(
239 const DisplaySnapshot& output,
240 ui::ColorCalibrationProfile new_profile) OVERRIDE {
241 return false;
244 virtual void AddObserver(NativeDisplayObserver* observer) OVERRIDE {}
246 virtual void RemoveObserver(NativeDisplayObserver* observer) OVERRIDE {}
248 private:
249 // Outputs to be returned by GetDisplays().
250 std::vector<DisplaySnapshot*> outputs_;
252 // |max_configurable_pixels_| represents the maximum number of pixels that
253 // Configure will support. Tests can use this to force Configure
254 // to fail if attempting to set a resolution that is higher than what
255 // a device might support under a given circumstance.
256 // A value of 0 means that no limit is enforced and Configure will
257 // return success regardless of the resolution.
258 int max_configurable_pixels_;
260 // Result value of GetHDCPState().
261 HDCPState hdcp_state_;
263 ActionLogger* log_; // Not owned.
265 DISALLOW_COPY_AND_ASSIGN(TestNativeDisplayDelegate);
268 class TestObserver : public DisplayConfigurator::Observer {
269 public:
270 explicit TestObserver(DisplayConfigurator* configurator)
271 : configurator_(configurator) {
272 Reset();
273 configurator_->AddObserver(this);
275 virtual ~TestObserver() { configurator_->RemoveObserver(this); }
277 int num_changes() const { return num_changes_; }
278 int num_failures() const { return num_failures_; }
279 const DisplayConfigurator::DisplayStateList& latest_outputs() const {
280 return latest_outputs_;
282 MultipleDisplayState latest_failed_state() const {
283 return latest_failed_state_;
286 void Reset() {
287 num_changes_ = 0;
288 num_failures_ = 0;
289 latest_outputs_.clear();
290 latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
293 // DisplayConfigurator::Observer overrides:
294 virtual void OnDisplayModeChanged(
295 const DisplayConfigurator::DisplayStateList& outputs) OVERRIDE {
296 num_changes_++;
297 latest_outputs_ = outputs;
300 virtual void OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)
301 OVERRIDE {
302 num_failures_++;
303 latest_failed_state_ = failed_new_state;
306 private:
307 DisplayConfigurator* configurator_; // Not owned.
309 // Number of times that OnDisplayMode*() has been called.
310 int num_changes_;
311 int num_failures_;
313 // Parameters most recently passed to OnDisplayMode*().
314 DisplayConfigurator::DisplayStateList latest_outputs_;
315 MultipleDisplayState latest_failed_state_;
317 DISALLOW_COPY_AND_ASSIGN(TestObserver);
320 class TestStateController : public DisplayConfigurator::StateController {
321 public:
322 TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {}
323 virtual ~TestStateController() {}
325 void set_state(MultipleDisplayState state) { state_ = state; }
327 // DisplayConfigurator::StateController overrides:
328 virtual MultipleDisplayState GetStateForDisplayIds(
329 const std::vector<int64_t>& outputs) const OVERRIDE {
330 return state_;
332 virtual bool GetResolutionForDisplayId(int64_t display_id,
333 gfx::Size* size) const OVERRIDE {
334 return false;
337 private:
338 MultipleDisplayState state_;
340 DISALLOW_COPY_AND_ASSIGN(TestStateController);
343 class TestMirroringController
344 : public DisplayConfigurator::SoftwareMirroringController {
345 public:
346 TestMirroringController() : software_mirroring_enabled_(false) {}
347 virtual ~TestMirroringController() {}
349 virtual void SetSoftwareMirroring(bool enabled) OVERRIDE {
350 software_mirroring_enabled_ = enabled;
353 virtual bool SoftwareMirroringEnabled() const OVERRIDE {
354 return software_mirroring_enabled_;
357 private:
358 bool software_mirroring_enabled_;
360 DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
363 class DisplayConfiguratorTest : public testing::Test {
364 public:
365 DisplayConfiguratorTest()
366 : small_mode_(gfx::Size(1366, 768), false, 60.0f),
367 big_mode_(gfx::Size(2560, 1600), false, 60.0f),
368 observer_(&configurator_),
369 test_api_(&configurator_) {}
370 virtual ~DisplayConfiguratorTest() {}
372 virtual void SetUp() OVERRIDE {
373 log_.reset(new ActionLogger());
375 native_display_delegate_ = new TestNativeDisplayDelegate(log_.get());
376 touchscreen_delegate_ = new TestTouchscreenDelegate(log_.get());
377 configurator_.SetDelegatesForTesting(
378 scoped_ptr<NativeDisplayDelegate>(native_display_delegate_),
379 scoped_ptr<DisplayConfigurator::TouchscreenDelegate>(
380 touchscreen_delegate_));
382 configurator_.set_state_controller(&state_controller_);
383 configurator_.set_mirroring_controller(&mirroring_controller_);
385 std::vector<const DisplayMode*> modes;
386 modes.push_back(&small_mode_);
388 TestDisplaySnapshot* o = &outputs_[0];
389 o->set_current_mode(&small_mode_);
390 o->set_native_mode(&small_mode_);
391 o->set_modes(modes);
392 o->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL);
393 o->set_is_aspect_preserving_scaling(true);
394 o->set_display_id(123);
395 o->set_has_proper_display_id(true);
397 o = &outputs_[1];
398 o->set_current_mode(&big_mode_);
399 o->set_native_mode(&big_mode_);
400 modes.push_back(&big_mode_);
401 o->set_modes(modes);
402 o->set_type(DISPLAY_CONNECTION_TYPE_HDMI);
403 o->set_is_aspect_preserving_scaling(true);
404 o->set_display_id(456);
405 o->set_has_proper_display_id(true);
407 UpdateOutputs(2, false);
410 // Predefined modes that can be used by outputs.
411 const DisplayMode small_mode_;
412 const DisplayMode big_mode_;
414 protected:
415 // Configures |native_display_delegate_| to return the first |num_outputs|
416 // entries from
417 // |outputs_|. If |send_events| is true, also sends screen-change and
418 // output-change events to |configurator_| and triggers the configure
419 // timeout if one was scheduled.
420 void UpdateOutputs(size_t num_outputs, bool send_events) {
421 ASSERT_LE(num_outputs, arraysize(outputs_));
422 std::vector<DisplaySnapshot*> outputs;
423 for (size_t i = 0; i < num_outputs; ++i)
424 outputs.push_back(&outputs_[i]);
425 native_display_delegate_->set_outputs(outputs);
427 if (send_events) {
428 configurator_.OnConfigurationChanged();
429 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
433 // Initializes |configurator_| with a single internal display.
434 void InitWithSingleOutput() {
435 UpdateOutputs(1, false);
436 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
437 configurator_.Init(false);
438 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
439 configurator_.ForceInitialConfigure(0);
440 EXPECT_EQ(
441 JoinActions(
442 kGrab,
443 kInitXRandR,
444 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL)
445 .c_str(),
446 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
447 kForceDPMS,
448 kUngrab,
449 NULL),
450 log_->GetActionsAndClear());
453 base::MessageLoop message_loop_;
454 TestStateController state_controller_;
455 TestMirroringController mirroring_controller_;
456 DisplayConfigurator configurator_;
457 TestObserver observer_;
458 scoped_ptr<ActionLogger> log_;
459 TestNativeDisplayDelegate* native_display_delegate_; // not owned
460 TestTouchscreenDelegate* touchscreen_delegate_; // not owned
461 DisplayConfigurator::TestApi test_api_;
463 TestDisplaySnapshot outputs_[2];
465 private:
466 DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest);
469 } // namespace
471 TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) {
472 ScopedVector<const DisplayMode> modes;
474 // Fields are width, height, interlaced, refresh rate.
475 modes.push_back(new DisplayMode(gfx::Size(1920, 1200), false, 60.0));
476 // Different rates.
477 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 30.0));
478 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 50.0));
479 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
480 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 0.0));
481 // Interlaced vs non-interlaced.
482 modes.push_back(new DisplayMode(gfx::Size(1280, 720), true, 60.0));
483 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 40.0));
484 // Interlaced only.
485 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 0.0));
486 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 40.0));
487 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 60.0));
488 // Mixed.
489 modes.push_back(new DisplayMode(gfx::Size(1024, 600), true, 60.0));
490 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 40.0));
491 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 50.0));
492 // Just one interlaced mode.
493 modes.push_back(new DisplayMode(gfx::Size(640, 480), true, 60.0));
494 // Refresh rate not available.
495 modes.push_back(new DisplayMode(gfx::Size(320, 200), false, 0.0));
497 TestDisplaySnapshot output;
498 output.set_modes(modes.get());
500 EXPECT_EQ(modes[0],
501 DisplayConfigurator::FindDisplayModeMatchingSize(
502 output, gfx::Size(1920, 1200)));
504 // Should pick highest refresh rate.
505 EXPECT_EQ(modes[2],
506 DisplayConfigurator::FindDisplayModeMatchingSize(
507 output, gfx::Size(1920, 1080)));
509 // Should pick non-interlaced mode.
510 EXPECT_EQ(modes[6],
511 DisplayConfigurator::FindDisplayModeMatchingSize(
512 output, gfx::Size(1280, 720)));
514 // Interlaced only. Should pick one with the highest refresh rate in
515 // interlaced mode.
516 EXPECT_EQ(modes[9],
517 DisplayConfigurator::FindDisplayModeMatchingSize(
518 output, gfx::Size(1024, 768)));
520 // Mixed: Should pick one with the highest refresh rate in
521 // interlaced mode.
522 EXPECT_EQ(modes[12],
523 DisplayConfigurator::FindDisplayModeMatchingSize(
524 output, gfx::Size(1024, 600)));
526 // Just one interlaced mode.
527 EXPECT_EQ(modes[13],
528 DisplayConfigurator::FindDisplayModeMatchingSize(
529 output, gfx::Size(640, 480)));
531 // Refresh rate not available.
532 EXPECT_EQ(modes[14],
533 DisplayConfigurator::FindDisplayModeMatchingSize(
534 output, gfx::Size(320, 200)));
536 // No mode found.
537 EXPECT_EQ(NULL,
538 DisplayConfigurator::FindDisplayModeMatchingSize(
539 output, gfx::Size(1440, 900)));
542 TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
543 InitWithSingleOutput();
545 // Connect a second output and check that the configurator enters
546 // extended mode.
547 observer_.Reset();
548 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
549 UpdateOutputs(2, true);
550 const int kDualHeight = small_mode_.size().height() +
551 DisplayConfigurator::kVerticalGap +
552 big_mode_.size().height();
553 EXPECT_EQ(
554 JoinActions(
555 kGrab,
556 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
557 &outputs_[0],
558 &outputs_[1]).c_str(),
559 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
560 GetCrtcAction(outputs_[1],
561 &big_mode_,
562 gfx::Point(0,
563 small_mode_.size().height() +
564 DisplayConfigurator::kVerticalGap))
565 .c_str(),
566 kUngrab,
567 NULL),
568 log_->GetActionsAndClear());
569 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
570 EXPECT_EQ(1, observer_.num_changes());
572 observer_.Reset();
573 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
574 EXPECT_EQ(
575 JoinActions(
576 kGrab,
577 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
578 .c_str(),
579 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
580 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
581 kUngrab,
582 NULL),
583 log_->GetActionsAndClear());
584 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
585 EXPECT_EQ(1, observer_.num_changes());
587 // Disconnect the second output.
588 observer_.Reset();
589 UpdateOutputs(1, true);
590 EXPECT_EQ(
591 JoinActions(
592 kGrab,
593 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
594 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
595 kUngrab,
596 NULL),
597 log_->GetActionsAndClear());
598 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
599 EXPECT_EQ(1, observer_.num_changes());
601 // Get rid of shared modes to force software mirroring.
602 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
603 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
604 UpdateOutputs(2, true);
605 EXPECT_EQ(
606 JoinActions(
607 kGrab,
608 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
609 &outputs_[0],
610 &outputs_[1]).c_str(),
611 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
612 GetCrtcAction(outputs_[1],
613 &big_mode_,
614 gfx::Point(0,
615 small_mode_.size().height() +
616 DisplayConfigurator::kVerticalGap))
617 .c_str(),
618 kUngrab,
619 NULL),
620 log_->GetActionsAndClear());
621 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
623 observer_.Reset();
624 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
625 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
626 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
627 configurator_.display_state());
628 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
629 EXPECT_EQ(1, observer_.num_changes());
631 // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
632 observer_.Reset();
633 EXPECT_TRUE(
634 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
635 EXPECT_EQ(JoinActions(NULL), log_->GetActionsAndClear());
636 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
637 EXPECT_EQ(1, observer_.num_changes());
639 // Set back to software mirror mode.
640 observer_.Reset();
641 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
642 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
643 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
644 configurator_.display_state());
645 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
646 EXPECT_EQ(1, observer_.num_changes());
648 // Disconnect the second output.
649 observer_.Reset();
650 UpdateOutputs(1, true);
651 EXPECT_EQ(
652 JoinActions(
653 kGrab,
654 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
655 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
656 kUngrab,
657 NULL),
658 log_->GetActionsAndClear());
659 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
660 EXPECT_EQ(1, observer_.num_changes());
663 TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
664 InitWithSingleOutput();
666 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
667 observer_.Reset();
668 UpdateOutputs(2, true);
669 EXPECT_EQ(
670 JoinActions(
671 kGrab,
672 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
673 .c_str(),
674 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
675 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
676 kUngrab,
677 NULL),
678 log_->GetActionsAndClear());
679 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
680 EXPECT_EQ(1, observer_.num_changes());
682 // Turning off the internal display should switch the external display to
683 // its native mode.
684 observer_.Reset();
685 configurator_.SetDisplayPower(
686 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
687 DisplayConfigurator::kSetDisplayPowerNoFlags);
688 EXPECT_EQ(
689 JoinActions(
690 kGrab,
691 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
692 .c_str(),
693 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
694 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
695 kForceDPMS,
696 kUngrab,
697 NULL),
698 log_->GetActionsAndClear());
699 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
700 EXPECT_EQ(1, observer_.num_changes());
702 // When all displays are turned off, the framebuffer should switch back
703 // to the mirrored size.
704 observer_.Reset();
705 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
706 DisplayConfigurator::kSetDisplayPowerNoFlags);
707 EXPECT_EQ(
708 JoinActions(kGrab,
709 GetFramebufferAction(
710 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
711 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
712 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
713 kUngrab,
714 NULL),
715 log_->GetActionsAndClear());
716 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
717 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
718 EXPECT_EQ(1, observer_.num_changes());
720 // Turn all displays on and check that mirroring is still used.
721 observer_.Reset();
722 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
723 DisplayConfigurator::kSetDisplayPowerNoFlags);
724 EXPECT_EQ(
725 JoinActions(
726 kGrab,
727 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
728 .c_str(),
729 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
730 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
731 kForceDPMS,
732 kUngrab,
733 NULL),
734 log_->GetActionsAndClear());
735 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
736 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
737 EXPECT_EQ(1, observer_.num_changes());
739 // Get rid of shared modes to force software mirroring.
740 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
741 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
742 observer_.Reset();
743 UpdateOutputs(2, true);
744 const int kDualHeight = small_mode_.size().height() +
745 DisplayConfigurator::kVerticalGap +
746 big_mode_.size().height();
747 EXPECT_EQ(
748 JoinActions(
749 kGrab,
750 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
751 &outputs_[0],
752 &outputs_[1]).c_str(),
753 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
754 GetCrtcAction(outputs_[1],
755 &big_mode_,
756 gfx::Point(0,
757 small_mode_.size().height() +
758 DisplayConfigurator::kVerticalGap))
759 .c_str(),
760 kUngrab,
761 NULL),
762 log_->GetActionsAndClear());
763 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
764 configurator_.display_state());
765 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
766 EXPECT_EQ(1, observer_.num_changes());
768 // Turning off the internal display should switch the external display to
769 // its native mode.
770 observer_.Reset();
771 configurator_.SetDisplayPower(
772 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
773 DisplayConfigurator::kSetDisplayPowerNoFlags);
774 EXPECT_EQ(
775 JoinActions(
776 kGrab,
777 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
778 .c_str(),
779 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
780 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
781 kForceDPMS,
782 kUngrab,
783 NULL),
784 log_->GetActionsAndClear());
785 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
786 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
787 EXPECT_EQ(1, observer_.num_changes());
789 // When all displays are turned off, the framebuffer should switch back
790 // to the extended + software mirroring.
791 observer_.Reset();
792 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
793 DisplayConfigurator::kSetDisplayPowerNoFlags);
794 EXPECT_EQ(
795 JoinActions(
796 kGrab,
797 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
798 &outputs_[0],
799 &outputs_[1]).c_str(),
800 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
801 GetCrtcAction(outputs_[1],
802 NULL,
803 gfx::Point(0,
804 small_mode_.size().height() +
805 DisplayConfigurator::kVerticalGap))
806 .c_str(),
807 kUngrab,
808 NULL),
809 log_->GetActionsAndClear());
810 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
811 configurator_.display_state());
812 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
813 EXPECT_EQ(1, observer_.num_changes());
815 // Turn all displays on and check that mirroring is still used.
816 observer_.Reset();
817 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
818 DisplayConfigurator::kSetDisplayPowerNoFlags);
819 EXPECT_EQ(
820 JoinActions(
821 kGrab,
822 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
823 &outputs_[0],
824 &outputs_[1]).c_str(),
825 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
826 GetCrtcAction(outputs_[1],
827 &big_mode_,
828 gfx::Point(0,
829 small_mode_.size().height() +
830 DisplayConfigurator::kVerticalGap))
831 .c_str(),
832 kForceDPMS,
833 kUngrab,
834 NULL),
835 log_->GetActionsAndClear());
836 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
837 configurator_.display_state());
838 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
839 EXPECT_EQ(1, observer_.num_changes());
842 TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
843 InitWithSingleOutput();
845 // No preparation is needed before suspending when the display is already
846 // on. The configurator should still reprobe on resume in case a display
847 // was connected while suspended.
848 configurator_.SuspendDisplays();
849 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
850 configurator_.ResumeDisplays();
851 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
852 EXPECT_EQ(
853 JoinActions(
854 kGrab,
855 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
856 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
857 kForceDPMS,
858 kUngrab,
859 NULL),
860 log_->GetActionsAndClear());
862 // Now turn the display off before suspending and check that the
863 // configurator turns it back on and syncs with the server.
864 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
865 DisplayConfigurator::kSetDisplayPowerNoFlags);
866 EXPECT_EQ(
867 JoinActions(
868 kGrab,
869 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
870 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
871 kUngrab,
872 NULL),
873 log_->GetActionsAndClear());
875 configurator_.SuspendDisplays();
876 EXPECT_EQ(
877 JoinActions(
878 kGrab,
879 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
880 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
881 kForceDPMS,
882 kUngrab,
883 kSync,
884 NULL),
885 log_->GetActionsAndClear());
887 configurator_.ResumeDisplays();
888 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
889 EXPECT_EQ(
890 JoinActions(
891 kGrab,
892 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
893 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
894 kForceDPMS,
895 kUngrab,
896 NULL),
897 log_->GetActionsAndClear());
899 // If a second, external display is connected, the displays shouldn't be
900 // powered back on before suspending.
901 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
902 UpdateOutputs(2, true);
903 EXPECT_EQ(
904 JoinActions(
905 kGrab,
906 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
907 .c_str(),
908 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
909 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
910 kUngrab,
911 NULL),
912 log_->GetActionsAndClear());
914 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
915 DisplayConfigurator::kSetDisplayPowerNoFlags);
916 EXPECT_EQ(
917 JoinActions(kGrab,
918 GetFramebufferAction(
919 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
920 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
921 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
922 kUngrab,
923 NULL),
924 log_->GetActionsAndClear());
926 configurator_.SuspendDisplays();
927 EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL),
928 log_->GetActionsAndClear());
930 // If a display is disconnected while suspended, the configurator should
931 // pick up the change.
932 UpdateOutputs(1, false);
933 configurator_.ResumeDisplays();
934 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
935 EXPECT_EQ(
936 JoinActions(
937 kGrab,
938 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
939 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
940 kUngrab,
941 NULL),
942 log_->GetActionsAndClear());
945 TEST_F(DisplayConfiguratorTest, Headless) {
946 UpdateOutputs(0, false);
947 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
948 configurator_.Init(false);
949 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
950 configurator_.ForceInitialConfigure(0);
951 EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab, NULL),
952 log_->GetActionsAndClear());
954 // Not much should happen when the display power state is changed while
955 // no displays are connected.
956 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
957 DisplayConfigurator::kSetDisplayPowerNoFlags);
958 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
959 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
960 DisplayConfigurator::kSetDisplayPowerNoFlags);
961 EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL),
962 log_->GetActionsAndClear());
964 // Connect an external display and check that it's configured correctly.
965 outputs_[0].set_current_mode(outputs_[1].current_mode());
966 outputs_[0].set_native_mode(outputs_[1].native_mode());
967 outputs_[0].set_modes(outputs_[1].modes());
968 outputs_[0].set_type(outputs_[1].type());
970 UpdateOutputs(1, true);
971 EXPECT_EQ(
972 JoinActions(
973 kGrab,
974 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
975 GetCrtcAction(outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
976 kUngrab,
977 NULL),
978 log_->GetActionsAndClear());
981 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
982 UpdateOutputs(2, false);
983 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
984 configurator_.Init(false);
985 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
987 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
988 configurator_.ForceInitialConfigure(0);
989 EXPECT_EQ(
990 JoinActions(
991 kGrab,
992 kInitXRandR,
993 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
994 .c_str(),
995 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
996 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
997 kForceDPMS,
998 kUngrab,
999 NULL),
1000 log_->GetActionsAndClear());
1003 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
1004 UpdateOutputs(0, false);
1005 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1006 configurator_.Init(false);
1007 configurator_.ForceInitialConfigure(0);
1008 observer_.Reset();
1009 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1010 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1011 EXPECT_FALSE(
1012 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1013 EXPECT_FALSE(
1014 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1015 EXPECT_EQ(1, observer_.num_changes());
1016 EXPECT_EQ(3, observer_.num_failures());
1018 UpdateOutputs(1, true);
1019 observer_.Reset();
1020 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1021 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1022 EXPECT_FALSE(
1023 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1024 EXPECT_FALSE(
1025 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1026 EXPECT_EQ(1, observer_.num_changes());
1027 EXPECT_EQ(3, observer_.num_failures());
1029 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1030 UpdateOutputs(2, true);
1031 observer_.Reset();
1032 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1033 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1034 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1035 EXPECT_TRUE(
1036 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1037 EXPECT_EQ(2, observer_.num_changes());
1038 EXPECT_EQ(2, observer_.num_failures());
1041 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithoutId) {
1042 outputs_[0].set_has_proper_display_id(false);
1043 UpdateOutputs(2, false);
1044 configurator_.Init(false);
1045 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1046 configurator_.ForceInitialConfigure(0);
1047 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
1048 configurator_.display_state());
1051 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithId) {
1052 outputs_[0].set_has_proper_display_id(true);
1053 UpdateOutputs(2, false);
1054 configurator_.Init(false);
1055 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1056 configurator_.ForceInitialConfigure(0);
1057 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1060 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
1061 InitWithSingleOutput();
1062 const DisplayConfigurator::DisplayStateList* cached =
1063 &configurator_.cached_displays();
1064 ASSERT_EQ(static_cast<size_t>(1), cached->size());
1065 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1067 // After connecting a second output, check that it shows up in
1068 // |cached_displays_| even if an invalid state is requested.
1069 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1070 UpdateOutputs(2, true);
1071 cached = &configurator_.cached_displays();
1072 ASSERT_EQ(static_cast<size_t>(2), cached->size());
1073 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1074 EXPECT_EQ(outputs_[1].current_mode(), (*cached)[1].display->current_mode());
1077 TEST_F(DisplayConfiguratorTest, PanelFitting) {
1078 // Configure the internal display to support only the big mode and the
1079 // external display to support only the small mode.
1080 outputs_[0].set_current_mode(&big_mode_);
1081 outputs_[0].set_native_mode(&big_mode_);
1082 outputs_[0].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
1084 outputs_[1].set_current_mode(&small_mode_);
1085 outputs_[1].set_native_mode(&small_mode_);
1086 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &small_mode_));
1088 // The small mode should be added to the internal output when requesting
1089 // mirrored mode.
1090 UpdateOutputs(2, false);
1091 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1092 configurator_.Init(true /* is_panel_fitting_enabled */);
1093 configurator_.ForceInitialConfigure(0);
1094 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1095 EXPECT_EQ(
1096 JoinActions(
1097 kGrab,
1098 kInitXRandR,
1099 GetAddOutputModeAction(outputs_[0], &small_mode_).c_str(),
1100 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1101 .c_str(),
1102 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1103 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1104 kForceDPMS,
1105 kUngrab,
1106 NULL),
1107 log_->GetActionsAndClear());
1109 // Both outputs should be using the small mode.
1110 ASSERT_EQ(1, observer_.num_changes());
1111 ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
1112 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[0].mirror_mode);
1113 EXPECT_EQ(&small_mode_,
1114 observer_.latest_outputs()[0].display->current_mode());
1115 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[1].mirror_mode);
1116 EXPECT_EQ(&small_mode_,
1117 observer_.latest_outputs()[1].display->current_mode());
1119 // Also check that the newly-added small mode is present in the internal
1120 // snapshot that was passed to the observer (http://crbug.com/289159).
1121 const DisplayConfigurator::DisplayState& state =
1122 observer_.latest_outputs()[0];
1123 ASSERT_NE(state.display->modes().end(),
1124 std::find(state.display->modes().begin(),
1125 state.display->modes().end(),
1126 &small_mode_));
1129 TEST_F(DisplayConfiguratorTest, ContentProtection) {
1130 configurator_.Init(false);
1131 configurator_.ForceInitialConfigure(0);
1132 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1134 DisplayConfigurator::ContentProtectionClientId id =
1135 configurator_.RegisterContentProtectionClient();
1136 EXPECT_NE(0u, id);
1138 // One output.
1139 UpdateOutputs(1, true);
1140 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1141 uint32_t link_mask = 0;
1142 uint32_t protection_mask = 0;
1143 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1144 id, outputs_[0].display_id(), &link_mask, &protection_mask));
1145 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), link_mask);
1146 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1147 protection_mask);
1148 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1150 // Two outputs.
1151 UpdateOutputs(2, true);
1152 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1153 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1154 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1155 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1156 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1157 protection_mask);
1158 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1160 EXPECT_TRUE(configurator_.EnableContentProtection(
1161 id, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1162 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED),
1163 log_->GetActionsAndClear());
1165 // Enable protection.
1166 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1167 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1168 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1169 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1170 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP),
1171 protection_mask);
1172 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1174 // Protections should be disabled after unregister.
1175 configurator_.UnregisterContentProtectionClient(id);
1176 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED),
1177 log_->GetActionsAndClear());
1180 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
1181 DisplayConfigurator::ContentProtectionClientId client1 =
1182 configurator_.RegisterContentProtectionClient();
1183 DisplayConfigurator::ContentProtectionClientId client2 =
1184 configurator_.RegisterContentProtectionClient();
1185 EXPECT_NE(client1, client2);
1187 configurator_.Init(false);
1188 configurator_.ForceInitialConfigure(0);
1189 UpdateOutputs(2, true);
1190 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1192 // Clients never know state enableness for methods that they didn't request.
1193 EXPECT_TRUE(configurator_.EnableContentProtection(
1194 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1195 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1196 log_->GetActionsAndClear());
1197 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1199 uint32_t link_mask = 0;
1200 uint32_t protection_mask = 0;
1201 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1202 client1, outputs_[1].display_id(), &link_mask, &protection_mask));
1203 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1204 EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, protection_mask);
1206 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1207 client2, outputs_[1].display_id(), &link_mask, &protection_mask));
1208 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1209 EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, protection_mask);
1211 // Protections will be disabled only if no more clients request them.
1212 EXPECT_TRUE(configurator_.EnableContentProtection(
1213 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1214 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1215 log_->GetActionsAndClear());
1216 EXPECT_TRUE(configurator_.EnableContentProtection(
1217 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1218 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED).c_str(),
1219 log_->GetActionsAndClear());
1222 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
1223 InitWithSingleOutput();
1225 ScopedVector<const DisplayMode> modes;
1226 // The first mode is the mode we are requesting DisplayConfigurator to choose.
1227 // The test will be setup so that this mode will fail and it will have to
1228 // choose the next best option.
1229 modes.push_back(new DisplayMode(gfx::Size(2560, 1600), false, 60.0));
1230 modes.push_back(new DisplayMode(gfx::Size(1024, 768), false, 60.0));
1231 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 60.0));
1232 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 60.0));
1233 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
1235 for (unsigned int i = 0; i < arraysize(outputs_); i++) {
1236 outputs_[i].set_modes(modes.get());
1237 outputs_[i].set_current_mode(modes[0]);
1238 outputs_[i].set_native_mode(modes[0]);
1241 configurator_.Init(false);
1243 // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is
1244 // probably unrealistic but we want to make sure any assumptions don't creep
1245 // in.
1246 native_display_delegate_->set_max_configurable_pixels(
1247 modes[2]->size().GetArea());
1248 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1249 UpdateOutputs(1, true);
1251 EXPECT_EQ(
1252 JoinActions(
1253 kGrab,
1254 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
1255 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1256 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1257 GetCrtcAction(outputs_[0], modes[2], gfx::Point(0, 0)).c_str(),
1258 kUngrab,
1259 NULL),
1260 log_->GetActionsAndClear());
1262 // This test should attempt to configure a mirror mode that will not succeed
1263 // and should end up in extended mode.
1264 native_display_delegate_->set_max_configurable_pixels(
1265 modes[3]->size().GetArea());
1266 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1267 UpdateOutputs(2, true);
1269 EXPECT_EQ(
1270 JoinActions(
1271 kGrab,
1272 GetFramebufferAction(modes[0]->size(), &outputs_[0], &outputs_[1])
1273 .c_str(),
1274 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1275 // First mode tried is expected to fail and it will
1276 // retry wil the 4th mode in the list.
1277 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1278 // Then attempt to configure crtc1 with the first mode.
1279 GetCrtcAction(outputs_[1], modes[0], gfx::Point(0, 0)).c_str(),
1280 GetCrtcAction(outputs_[1], modes[3], gfx::Point(0, 0)).c_str(),
1281 // Since it was requested to go into mirror mode
1282 // and the configured modes were different, it
1283 // should now try and setup a valid configurable
1284 // extended mode.
1285 GetFramebufferAction(
1286 gfx::Size(modes[0]->size().width(),
1287 modes[0]->size().height() + modes[0]->size().height() +
1288 DisplayConfigurator::kVerticalGap),
1289 &outputs_[0],
1290 &outputs_[1]).c_str(),
1291 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1292 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1293 GetCrtcAction(outputs_[1],
1294 modes[0],
1295 gfx::Point(0,
1296 modes[0]->size().height() +
1297 DisplayConfigurator::kVerticalGap))
1298 .c_str(),
1299 GetCrtcAction(outputs_[1],
1300 modes[3],
1301 gfx::Point(0,
1302 modes[0]->size().height() +
1303 DisplayConfigurator::kVerticalGap))
1304 .c_str(),
1305 kUngrab,
1306 NULL),
1307 log_->GetActionsAndClear());
1310 } // namespace ui