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