• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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