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 "ui/display/chromeos/display_configurator.h"
6
7 #include <stdint.h>
8
9 #include <cmath>
10 #include <cstdarg>
11 #include <map>
12 #include <string>
13 #include <vector>
14
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/display_mode.h"
23 #include "ui/display/types/native_display_delegate.h"
24
25 namespace ui {
26
27 namespace {
28
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";
36
37 // String returned by TestNativeDisplayDelegate::GetActionsAndClear() if no
38 // actions were requested.
39 const char kNoActions[] = "";
40
DisplaySnapshotToString(const DisplaySnapshot & output)41 std::string DisplaySnapshotToString(const DisplaySnapshot& output) {
42 return base::StringPrintf("id=%" PRId64, output.display_id());
43 }
44
45 // Returns a string describing a TestNativeDisplayDelegate::SetBackgroundColor()
46 // call.
GetBackgroundAction(uint32_t color_argb)47 std::string GetBackgroundAction(uint32_t color_argb) {
48 return base::StringPrintf("background(0x%x)", color_argb);
49 }
50
51 // Returns a string describing a TestNativeDisplayDelegate::AddOutputMode()
52 // call.
GetAddOutputModeAction(const DisplaySnapshot & output,const DisplayMode * mode)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());
58 }
59
60 // Returns a string describing a TestNativeDisplayDelegate::Configure()
61 // call.
GetCrtcAction(const DisplaySnapshot & output,const DisplayMode * mode,const gfx::Point & origin)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");
70 }
71
72 // Returns a string describing a TestNativeDisplayDelegate::CreateFramebuffer()
73 // call.
GetFramebufferAction(const gfx::Size & size,const DisplaySnapshot * out1,const DisplaySnapshot * out2)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");
83 }
84
85 // Returns a string describing a TestNativeDisplayDelegate::SetHDCPState() call.
GetSetHDCPStateAction(const DisplaySnapshot & output,HDCPState state)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);
90 }
91
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.
JoinActions(const char * action,...)96 std::string JoinActions(const char* action, ...) {
97 std::string actions;
98
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*);
106 }
107 va_end(arg_list);
108 return actions;
109 }
110
111 class ActionLogger {
112 public:
ActionLogger()113 ActionLogger() {}
114
AppendAction(const std::string & action)115 void AppendAction(const std::string& action) {
116 if (!actions_.empty())
117 actions_ += ",";
118 actions_ += action;
119 }
120
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).
GetActionsAndClear()124 std::string GetActionsAndClear() {
125 std::string actions = actions_;
126 actions_.clear();
127 return actions;
128 }
129
130 private:
131 std::string actions_;
132
133 DISALLOW_COPY_AND_ASSIGN(ActionLogger);
134 };
135
136 class TestNativeDisplayDelegate : public NativeDisplayDelegate {
137 public:
138 // Ownership of |log| remains with the caller.
TestNativeDisplayDelegate(ActionLogger * log)139 explicit TestNativeDisplayDelegate(ActionLogger* log)
140 : max_configurable_pixels_(0),
141 hdcp_state_(HDCP_STATE_UNDESIRED),
142 log_(log) {}
~TestNativeDisplayDelegate()143 virtual ~TestNativeDisplayDelegate() {}
144
outputs() const145 const std::vector<DisplaySnapshot*>& outputs() const { return outputs_; }
set_outputs(const std::vector<DisplaySnapshot * > & outputs)146 void set_outputs(const std::vector<DisplaySnapshot*>& outputs) {
147 outputs_ = outputs;
148 }
149
set_max_configurable_pixels(int pixels)150 void set_max_configurable_pixels(int pixels) {
151 max_configurable_pixels_ = pixels;
152 }
153
set_hdcp_state(HDCPState state)154 void set_hdcp_state(HDCPState state) { hdcp_state_ = state; }
155
156 // DisplayConfigurator::Delegate overrides:
Initialize()157 virtual void Initialize() OVERRIDE { log_->AppendAction(kInitXRandR); }
GrabServer()158 virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); }
UngrabServer()159 virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); }
SyncWithServer()160 virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); }
SetBackgroundColor(uint32_t color_argb)161 virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE {
162 log_->AppendAction(GetBackgroundAction(color_argb));
163 }
ForceDPMSOn()164 virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); }
GetDisplays()165 virtual std::vector<DisplaySnapshot*> GetDisplays() OVERRIDE {
166 return outputs_;
167 }
AddMode(const DisplaySnapshot & output,const DisplayMode * mode)168 virtual void AddMode(const DisplaySnapshot& output,
169 const DisplayMode* mode) OVERRIDE {
170 log_->AppendAction(GetAddOutputModeAction(output, mode));
171 }
Configure(const DisplaySnapshot & output,const DisplayMode * mode,const gfx::Point & origin)172 virtual bool Configure(const DisplaySnapshot& output,
173 const DisplayMode* mode,
174 const gfx::Point& origin) OVERRIDE {
175 log_->AppendAction(GetCrtcAction(output, mode, origin));
176
177 if (max_configurable_pixels_ == 0)
178 return true;
179
180 if (!mode)
181 return false;
182
183 return mode->size().GetArea() <= max_configurable_pixels_;
184 }
CreateFrameBuffer(const gfx::Size & size)185 virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE {
186 log_->AppendAction(
187 GetFramebufferAction(size,
188 outputs_.size() >= 1 ? outputs_[0] : NULL,
189 outputs_.size() >= 2 ? outputs_[1] : NULL));
190 }
GetHDCPState(const DisplaySnapshot & output,HDCPState * state)191 virtual bool GetHDCPState(const DisplaySnapshot& output,
192 HDCPState* state) OVERRIDE {
193 *state = hdcp_state_;
194 return true;
195 }
196
SetHDCPState(const DisplaySnapshot & output,HDCPState state)197 virtual bool SetHDCPState(const DisplaySnapshot& output,
198 HDCPState state) OVERRIDE {
199 log_->AppendAction(GetSetHDCPStateAction(output, state));
200 return true;
201 }
202
203 virtual std::vector<ui::ColorCalibrationProfile>
GetAvailableColorCalibrationProfiles(const DisplaySnapshot & output)204 GetAvailableColorCalibrationProfiles(const DisplaySnapshot& output) OVERRIDE {
205 return std::vector<ui::ColorCalibrationProfile>();
206 }
207
SetColorCalibrationProfile(const DisplaySnapshot & output,ui::ColorCalibrationProfile new_profile)208 virtual bool SetColorCalibrationProfile(
209 const DisplaySnapshot& output,
210 ui::ColorCalibrationProfile new_profile) OVERRIDE {
211 return false;
212 }
213
AddObserver(NativeDisplayObserver * observer)214 virtual void AddObserver(NativeDisplayObserver* observer) OVERRIDE {}
215
RemoveObserver(NativeDisplayObserver * observer)216 virtual void RemoveObserver(NativeDisplayObserver* observer) OVERRIDE {}
217
218 private:
219 // Outputs to be returned by GetDisplays().
220 std::vector<DisplaySnapshot*> outputs_;
221
222 // |max_configurable_pixels_| represents the maximum number of pixels that
223 // Configure will support. Tests can use this to force Configure
224 // to fail if attempting to set a resolution that is higher than what
225 // a device might support under a given circumstance.
226 // A value of 0 means that no limit is enforced and Configure will
227 // return success regardless of the resolution.
228 int max_configurable_pixels_;
229
230 // Result value of GetHDCPState().
231 HDCPState hdcp_state_;
232
233 ActionLogger* log_; // Not owned.
234
235 DISALLOW_COPY_AND_ASSIGN(TestNativeDisplayDelegate);
236 };
237
238 class TestObserver : public DisplayConfigurator::Observer {
239 public:
TestObserver(DisplayConfigurator * configurator)240 explicit TestObserver(DisplayConfigurator* configurator)
241 : configurator_(configurator) {
242 Reset();
243 configurator_->AddObserver(this);
244 }
~TestObserver()245 virtual ~TestObserver() { configurator_->RemoveObserver(this); }
246
num_changes() const247 int num_changes() const { return num_changes_; }
num_failures() const248 int num_failures() const { return num_failures_; }
latest_outputs() const249 const DisplayConfigurator::DisplayStateList& latest_outputs() const {
250 return latest_outputs_;
251 }
latest_failed_state() const252 MultipleDisplayState latest_failed_state() const {
253 return latest_failed_state_;
254 }
255
Reset()256 void Reset() {
257 num_changes_ = 0;
258 num_failures_ = 0;
259 latest_outputs_.clear();
260 latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
261 }
262
263 // DisplayConfigurator::Observer overrides:
OnDisplayModeChanged(const DisplayConfigurator::DisplayStateList & outputs)264 virtual void OnDisplayModeChanged(
265 const DisplayConfigurator::DisplayStateList& outputs) OVERRIDE {
266 num_changes_++;
267 latest_outputs_ = outputs;
268 }
269
OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)270 virtual void OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)
271 OVERRIDE {
272 num_failures_++;
273 latest_failed_state_ = failed_new_state;
274 }
275
276 private:
277 DisplayConfigurator* configurator_; // Not owned.
278
279 // Number of times that OnDisplayMode*() has been called.
280 int num_changes_;
281 int num_failures_;
282
283 // Parameters most recently passed to OnDisplayMode*().
284 DisplayConfigurator::DisplayStateList latest_outputs_;
285 MultipleDisplayState latest_failed_state_;
286
287 DISALLOW_COPY_AND_ASSIGN(TestObserver);
288 };
289
290 class TestStateController : public DisplayConfigurator::StateController {
291 public:
TestStateController()292 TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {}
~TestStateController()293 virtual ~TestStateController() {}
294
set_state(MultipleDisplayState state)295 void set_state(MultipleDisplayState state) { state_ = state; }
296
297 // DisplayConfigurator::StateController overrides:
GetStateForDisplayIds(const std::vector<int64_t> & outputs) const298 virtual MultipleDisplayState GetStateForDisplayIds(
299 const std::vector<int64_t>& outputs) const OVERRIDE {
300 return state_;
301 }
GetResolutionForDisplayId(int64_t display_id,gfx::Size * size) const302 virtual bool GetResolutionForDisplayId(int64_t display_id,
303 gfx::Size* size) const OVERRIDE {
304 return false;
305 }
306
307 private:
308 MultipleDisplayState state_;
309
310 DISALLOW_COPY_AND_ASSIGN(TestStateController);
311 };
312
313 class TestMirroringController
314 : public DisplayConfigurator::SoftwareMirroringController {
315 public:
TestMirroringController()316 TestMirroringController() : software_mirroring_enabled_(false) {}
~TestMirroringController()317 virtual ~TestMirroringController() {}
318
SetSoftwareMirroring(bool enabled)319 virtual void SetSoftwareMirroring(bool enabled) OVERRIDE {
320 software_mirroring_enabled_ = enabled;
321 }
322
SoftwareMirroringEnabled() const323 virtual bool SoftwareMirroringEnabled() const OVERRIDE {
324 return software_mirroring_enabled_;
325 }
326
327 private:
328 bool software_mirroring_enabled_;
329
330 DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
331 };
332
333 class DisplayConfiguratorTest : public testing::Test {
334 public:
DisplayConfiguratorTest()335 DisplayConfiguratorTest()
336 : small_mode_(gfx::Size(1366, 768), false, 60.0f),
337 big_mode_(gfx::Size(2560, 1600), false, 60.0f),
338 observer_(&configurator_),
339 test_api_(&configurator_) {}
~DisplayConfiguratorTest()340 virtual ~DisplayConfiguratorTest() {}
341
SetUp()342 virtual void SetUp() OVERRIDE {
343 log_.reset(new ActionLogger());
344
345 native_display_delegate_ = new TestNativeDisplayDelegate(log_.get());
346 configurator_.SetDelegateForTesting(
347 scoped_ptr<NativeDisplayDelegate>(native_display_delegate_));
348
349 configurator_.set_state_controller(&state_controller_);
350 configurator_.set_mirroring_controller(&mirroring_controller_);
351
352 std::vector<const DisplayMode*> modes;
353 modes.push_back(&small_mode_);
354
355 TestDisplaySnapshot* o = &outputs_[0];
356 o->set_current_mode(&small_mode_);
357 o->set_native_mode(&small_mode_);
358 o->set_modes(modes);
359 o->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL);
360 o->set_is_aspect_preserving_scaling(true);
361 o->set_display_id(123);
362 o->set_has_proper_display_id(true);
363
364 o = &outputs_[1];
365 o->set_current_mode(&big_mode_);
366 o->set_native_mode(&big_mode_);
367 modes.push_back(&big_mode_);
368 o->set_modes(modes);
369 o->set_type(DISPLAY_CONNECTION_TYPE_HDMI);
370 o->set_is_aspect_preserving_scaling(true);
371 o->set_display_id(456);
372 o->set_has_proper_display_id(true);
373
374 UpdateOutputs(2, false);
375 }
376
377 // Predefined modes that can be used by outputs.
378 const DisplayMode small_mode_;
379 const DisplayMode big_mode_;
380
381 protected:
382 // Configures |native_display_delegate_| to return the first |num_outputs|
383 // entries from
384 // |outputs_|. If |send_events| is true, also sends screen-change and
385 // output-change events to |configurator_| and triggers the configure
386 // timeout if one was scheduled.
UpdateOutputs(size_t num_outputs,bool send_events)387 void UpdateOutputs(size_t num_outputs, bool send_events) {
388 ASSERT_LE(num_outputs, arraysize(outputs_));
389 std::vector<DisplaySnapshot*> outputs;
390 for (size_t i = 0; i < num_outputs; ++i)
391 outputs.push_back(&outputs_[i]);
392 native_display_delegate_->set_outputs(outputs);
393
394 if (send_events) {
395 configurator_.OnConfigurationChanged();
396 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
397 }
398 }
399
400 // Initializes |configurator_| with a single internal display.
InitWithSingleOutput()401 void InitWithSingleOutput() {
402 UpdateOutputs(1, false);
403 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
404 configurator_.Init(false);
405 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
406 configurator_.ForceInitialConfigure(0);
407 EXPECT_EQ(
408 JoinActions(
409 kGrab,
410 kInitXRandR,
411 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL)
412 .c_str(),
413 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
414 kForceDPMS,
415 kUngrab,
416 NULL),
417 log_->GetActionsAndClear());
418 }
419
420 base::MessageLoop message_loop_;
421 TestStateController state_controller_;
422 TestMirroringController mirroring_controller_;
423 DisplayConfigurator configurator_;
424 TestObserver observer_;
425 scoped_ptr<ActionLogger> log_;
426 TestNativeDisplayDelegate* native_display_delegate_; // not owned
427 DisplayConfigurator::TestApi test_api_;
428
429 TestDisplaySnapshot outputs_[2];
430
431 private:
432 DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest);
433 };
434
435 } // namespace
436
TEST_F(DisplayConfiguratorTest,FindDisplayModeMatchingSize)437 TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) {
438 ScopedVector<const DisplayMode> modes;
439
440 // Fields are width, height, interlaced, refresh rate.
441 modes.push_back(new DisplayMode(gfx::Size(1920, 1200), false, 60.0));
442 // Different rates.
443 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 30.0));
444 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 50.0));
445 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
446 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 0.0));
447 // Interlaced vs non-interlaced.
448 modes.push_back(new DisplayMode(gfx::Size(1280, 720), true, 60.0));
449 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 40.0));
450 // Interlaced only.
451 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 0.0));
452 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 40.0));
453 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 60.0));
454 // Mixed.
455 modes.push_back(new DisplayMode(gfx::Size(1024, 600), true, 60.0));
456 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 40.0));
457 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 50.0));
458 // Just one interlaced mode.
459 modes.push_back(new DisplayMode(gfx::Size(640, 480), true, 60.0));
460 // Refresh rate not available.
461 modes.push_back(new DisplayMode(gfx::Size(320, 200), false, 0.0));
462
463 TestDisplaySnapshot output;
464 output.set_modes(modes.get());
465
466 EXPECT_EQ(modes[0],
467 DisplayConfigurator::FindDisplayModeMatchingSize(
468 output, gfx::Size(1920, 1200)));
469
470 // Should pick highest refresh rate.
471 EXPECT_EQ(modes[2],
472 DisplayConfigurator::FindDisplayModeMatchingSize(
473 output, gfx::Size(1920, 1080)));
474
475 // Should pick non-interlaced mode.
476 EXPECT_EQ(modes[6],
477 DisplayConfigurator::FindDisplayModeMatchingSize(
478 output, gfx::Size(1280, 720)));
479
480 // Interlaced only. Should pick one with the highest refresh rate in
481 // interlaced mode.
482 EXPECT_EQ(modes[9],
483 DisplayConfigurator::FindDisplayModeMatchingSize(
484 output, gfx::Size(1024, 768)));
485
486 // Mixed: Should pick one with the highest refresh rate in
487 // interlaced mode.
488 EXPECT_EQ(modes[12],
489 DisplayConfigurator::FindDisplayModeMatchingSize(
490 output, gfx::Size(1024, 600)));
491
492 // Just one interlaced mode.
493 EXPECT_EQ(modes[13],
494 DisplayConfigurator::FindDisplayModeMatchingSize(
495 output, gfx::Size(640, 480)));
496
497 // Refresh rate not available.
498 EXPECT_EQ(modes[14],
499 DisplayConfigurator::FindDisplayModeMatchingSize(
500 output, gfx::Size(320, 200)));
501
502 // No mode found.
503 EXPECT_EQ(NULL,
504 DisplayConfigurator::FindDisplayModeMatchingSize(
505 output, gfx::Size(1440, 900)));
506 }
507
TEST_F(DisplayConfiguratorTest,ConnectSecondOutput)508 TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
509 InitWithSingleOutput();
510
511 // Connect a second output and check that the configurator enters
512 // extended mode.
513 observer_.Reset();
514 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
515 UpdateOutputs(2, true);
516 const int kDualHeight = small_mode_.size().height() +
517 DisplayConfigurator::kVerticalGap +
518 big_mode_.size().height();
519 EXPECT_EQ(
520 JoinActions(
521 kGrab,
522 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
523 &outputs_[0],
524 &outputs_[1]).c_str(),
525 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
526 GetCrtcAction(outputs_[1],
527 &big_mode_,
528 gfx::Point(0,
529 small_mode_.size().height() +
530 DisplayConfigurator::kVerticalGap))
531 .c_str(),
532 kUngrab,
533 NULL),
534 log_->GetActionsAndClear());
535 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
536 EXPECT_EQ(1, observer_.num_changes());
537
538 observer_.Reset();
539 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
540 EXPECT_EQ(
541 JoinActions(
542 kGrab,
543 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
544 .c_str(),
545 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
546 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
547 kUngrab,
548 NULL),
549 log_->GetActionsAndClear());
550 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
551 EXPECT_EQ(1, observer_.num_changes());
552
553 // Disconnect the second output.
554 observer_.Reset();
555 UpdateOutputs(1, true);
556 EXPECT_EQ(
557 JoinActions(
558 kGrab,
559 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
560 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
561 kUngrab,
562 NULL),
563 log_->GetActionsAndClear());
564 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
565 EXPECT_EQ(1, observer_.num_changes());
566
567 // Get rid of shared modes to force software mirroring.
568 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
569 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
570 UpdateOutputs(2, true);
571 EXPECT_EQ(
572 JoinActions(
573 kGrab,
574 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
575 &outputs_[0],
576 &outputs_[1]).c_str(),
577 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
578 GetCrtcAction(outputs_[1],
579 &big_mode_,
580 gfx::Point(0,
581 small_mode_.size().height() +
582 DisplayConfigurator::kVerticalGap))
583 .c_str(),
584 kUngrab,
585 NULL),
586 log_->GetActionsAndClear());
587 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
588
589 observer_.Reset();
590 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
591 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
592 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
593 configurator_.display_state());
594 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
595 EXPECT_EQ(1, observer_.num_changes());
596
597 // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
598 observer_.Reset();
599 EXPECT_TRUE(
600 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
601 EXPECT_EQ(JoinActions(NULL), log_->GetActionsAndClear());
602 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
603 EXPECT_EQ(1, observer_.num_changes());
604
605 // Set back to software mirror mode.
606 observer_.Reset();
607 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
608 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
609 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
610 configurator_.display_state());
611 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
612 EXPECT_EQ(1, observer_.num_changes());
613
614 // Disconnect the second output.
615 observer_.Reset();
616 UpdateOutputs(1, true);
617 EXPECT_EQ(
618 JoinActions(
619 kGrab,
620 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
621 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
622 kUngrab,
623 NULL),
624 log_->GetActionsAndClear());
625 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
626 EXPECT_EQ(1, observer_.num_changes());
627 }
628
TEST_F(DisplayConfiguratorTest,SetDisplayPower)629 TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
630 InitWithSingleOutput();
631
632 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
633 observer_.Reset();
634 UpdateOutputs(2, true);
635 EXPECT_EQ(
636 JoinActions(
637 kGrab,
638 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
639 .c_str(),
640 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
641 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
642 kUngrab,
643 NULL),
644 log_->GetActionsAndClear());
645 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
646 EXPECT_EQ(1, observer_.num_changes());
647
648 // Turning off the internal display should switch the external display to
649 // its native mode.
650 observer_.Reset();
651 configurator_.SetDisplayPower(
652 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
653 DisplayConfigurator::kSetDisplayPowerNoFlags);
654 EXPECT_EQ(
655 JoinActions(
656 kGrab,
657 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
658 .c_str(),
659 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
660 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
661 kForceDPMS,
662 kUngrab,
663 NULL),
664 log_->GetActionsAndClear());
665 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
666 EXPECT_EQ(1, observer_.num_changes());
667
668 // When all displays are turned off, the framebuffer should switch back
669 // to the mirrored size.
670 observer_.Reset();
671 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
672 DisplayConfigurator::kSetDisplayPowerNoFlags);
673 EXPECT_EQ(
674 JoinActions(kGrab,
675 GetFramebufferAction(
676 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
677 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
678 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
679 kUngrab,
680 NULL),
681 log_->GetActionsAndClear());
682 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
683 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
684 EXPECT_EQ(1, observer_.num_changes());
685
686 // Turn all displays on and check that mirroring is still used.
687 observer_.Reset();
688 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
689 DisplayConfigurator::kSetDisplayPowerNoFlags);
690 EXPECT_EQ(
691 JoinActions(
692 kGrab,
693 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
694 .c_str(),
695 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
696 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
697 kForceDPMS,
698 kUngrab,
699 NULL),
700 log_->GetActionsAndClear());
701 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
702 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
703 EXPECT_EQ(1, observer_.num_changes());
704
705 // Get rid of shared modes to force software mirroring.
706 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
707 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
708 observer_.Reset();
709 UpdateOutputs(2, true);
710 const int kDualHeight = small_mode_.size().height() +
711 DisplayConfigurator::kVerticalGap +
712 big_mode_.size().height();
713 EXPECT_EQ(
714 JoinActions(
715 kGrab,
716 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
717 &outputs_[0],
718 &outputs_[1]).c_str(),
719 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
720 GetCrtcAction(outputs_[1],
721 &big_mode_,
722 gfx::Point(0,
723 small_mode_.size().height() +
724 DisplayConfigurator::kVerticalGap))
725 .c_str(),
726 kUngrab,
727 NULL),
728 log_->GetActionsAndClear());
729 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
730 configurator_.display_state());
731 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
732 EXPECT_EQ(1, observer_.num_changes());
733
734 // Turning off the internal display should switch the external display to
735 // its native mode.
736 observer_.Reset();
737 configurator_.SetDisplayPower(
738 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
739 DisplayConfigurator::kSetDisplayPowerNoFlags);
740 EXPECT_EQ(
741 JoinActions(
742 kGrab,
743 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
744 .c_str(),
745 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
746 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
747 kForceDPMS,
748 kUngrab,
749 NULL),
750 log_->GetActionsAndClear());
751 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
752 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
753 EXPECT_EQ(1, observer_.num_changes());
754
755 // When all displays are turned off, the framebuffer should switch back
756 // to the extended + software mirroring.
757 observer_.Reset();
758 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
759 DisplayConfigurator::kSetDisplayPowerNoFlags);
760 EXPECT_EQ(
761 JoinActions(
762 kGrab,
763 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
764 &outputs_[0],
765 &outputs_[1]).c_str(),
766 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
767 GetCrtcAction(outputs_[1],
768 NULL,
769 gfx::Point(0,
770 small_mode_.size().height() +
771 DisplayConfigurator::kVerticalGap))
772 .c_str(),
773 kUngrab,
774 NULL),
775 log_->GetActionsAndClear());
776 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
777 configurator_.display_state());
778 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
779 EXPECT_EQ(1, observer_.num_changes());
780
781 // Turn all displays on and check that mirroring is still used.
782 observer_.Reset();
783 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
784 DisplayConfigurator::kSetDisplayPowerNoFlags);
785 EXPECT_EQ(
786 JoinActions(
787 kGrab,
788 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
789 &outputs_[0],
790 &outputs_[1]).c_str(),
791 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
792 GetCrtcAction(outputs_[1],
793 &big_mode_,
794 gfx::Point(0,
795 small_mode_.size().height() +
796 DisplayConfigurator::kVerticalGap))
797 .c_str(),
798 kForceDPMS,
799 kUngrab,
800 NULL),
801 log_->GetActionsAndClear());
802 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
803 configurator_.display_state());
804 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
805 EXPECT_EQ(1, observer_.num_changes());
806 }
807
TEST_F(DisplayConfiguratorTest,SuspendAndResume)808 TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
809 InitWithSingleOutput();
810
811 // No preparation is needed before suspending when the display is already
812 // on. The configurator should still reprobe on resume in case a display
813 // was connected while suspended.
814 configurator_.SuspendDisplays();
815 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
816 configurator_.ResumeDisplays();
817 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
818 EXPECT_EQ(
819 JoinActions(
820 kGrab,
821 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
822 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
823 kForceDPMS,
824 kUngrab,
825 NULL),
826 log_->GetActionsAndClear());
827
828 // Now turn the display off before suspending and check that the
829 // configurator turns it back on and syncs with the server.
830 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
831 DisplayConfigurator::kSetDisplayPowerNoFlags);
832 EXPECT_EQ(
833 JoinActions(
834 kGrab,
835 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
836 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
837 kUngrab,
838 NULL),
839 log_->GetActionsAndClear());
840
841 configurator_.SuspendDisplays();
842 EXPECT_EQ(
843 JoinActions(
844 kGrab,
845 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
846 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
847 kForceDPMS,
848 kUngrab,
849 kSync,
850 NULL),
851 log_->GetActionsAndClear());
852
853 configurator_.ResumeDisplays();
854 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
855 EXPECT_EQ(
856 JoinActions(
857 kGrab,
858 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
859 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
860 kForceDPMS,
861 kUngrab,
862 NULL),
863 log_->GetActionsAndClear());
864
865 // If a second, external display is connected, the displays shouldn't be
866 // powered back on before suspending.
867 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
868 UpdateOutputs(2, true);
869 EXPECT_EQ(
870 JoinActions(
871 kGrab,
872 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
873 .c_str(),
874 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
875 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
876 kUngrab,
877 NULL),
878 log_->GetActionsAndClear());
879
880 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
881 DisplayConfigurator::kSetDisplayPowerNoFlags);
882 EXPECT_EQ(
883 JoinActions(kGrab,
884 GetFramebufferAction(
885 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
886 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
887 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
888 kUngrab,
889 NULL),
890 log_->GetActionsAndClear());
891
892 configurator_.SuspendDisplays();
893 EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL),
894 log_->GetActionsAndClear());
895
896 // If a display is disconnected while suspended, the configurator should
897 // pick up the change.
898 UpdateOutputs(1, false);
899 configurator_.ResumeDisplays();
900 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
901 EXPECT_EQ(
902 JoinActions(
903 kGrab,
904 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
905 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
906 kUngrab,
907 NULL),
908 log_->GetActionsAndClear());
909 }
910
TEST_F(DisplayConfiguratorTest,Headless)911 TEST_F(DisplayConfiguratorTest, Headless) {
912 UpdateOutputs(0, false);
913 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
914 configurator_.Init(false);
915 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
916 configurator_.ForceInitialConfigure(0);
917 EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab, NULL),
918 log_->GetActionsAndClear());
919
920 // Not much should happen when the display power state is changed while
921 // no displays are connected.
922 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
923 DisplayConfigurator::kSetDisplayPowerNoFlags);
924 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
925 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
926 DisplayConfigurator::kSetDisplayPowerNoFlags);
927 EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL),
928 log_->GetActionsAndClear());
929
930 // Connect an external display and check that it's configured correctly.
931 outputs_[0].set_current_mode(outputs_[1].current_mode());
932 outputs_[0].set_native_mode(outputs_[1].native_mode());
933 outputs_[0].set_modes(outputs_[1].modes());
934 outputs_[0].set_type(outputs_[1].type());
935
936 UpdateOutputs(1, true);
937 EXPECT_EQ(
938 JoinActions(
939 kGrab,
940 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
941 GetCrtcAction(outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
942 kUngrab,
943 NULL),
944 log_->GetActionsAndClear());
945 }
946
TEST_F(DisplayConfiguratorTest,StartWithTwoOutputs)947 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
948 UpdateOutputs(2, false);
949 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
950 configurator_.Init(false);
951 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
952
953 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
954 configurator_.ForceInitialConfigure(0);
955 EXPECT_EQ(
956 JoinActions(
957 kGrab,
958 kInitXRandR,
959 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
960 .c_str(),
961 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
962 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
963 kForceDPMS,
964 kUngrab,
965 NULL),
966 log_->GetActionsAndClear());
967 }
968
TEST_F(DisplayConfiguratorTest,InvalidMultipleDisplayStates)969 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
970 UpdateOutputs(0, false);
971 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
972 configurator_.Init(false);
973 configurator_.ForceInitialConfigure(0);
974 observer_.Reset();
975 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
976 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
977 EXPECT_FALSE(
978 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
979 EXPECT_FALSE(
980 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
981 EXPECT_EQ(1, observer_.num_changes());
982 EXPECT_EQ(3, observer_.num_failures());
983
984 UpdateOutputs(1, true);
985 observer_.Reset();
986 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
987 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
988 EXPECT_FALSE(
989 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
990 EXPECT_FALSE(
991 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
992 EXPECT_EQ(1, observer_.num_changes());
993 EXPECT_EQ(3, observer_.num_failures());
994
995 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
996 UpdateOutputs(2, true);
997 observer_.Reset();
998 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
999 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1000 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1001 EXPECT_TRUE(
1002 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1003 EXPECT_EQ(2, observer_.num_changes());
1004 EXPECT_EQ(2, observer_.num_failures());
1005 }
1006
TEST_F(DisplayConfiguratorTest,GetMultipleDisplayStateForDisplaysWithoutId)1007 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithoutId) {
1008 outputs_[0].set_has_proper_display_id(false);
1009 UpdateOutputs(2, false);
1010 configurator_.Init(false);
1011 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1012 configurator_.ForceInitialConfigure(0);
1013 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
1014 configurator_.display_state());
1015 }
1016
TEST_F(DisplayConfiguratorTest,GetMultipleDisplayStateForDisplaysWithId)1017 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithId) {
1018 outputs_[0].set_has_proper_display_id(true);
1019 UpdateOutputs(2, false);
1020 configurator_.Init(false);
1021 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1022 configurator_.ForceInitialConfigure(0);
1023 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1024 }
1025
TEST_F(DisplayConfiguratorTest,UpdateCachedOutputsEvenAfterFailure)1026 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
1027 InitWithSingleOutput();
1028 const DisplayConfigurator::DisplayStateList* cached =
1029 &configurator_.cached_displays();
1030 ASSERT_EQ(static_cast<size_t>(1), cached->size());
1031 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1032
1033 // After connecting a second output, check that it shows up in
1034 // |cached_displays_| even if an invalid state is requested.
1035 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1036 UpdateOutputs(2, true);
1037 cached = &configurator_.cached_displays();
1038 ASSERT_EQ(static_cast<size_t>(2), cached->size());
1039 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1040 EXPECT_EQ(outputs_[1].current_mode(), (*cached)[1].display->current_mode());
1041 }
1042
TEST_F(DisplayConfiguratorTest,PanelFitting)1043 TEST_F(DisplayConfiguratorTest, PanelFitting) {
1044 // Configure the internal display to support only the big mode and the
1045 // external display to support only the small mode.
1046 outputs_[0].set_current_mode(&big_mode_);
1047 outputs_[0].set_native_mode(&big_mode_);
1048 outputs_[0].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
1049
1050 outputs_[1].set_current_mode(&small_mode_);
1051 outputs_[1].set_native_mode(&small_mode_);
1052 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &small_mode_));
1053
1054 // The small mode should be added to the internal output when requesting
1055 // mirrored mode.
1056 UpdateOutputs(2, false);
1057 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1058 configurator_.Init(true /* is_panel_fitting_enabled */);
1059 configurator_.ForceInitialConfigure(0);
1060 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1061 EXPECT_EQ(
1062 JoinActions(
1063 kGrab,
1064 kInitXRandR,
1065 GetAddOutputModeAction(outputs_[0], &small_mode_).c_str(),
1066 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1067 .c_str(),
1068 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1069 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1070 kForceDPMS,
1071 kUngrab,
1072 NULL),
1073 log_->GetActionsAndClear());
1074
1075 // Both outputs should be using the small mode.
1076 ASSERT_EQ(1, observer_.num_changes());
1077 ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
1078 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[0].mirror_mode);
1079 EXPECT_EQ(&small_mode_,
1080 observer_.latest_outputs()[0].display->current_mode());
1081 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[1].mirror_mode);
1082 EXPECT_EQ(&small_mode_,
1083 observer_.latest_outputs()[1].display->current_mode());
1084
1085 // Also check that the newly-added small mode is present in the internal
1086 // snapshot that was passed to the observer (http://crbug.com/289159).
1087 const DisplayConfigurator::DisplayState& state =
1088 observer_.latest_outputs()[0];
1089 ASSERT_NE(state.display->modes().end(),
1090 std::find(state.display->modes().begin(),
1091 state.display->modes().end(),
1092 &small_mode_));
1093 }
1094
TEST_F(DisplayConfiguratorTest,ContentProtection)1095 TEST_F(DisplayConfiguratorTest, ContentProtection) {
1096 configurator_.Init(false);
1097 configurator_.ForceInitialConfigure(0);
1098 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1099
1100 DisplayConfigurator::ContentProtectionClientId id =
1101 configurator_.RegisterContentProtectionClient();
1102 EXPECT_NE(0u, id);
1103
1104 // One output.
1105 UpdateOutputs(1, true);
1106 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1107 uint32_t link_mask = 0;
1108 uint32_t protection_mask = 0;
1109 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1110 id, outputs_[0].display_id(), &link_mask, &protection_mask));
1111 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), link_mask);
1112 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1113 protection_mask);
1114 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1115
1116 // Two outputs.
1117 UpdateOutputs(2, true);
1118 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1119 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1120 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1121 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1122 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1123 protection_mask);
1124 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1125
1126 EXPECT_TRUE(configurator_.EnableContentProtection(
1127 id, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1128 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED),
1129 log_->GetActionsAndClear());
1130
1131 // Enable protection.
1132 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1133 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1134 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1135 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1136 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP),
1137 protection_mask);
1138 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1139
1140 // Protections should be disabled after unregister.
1141 configurator_.UnregisterContentProtectionClient(id);
1142 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED),
1143 log_->GetActionsAndClear());
1144 }
1145
TEST_F(DisplayConfiguratorTest,ContentProtectionTwoClients)1146 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
1147 DisplayConfigurator::ContentProtectionClientId client1 =
1148 configurator_.RegisterContentProtectionClient();
1149 DisplayConfigurator::ContentProtectionClientId client2 =
1150 configurator_.RegisterContentProtectionClient();
1151 EXPECT_NE(client1, client2);
1152
1153 configurator_.Init(false);
1154 configurator_.ForceInitialConfigure(0);
1155 UpdateOutputs(2, true);
1156 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1157
1158 // Clients never know state enableness for methods that they didn't request.
1159 EXPECT_TRUE(configurator_.EnableContentProtection(
1160 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1161 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1162 log_->GetActionsAndClear());
1163 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1164
1165 uint32_t link_mask = 0;
1166 uint32_t protection_mask = 0;
1167 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1168 client1, outputs_[1].display_id(), &link_mask, &protection_mask));
1169 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1170 EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, protection_mask);
1171
1172 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1173 client2, outputs_[1].display_id(), &link_mask, &protection_mask));
1174 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1175 EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, protection_mask);
1176
1177 // Protections will be disabled only if no more clients request them.
1178 EXPECT_TRUE(configurator_.EnableContentProtection(
1179 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1180 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1181 EXPECT_TRUE(configurator_.EnableContentProtection(
1182 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1183 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED).c_str(),
1184 log_->GetActionsAndClear());
1185 }
1186
TEST_F(DisplayConfiguratorTest,ContentProtectionTwoClientsEnable)1187 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClientsEnable) {
1188 DisplayConfigurator::ContentProtectionClientId client1 =
1189 configurator_.RegisterContentProtectionClient();
1190 DisplayConfigurator::ContentProtectionClientId client2 =
1191 configurator_.RegisterContentProtectionClient();
1192 EXPECT_NE(client1, client2);
1193
1194 configurator_.Init(false);
1195 configurator_.ForceInitialConfigure(0);
1196 UpdateOutputs(2, true);
1197 log_->GetActionsAndClear();
1198
1199 // Only enable once if HDCP is enabling.
1200 EXPECT_TRUE(configurator_.EnableContentProtection(
1201 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1202 native_display_delegate_->set_hdcp_state(HDCP_STATE_DESIRED);
1203 EXPECT_TRUE(configurator_.EnableContentProtection(
1204 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1205 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1206 log_->GetActionsAndClear());
1207 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1208
1209 // Don't enable again if HDCP is already active.
1210 EXPECT_TRUE(configurator_.EnableContentProtection(
1211 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1212 EXPECT_TRUE(configurator_.EnableContentProtection(
1213 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1214 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1215 }
1216
TEST_F(DisplayConfiguratorTest,HandleConfigureCrtcFailure)1217 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
1218 InitWithSingleOutput();
1219
1220 ScopedVector<const DisplayMode> modes;
1221 // The first mode is the mode we are requesting DisplayConfigurator to choose.
1222 // The test will be setup so that this mode will fail and it will have to
1223 // choose the next best option.
1224 modes.push_back(new DisplayMode(gfx::Size(2560, 1600), false, 60.0));
1225 modes.push_back(new DisplayMode(gfx::Size(1024, 768), false, 60.0));
1226 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 60.0));
1227 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 60.0));
1228 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
1229
1230 for (unsigned int i = 0; i < arraysize(outputs_); i++) {
1231 outputs_[i].set_modes(modes.get());
1232 outputs_[i].set_current_mode(modes[0]);
1233 outputs_[i].set_native_mode(modes[0]);
1234 }
1235
1236 // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is
1237 // probably unrealistic but we want to make sure any assumptions don't creep
1238 // in.
1239 native_display_delegate_->set_max_configurable_pixels(
1240 modes[2]->size().GetArea());
1241 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1242 UpdateOutputs(1, true);
1243
1244 EXPECT_EQ(
1245 JoinActions(
1246 kGrab,
1247 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
1248 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1249 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1250 GetCrtcAction(outputs_[0], modes[2], gfx::Point(0, 0)).c_str(),
1251 kUngrab,
1252 NULL),
1253 log_->GetActionsAndClear());
1254
1255 // This test should attempt to configure a mirror mode that will not succeed
1256 // and should end up in extended mode.
1257 native_display_delegate_->set_max_configurable_pixels(
1258 modes[3]->size().GetArea());
1259 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1260 UpdateOutputs(2, true);
1261
1262 EXPECT_EQ(
1263 JoinActions(
1264 kGrab,
1265 GetFramebufferAction(modes[0]->size(), &outputs_[0], &outputs_[1])
1266 .c_str(),
1267 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1268 // First mode tried is expected to fail and it will
1269 // retry wil the 4th mode in the list.
1270 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1271 // Then attempt to configure crtc1 with the first mode.
1272 GetCrtcAction(outputs_[1], modes[0], gfx::Point(0, 0)).c_str(),
1273 GetCrtcAction(outputs_[1], modes[3], gfx::Point(0, 0)).c_str(),
1274 // Since it was requested to go into mirror mode
1275 // and the configured modes were different, it
1276 // should now try and setup a valid configurable
1277 // extended mode.
1278 GetFramebufferAction(
1279 gfx::Size(modes[0]->size().width(),
1280 modes[0]->size().height() + modes[0]->size().height() +
1281 DisplayConfigurator::kVerticalGap),
1282 &outputs_[0],
1283 &outputs_[1]).c_str(),
1284 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1285 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1286 GetCrtcAction(outputs_[1],
1287 modes[0],
1288 gfx::Point(0,
1289 modes[0]->size().height() +
1290 DisplayConfigurator::kVerticalGap))
1291 .c_str(),
1292 GetCrtcAction(outputs_[1],
1293 modes[3],
1294 gfx::Point(0,
1295 modes[0]->size().height() +
1296 DisplayConfigurator::kVerticalGap))
1297 .c_str(),
1298 kUngrab,
1299 NULL),
1300 log_->GetActionsAndClear());
1301 }
1302
1303 // Tests that power state requests are saved after failed configuration attempts
1304 // so they can be reused later: http://crosbug.com/p/31571
TEST_F(DisplayConfiguratorTest,SaveDisplayPowerStateOnConfigFailure)1305 TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) {
1306 // Start out with two displays in extended mode.
1307 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1308 configurator_.Init(false);
1309 configurator_.ForceInitialConfigure(0);
1310 log_->GetActionsAndClear();
1311
1312 // Turn off the internal display, simulating docked mode.
1313 EXPECT_TRUE(configurator_.SetDisplayPower(
1314 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
1315 DisplayConfigurator::kSetDisplayPowerNoFlags));
1316 log_->GetActionsAndClear();
1317
1318 // Make all subsequent configuration requests fail and try to turn the
1319 // internal display back on.
1320 native_display_delegate_->set_max_configurable_pixels(1);
1321 EXPECT_FALSE(configurator_.SetDisplayPower(
1322 chromeos::DISPLAY_POWER_ALL_ON,
1323 DisplayConfigurator::kSetDisplayPowerNoFlags));
1324 log_->GetActionsAndClear();
1325
1326 // Simulate the external display getting disconnected and check that the
1327 // internal display is turned on (i.e. DISPLAY_POWER_ALL_ON is used) rather
1328 // than the earlier DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON state.
1329 native_display_delegate_->set_max_configurable_pixels(0);
1330 UpdateOutputs(1, true);
1331 EXPECT_EQ(
1332 JoinActions(
1333 kGrab,
1334 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
1335 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1336 kUngrab,
1337 NULL),
1338 log_->GetActionsAndClear());
1339 }
1340
1341 } // namespace ui
1342