| OLD | NEW | 
 | (Empty) | 
|     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 <stddef.h> |  | 
|     8 #include <stdint.h> |  | 
|     9  |  | 
|    10 #include "base/macros.h" |  | 
|    11 #include "base/memory/ptr_util.h" |  | 
|    12 #include "base/memory/scoped_vector.h" |  | 
|    13 #include "base/message_loop/message_loop.h" |  | 
|    14 #include "base/run_loop.h" |  | 
|    15 #include "testing/gtest/include/gtest/gtest.h" |  | 
|    16 #include "ui/display/chromeos/test/action_logger_util.h" |  | 
|    17 #include "ui/display/chromeos/test/test_native_display_delegate.h" |  | 
|    18 #include "ui/display/fake_display_snapshot.h" |  | 
|    19 #include "ui/display/util/display_util.h" |  | 
|    20  |  | 
|    21 namespace ui { |  | 
|    22 namespace test { |  | 
|    23  |  | 
|    24 namespace { |  | 
|    25  |  | 
|    26 int64_t kDisplayIds[3] = {123, 456, 789}; |  | 
|    27  |  | 
|    28 std::unique_ptr<ui::DisplayMode> MakeDisplayMode(int width, |  | 
|    29                                                  int height, |  | 
|    30                                                  bool is_interlaced, |  | 
|    31                                                  float refresh_rate) { |  | 
|    32   return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), |  | 
|    33                                            is_interlaced, refresh_rate); |  | 
|    34 } |  | 
|    35  |  | 
|    36 enum CallbackResult { |  | 
|    37   CALLBACK_FAILURE, |  | 
|    38   CALLBACK_SUCCESS, |  | 
|    39   CALLBACK_NOT_CALLED, |  | 
|    40 }; |  | 
|    41  |  | 
|    42 // Expected immediate configurations should be done without any delays. |  | 
|    43 constexpr base::TimeDelta kNoDelay = base::TimeDelta::FromMilliseconds(0); |  | 
|    44  |  | 
|    45 // The expected configuration delay when resuming from suspend while in 2+ |  | 
|    46 // display mode. |  | 
|    47 constexpr base::TimeDelta kLongDelay = base::TimeDelta::FromMilliseconds( |  | 
|    48     DisplayConfigurator::kResumeConfigureMultiDisplayDelayMs); |  | 
|    49  |  | 
|    50 class TestObserver : public DisplayConfigurator::Observer { |  | 
|    51  public: |  | 
|    52   explicit TestObserver(DisplayConfigurator* configurator) |  | 
|    53       : configurator_(configurator) { |  | 
|    54     Reset(); |  | 
|    55     configurator_->AddObserver(this); |  | 
|    56   } |  | 
|    57   ~TestObserver() override { configurator_->RemoveObserver(this); } |  | 
|    58  |  | 
|    59   int num_changes() const { return num_changes_; } |  | 
|    60   int num_failures() const { return num_failures_; } |  | 
|    61   const DisplayConfigurator::DisplayStateList& latest_outputs() const { |  | 
|    62     return latest_outputs_; |  | 
|    63   } |  | 
|    64   MultipleDisplayState latest_failed_state() const { |  | 
|    65     return latest_failed_state_; |  | 
|    66   } |  | 
|    67  |  | 
|    68   void Reset() { |  | 
|    69     num_changes_ = 0; |  | 
|    70     num_failures_ = 0; |  | 
|    71     latest_outputs_.clear(); |  | 
|    72     latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID; |  | 
|    73   } |  | 
|    74  |  | 
|    75   // DisplayConfigurator::Observer overrides: |  | 
|    76   void OnDisplayModeChanged( |  | 
|    77       const DisplayConfigurator::DisplayStateList& outputs) override { |  | 
|    78     num_changes_++; |  | 
|    79     latest_outputs_ = outputs; |  | 
|    80   } |  | 
|    81  |  | 
|    82   void OnDisplayModeChangeFailed( |  | 
|    83       const DisplayConfigurator::DisplayStateList& outputs, |  | 
|    84       MultipleDisplayState failed_new_state) override { |  | 
|    85     num_failures_++; |  | 
|    86     latest_failed_state_ = failed_new_state; |  | 
|    87   } |  | 
|    88  |  | 
|    89  private: |  | 
|    90   DisplayConfigurator* configurator_;  // Not owned. |  | 
|    91  |  | 
|    92   // Number of times that OnDisplayMode*() has been called. |  | 
|    93   int num_changes_; |  | 
|    94   int num_failures_; |  | 
|    95  |  | 
|    96   // Parameters most recently passed to OnDisplayMode*(). |  | 
|    97   DisplayConfigurator::DisplayStateList latest_outputs_; |  | 
|    98   MultipleDisplayState latest_failed_state_; |  | 
|    99  |  | 
|   100   DISALLOW_COPY_AND_ASSIGN(TestObserver); |  | 
|   101 }; |  | 
|   102  |  | 
|   103 class TestStateController : public DisplayConfigurator::StateController { |  | 
|   104  public: |  | 
|   105   TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {} |  | 
|   106   ~TestStateController() override {} |  | 
|   107  |  | 
|   108   void set_state(MultipleDisplayState state) { state_ = state; } |  | 
|   109  |  | 
|   110   // DisplayConfigurator::StateController overrides: |  | 
|   111   MultipleDisplayState GetStateForDisplayIds( |  | 
|   112       const DisplayConfigurator::DisplayStateList& outputs) const override { |  | 
|   113     return state_; |  | 
|   114   } |  | 
|   115   bool GetResolutionForDisplayId(int64_t display_id, |  | 
|   116                                  gfx::Size* size) const override { |  | 
|   117     return false; |  | 
|   118   } |  | 
|   119  |  | 
|   120  private: |  | 
|   121   MultipleDisplayState state_; |  | 
|   122  |  | 
|   123   DISALLOW_COPY_AND_ASSIGN(TestStateController); |  | 
|   124 }; |  | 
|   125  |  | 
|   126 class TestMirroringController |  | 
|   127     : public DisplayConfigurator::SoftwareMirroringController { |  | 
|   128  public: |  | 
|   129   TestMirroringController() : software_mirroring_enabled_(false) {} |  | 
|   130   ~TestMirroringController() override {} |  | 
|   131  |  | 
|   132   void SetSoftwareMirroring(bool enabled) override { |  | 
|   133     software_mirroring_enabled_ = enabled; |  | 
|   134   } |  | 
|   135  |  | 
|   136   bool SoftwareMirroringEnabled() const override { |  | 
|   137     return software_mirroring_enabled_; |  | 
|   138   } |  | 
|   139  |  | 
|   140  private: |  | 
|   141   bool software_mirroring_enabled_; |  | 
|   142  |  | 
|   143   DISALLOW_COPY_AND_ASSIGN(TestMirroringController); |  | 
|   144 }; |  | 
|   145  |  | 
|   146 // Abstracts waiting for the display configuration to be completed and getting |  | 
|   147 // the time it took to complete. |  | 
|   148 class ConfigurationWaiter { |  | 
|   149  public: |  | 
|   150   ConfigurationWaiter(DisplayConfigurator::TestApi* test_api) |  | 
|   151       : on_configured_callback_(base::Bind(&ConfigurationWaiter::OnConfigured, |  | 
|   152                                            base::Unretained(this))), |  | 
|   153         test_api_(test_api), |  | 
|   154         callback_result_(CALLBACK_NOT_CALLED) {} |  | 
|   155  |  | 
|   156   ~ConfigurationWaiter() = default; |  | 
|   157  |  | 
|   158   const DisplayConfigurator::ConfigurationCallback& on_configuration_callback() |  | 
|   159       const { |  | 
|   160     return on_configured_callback_; |  | 
|   161   } |  | 
|   162  |  | 
|   163   CallbackResult callback_result() const { return callback_result_; } |  | 
|   164  |  | 
|   165   void Reset() { callback_result_ = CALLBACK_NOT_CALLED; } |  | 
|   166  |  | 
|   167   // Simulates waiting for the next configuration. If an async task is pending, |  | 
|   168   // runs it and returns base::TimeDelta(). Otherwise, triggers the |  | 
|   169   // configuration timer and returns its delay. If the timer wasn't running, |  | 
|   170   // returns base::TimeDelta::Max(). |  | 
|   171   base::TimeDelta Wait() WARN_UNUSED_RESULT { |  | 
|   172     base::RunLoop().RunUntilIdle(); |  | 
|   173     if (callback_result_ != CALLBACK_NOT_CALLED) |  | 
|   174       return base::TimeDelta(); |  | 
|   175  |  | 
|   176     const base::TimeDelta delay = test_api_->GetConfigureDelay(); |  | 
|   177     if (!test_api_->TriggerConfigureTimeout()) |  | 
|   178       return base::TimeDelta::Max(); |  | 
|   179  |  | 
|   180     return delay; |  | 
|   181   } |  | 
|   182  |  | 
|   183  private: |  | 
|   184   void OnConfigured(bool status) { |  | 
|   185     CHECK_EQ(callback_result_, CALLBACK_NOT_CALLED); |  | 
|   186     callback_result_ = status ? CALLBACK_SUCCESS : CALLBACK_FAILURE; |  | 
|   187   } |  | 
|   188  |  | 
|   189   // Passed with configuration requests to run OnConfigured(). |  | 
|   190   const DisplayConfigurator::ConfigurationCallback on_configured_callback_; |  | 
|   191  |  | 
|   192   DisplayConfigurator::TestApi* test_api_;  // Not owned. |  | 
|   193  |  | 
|   194   // The status of the display configuration. |  | 
|   195   CallbackResult callback_result_; |  | 
|   196  |  | 
|   197   DISALLOW_COPY_AND_ASSIGN(ConfigurationWaiter); |  | 
|   198 }; |  | 
|   199  |  | 
|   200 class DisplayConfiguratorTest : public testing::Test { |  | 
|   201  public: |  | 
|   202   DisplayConfiguratorTest() |  | 
|   203       : small_mode_(gfx::Size(1366, 768), false, 60.0f), |  | 
|   204         big_mode_(gfx::Size(2560, 1600), false, 60.0f), |  | 
|   205         observer_(&configurator_), |  | 
|   206         test_api_(&configurator_), |  | 
|   207         config_waiter_(&test_api_), |  | 
|   208         enable_content_protection_status_(0), |  | 
|   209         enable_content_protection_call_count_(0), |  | 
|   210         query_content_protection_call_count_(0), |  | 
|   211         display_control_result_(CALLBACK_NOT_CALLED) {} |  | 
|   212   ~DisplayConfiguratorTest() override {} |  | 
|   213  |  | 
|   214   void SetUp() override { |  | 
|   215     log_.reset(new ActionLogger()); |  | 
|   216  |  | 
|   217     native_display_delegate_ = new TestNativeDisplayDelegate(log_.get()); |  | 
|   218     configurator_.SetDelegateForTesting( |  | 
|   219         std::unique_ptr<NativeDisplayDelegate>(native_display_delegate_)); |  | 
|   220  |  | 
|   221     configurator_.set_state_controller(&state_controller_); |  | 
|   222     configurator_.set_mirroring_controller(&mirroring_controller_); |  | 
|   223  |  | 
|   224     outputs_[0] = display::FakeDisplaySnapshot::Builder() |  | 
|   225                       .SetId(kDisplayIds[0]) |  | 
|   226                       .SetNativeMode(small_mode_.Clone()) |  | 
|   227                       .SetCurrentMode(small_mode_.Clone()) |  | 
|   228                       .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL) |  | 
|   229                       .SetIsAspectPerservingScaling(true) |  | 
|   230                       .Build(); |  | 
|   231  |  | 
|   232     outputs_[1] = display::FakeDisplaySnapshot::Builder() |  | 
|   233                       .SetId(kDisplayIds[1]) |  | 
|   234                       .SetNativeMode(big_mode_.Clone()) |  | 
|   235                       .SetCurrentMode(big_mode_.Clone()) |  | 
|   236                       .AddMode(small_mode_.Clone()) |  | 
|   237                       .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|   238                       .SetIsAspectPerservingScaling(true) |  | 
|   239                       .Build(); |  | 
|   240  |  | 
|   241     outputs_[2] = display::FakeDisplaySnapshot::Builder() |  | 
|   242                       .SetId(kDisplayIds[2]) |  | 
|   243                       .SetNativeMode(small_mode_.Clone()) |  | 
|   244                       .SetCurrentMode(small_mode_.Clone()) |  | 
|   245                       .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|   246                       .SetIsAspectPerservingScaling(true) |  | 
|   247                       .Build(); |  | 
|   248  |  | 
|   249     UpdateOutputs(2, false); |  | 
|   250   } |  | 
|   251  |  | 
|   252   void OnDisplayControlUpdated(bool status) { |  | 
|   253     display_control_result_ = (status ? CALLBACK_SUCCESS : CALLBACK_FAILURE); |  | 
|   254   } |  | 
|   255  |  | 
|   256   void EnableContentProtectionCallback(bool status) { |  | 
|   257     enable_content_protection_status_ = status; |  | 
|   258     enable_content_protection_call_count_++; |  | 
|   259   } |  | 
|   260  |  | 
|   261   void QueryContentProtectionCallback( |  | 
|   262       const DisplayConfigurator::QueryProtectionResponse& response) { |  | 
|   263     query_content_protection_response_ = response; |  | 
|   264     query_content_protection_call_count_++; |  | 
|   265   } |  | 
|   266  |  | 
|   267   // Predefined modes that can be used by outputs. |  | 
|   268   const DisplayMode small_mode_; |  | 
|   269   const DisplayMode big_mode_; |  | 
|   270  |  | 
|   271  protected: |  | 
|   272   // Configures |native_display_delegate_| to return the first |num_outputs| |  | 
|   273   // entries from |  | 
|   274   // |outputs_|. If |send_events| is true, also sends screen-change and |  | 
|   275   // output-change events to |configurator_| and triggers the configure |  | 
|   276   // timeout if one was scheduled. |  | 
|   277   void UpdateOutputs(size_t num_outputs, bool send_events) { |  | 
|   278     ASSERT_LE(num_outputs, arraysize(outputs_)); |  | 
|   279     std::vector<DisplaySnapshot*> outputs; |  | 
|   280     for (size_t i = 0; i < num_outputs; ++i) |  | 
|   281       outputs.push_back(outputs_[i].get()); |  | 
|   282     native_display_delegate_->set_outputs(outputs); |  | 
|   283  |  | 
|   284     if (send_events) { |  | 
|   285       configurator_.OnConfigurationChanged(); |  | 
|   286       EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |  | 
|   287     } |  | 
|   288   } |  | 
|   289  |  | 
|   290   void Init(bool panel_fitting_enabled) { |  | 
|   291     configurator_.Init(nullptr, panel_fitting_enabled); |  | 
|   292   } |  | 
|   293  |  | 
|   294   // Initializes |configurator_| with a single internal display. |  | 
|   295   void InitWithSingleOutput() { |  | 
|   296     UpdateOutputs(1, false); |  | 
|   297     EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|   298     configurator_.Init(nullptr, false); |  | 
|   299  |  | 
|   300     EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|   301     configurator_.ForceInitialConfigure(0); |  | 
|   302     EXPECT_EQ( |  | 
|   303         JoinActions( |  | 
|   304             kInitXRandR, kGrab, |  | 
|   305             GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   306                 .c_str(), |  | 
|   307             GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   308             kForceDPMS, kUngrab, nullptr), |  | 
|   309         log_->GetActionsAndClear()); |  | 
|   310   } |  | 
|   311  |  | 
|   312   CallbackResult PopDisplayControlResult() { |  | 
|   313     CallbackResult result = display_control_result_; |  | 
|   314     display_control_result_ = CALLBACK_NOT_CALLED; |  | 
|   315     return result; |  | 
|   316   } |  | 
|   317  |  | 
|   318   base::MessageLoop message_loop_; |  | 
|   319   TestStateController state_controller_; |  | 
|   320   TestMirroringController mirroring_controller_; |  | 
|   321   DisplayConfigurator configurator_; |  | 
|   322   TestObserver observer_; |  | 
|   323   std::unique_ptr<ActionLogger> log_; |  | 
|   324   TestNativeDisplayDelegate* native_display_delegate_;  // not owned |  | 
|   325   DisplayConfigurator::TestApi test_api_; |  | 
|   326   ConfigurationWaiter config_waiter_; |  | 
|   327   bool enable_content_protection_status_; |  | 
|   328   int enable_content_protection_call_count_; |  | 
|   329   DisplayConfigurator::QueryProtectionResponse |  | 
|   330       query_content_protection_response_; |  | 
|   331   int query_content_protection_call_count_; |  | 
|   332  |  | 
|   333   std::unique_ptr<DisplaySnapshot> outputs_[3]; |  | 
|   334  |  | 
|   335   CallbackResult display_control_result_; |  | 
|   336  |  | 
|   337  private: |  | 
|   338   DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest); |  | 
|   339 }; |  | 
|   340  |  | 
|   341 }  // namespace |  | 
|   342  |  | 
|   343 TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) { |  | 
|   344   std::unique_ptr<ui::DisplaySnapshot> output = |  | 
|   345       display::FakeDisplaySnapshot::Builder() |  | 
|   346           .SetId(kDisplayIds[0]) |  | 
|   347           .AddMode(MakeDisplayMode(1920, 1200, false, 60.0)) |  | 
|   348           .SetNativeMode(MakeDisplayMode(1920, 1200, false, 50.0)) |  | 
|   349           // Different rates. |  | 
|   350           .AddMode(MakeDisplayMode(1920, 1080, false, 30.0)) |  | 
|   351           .AddMode(MakeDisplayMode(1920, 1080, false, 50.0)) |  | 
|   352           .AddMode(MakeDisplayMode(1920, 1080, false, 40.0)) |  | 
|   353           .AddMode(MakeDisplayMode(1920, 1080, false, 0.0)) |  | 
|   354           // Interlaced vs non-interlaced. |  | 
|   355           .AddMode(MakeDisplayMode(1280, 720, true, 60.0)) |  | 
|   356           .AddMode(MakeDisplayMode(1280, 720, false, 40.0)) |  | 
|   357           // Interlaced only. |  | 
|   358           .AddMode(MakeDisplayMode(1024, 768, true, 0.0)) |  | 
|   359           .AddMode(MakeDisplayMode(1024, 768, true, 40.0)) |  | 
|   360           .AddMode(MakeDisplayMode(1024, 768, true, 60.0)) |  | 
|   361           // Mixed. |  | 
|   362           .AddMode(MakeDisplayMode(1024, 600, true, 60.0)) |  | 
|   363           .AddMode(MakeDisplayMode(1024, 600, false, 40.0)) |  | 
|   364           .AddMode(MakeDisplayMode(1024, 600, false, 50.0)) |  | 
|   365           // Just one interlaced mode. |  | 
|   366           .AddMode(MakeDisplayMode(640, 480, true, 60.0)) |  | 
|   367           // Refresh rate not available. |  | 
|   368           .AddMode(MakeDisplayMode(320, 200, false, 0.0)) |  | 
|   369           .Build(); |  | 
|   370  |  | 
|   371   const std::vector<std::unique_ptr<const DisplayMode>>& modes = |  | 
|   372       output->modes(); |  | 
|   373  |  | 
|   374   // Should pick native over highest refresh rate. |  | 
|   375   EXPECT_EQ(modes[1].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   376                                 *output, gfx::Size(1920, 1200))); |  | 
|   377  |  | 
|   378   // Should pick highest refresh rate. |  | 
|   379   EXPECT_EQ(modes[3].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   380                                 *output, gfx::Size(1920, 1080))); |  | 
|   381  |  | 
|   382   // Should pick non-interlaced mode. |  | 
|   383   EXPECT_EQ(modes[7].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   384                                 *output, gfx::Size(1280, 720))); |  | 
|   385  |  | 
|   386   // Interlaced only. Should pick one with the highest refresh rate in |  | 
|   387   // interlaced mode. |  | 
|   388   EXPECT_EQ(modes[10].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   389                                  *output, gfx::Size(1024, 768))); |  | 
|   390  |  | 
|   391   // Mixed: Should pick one with the highest refresh rate in |  | 
|   392   // interlaced mode. |  | 
|   393   EXPECT_EQ(modes[13].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   394                                  *output, gfx::Size(1024, 600))); |  | 
|   395  |  | 
|   396   // Just one interlaced mode. |  | 
|   397   EXPECT_EQ(modes[14].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   398                                  *output, gfx::Size(640, 480))); |  | 
|   399  |  | 
|   400   // Refresh rate not available. |  | 
|   401   EXPECT_EQ(modes[15].get(), DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   402                                  *output, gfx::Size(320, 200))); |  | 
|   403  |  | 
|   404   // No mode found. |  | 
|   405   EXPECT_EQ(nullptr, DisplayConfigurator::FindDisplayModeMatchingSize( |  | 
|   406                          *output, gfx::Size(1440, 900))); |  | 
|   407 } |  | 
|   408  |  | 
|   409 TEST_F(DisplayConfiguratorTest, EnableVirtualDisplay) { |  | 
|   410   InitWithSingleOutput(); |  | 
|   411  |  | 
|   412   observer_.Reset(); |  | 
|   413   const DisplayConfigurator::DisplayStateList& cached = |  | 
|   414       configurator_.cached_displays(); |  | 
|   415   ASSERT_EQ(static_cast<size_t>(1u), cached.size()); |  | 
|   416   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   417  |  | 
|   418   // Add virtual display. |  | 
|   419   int64_t virtual_display_id = |  | 
|   420       configurator_.AddVirtualDisplay(big_mode_.size()); |  | 
|   421   EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 1), virtual_display_id); |  | 
|   422   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   423   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   424             configurator_.display_state()); |  | 
|   425  |  | 
|   426   // Virtual should not trigger addition of added crtc but does change FB |  | 
|   427   // height. |  | 
|   428   const int kVirtualHeight = small_mode_.size().height() + |  | 
|   429                              DisplayConfigurator::kVerticalGap + |  | 
|   430                              big_mode_.size().height(); |  | 
|   431   EXPECT_EQ( |  | 
|   432       JoinActions( |  | 
|   433           kGrab, GetFramebufferAction( |  | 
|   434                      gfx::Size(big_mode_.size().width(), kVirtualHeight), |  | 
|   435                      outputs_[0].get(), nullptr) |  | 
|   436                      .c_str(), |  | 
|   437           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   438           kUngrab, nullptr), |  | 
|   439       log_->GetActionsAndClear()); |  | 
|   440   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   441   ASSERT_EQ(static_cast<size_t>(2u), cached.size()); |  | 
|   442   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   443   EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size()); |  | 
|   444   EXPECT_EQ(virtual_display_id, cached[1]->display_id()); |  | 
|   445  |  | 
|   446   // Remove virtual display. |  | 
|   447   observer_.Reset(); |  | 
|   448   EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id)); |  | 
|   449   EXPECT_EQ( |  | 
|   450       JoinActions( |  | 
|   451           kGrab, |  | 
|   452           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   453               .c_str(), |  | 
|   454           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   455           kUngrab, nullptr), |  | 
|   456       log_->GetActionsAndClear()); |  | 
|   457   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   458   ASSERT_EQ(static_cast<size_t>(1u), cached.size()); |  | 
|   459   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   460   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |  | 
|   461 } |  | 
|   462  |  | 
|   463 TEST_F(DisplayConfiguratorTest, EnableTwoVirtualDisplays) { |  | 
|   464   InitWithSingleOutput(); |  | 
|   465  |  | 
|   466   observer_.Reset(); |  | 
|   467   const DisplayConfigurator::DisplayStateList& cached = |  | 
|   468       configurator_.cached_displays(); |  | 
|   469   ASSERT_EQ(static_cast<size_t>(1u), cached.size()); |  | 
|   470   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   471  |  | 
|   472   // Add 1st virtual display. |  | 
|   473   int64_t virtual_display_id_1 = |  | 
|   474       configurator_.AddVirtualDisplay(big_mode_.size()); |  | 
|   475   EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 1), virtual_display_id_1); |  | 
|   476   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   477   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   478             configurator_.display_state()); |  | 
|   479  |  | 
|   480   // Virtual should not trigger addition of added crtc but does change FB |  | 
|   481   // height. |  | 
|   482   const int kSingleVirtualHeight = small_mode_.size().height() + |  | 
|   483                                    DisplayConfigurator::kVerticalGap + |  | 
|   484                                    big_mode_.size().height(); |  | 
|   485   EXPECT_EQ( |  | 
|   486       JoinActions( |  | 
|   487           kGrab, GetFramebufferAction( |  | 
|   488                      gfx::Size(big_mode_.size().width(), kSingleVirtualHeight), |  | 
|   489                      outputs_[0].get(), nullptr) |  | 
|   490                      .c_str(), |  | 
|   491           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   492           kUngrab, nullptr), |  | 
|   493       log_->GetActionsAndClear()); |  | 
|   494   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   495   ASSERT_EQ(static_cast<size_t>(2), cached.size()); |  | 
|   496   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   497   EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size()); |  | 
|   498   EXPECT_EQ(virtual_display_id_1, cached[1]->display_id()); |  | 
|   499  |  | 
|   500   // Add 2nd virtual display |  | 
|   501   int64_t virtual_display_id_2 = |  | 
|   502       configurator_.AddVirtualDisplay(big_mode_.size()); |  | 
|   503   EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 2), virtual_display_id_2); |  | 
|   504   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   505   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |  | 
|   506             configurator_.display_state()); |  | 
|   507  |  | 
|   508   const int kDualVirtualHeight = |  | 
|   509       small_mode_.size().height() + |  | 
|   510       (DisplayConfigurator::kVerticalGap + big_mode_.size().height()) * 2; |  | 
|   511   EXPECT_EQ( |  | 
|   512       JoinActions( |  | 
|   513           kGrab, GetFramebufferAction( |  | 
|   514                      gfx::Size(big_mode_.size().width(), kDualVirtualHeight), |  | 
|   515                      outputs_[0].get(), nullptr) |  | 
|   516                      .c_str(), |  | 
|   517           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   518           kUngrab, nullptr), |  | 
|   519       log_->GetActionsAndClear()); |  | 
|   520   EXPECT_EQ(2, observer_.num_changes()); |  | 
|   521   ASSERT_EQ(static_cast<size_t>(3u), cached.size()); |  | 
|   522   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   523   EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size()); |  | 
|   524   EXPECT_EQ(big_mode_.size(), cached[2]->current_mode()->size()); |  | 
|   525   EXPECT_EQ(virtual_display_id_1, cached[1]->display_id()); |  | 
|   526   EXPECT_EQ(virtual_display_id_2, cached[2]->display_id()); |  | 
|   527  |  | 
|   528   // Remove 1st virtual display. |  | 
|   529   observer_.Reset(); |  | 
|   530   EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id_1)); |  | 
|   531   EXPECT_EQ( |  | 
|   532       JoinActions( |  | 
|   533           kGrab, GetFramebufferAction( |  | 
|   534                      gfx::Size(big_mode_.size().width(), kSingleVirtualHeight), |  | 
|   535                      outputs_[0].get(), nullptr) |  | 
|   536                      .c_str(), |  | 
|   537           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   538           kUngrab, nullptr), |  | 
|   539       log_->GetActionsAndClear()); |  | 
|   540   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   541   ASSERT_EQ(static_cast<size_t>(2u), cached.size()); |  | 
|   542   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   543   EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size()); |  | 
|   544   EXPECT_EQ(virtual_display_id_2, cached[1]->display_id()); |  | 
|   545   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   546             configurator_.display_state()); |  | 
|   547  |  | 
|   548   // Remove 2nd virtual display. |  | 
|   549   observer_.Reset(); |  | 
|   550   EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id_2)); |  | 
|   551   EXPECT_EQ( |  | 
|   552       JoinActions( |  | 
|   553           kGrab, |  | 
|   554           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   555               .c_str(), |  | 
|   556           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   557           kUngrab, nullptr), |  | 
|   558       log_->GetActionsAndClear()); |  | 
|   559   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   560   ASSERT_EQ(static_cast<size_t>(1), cached.size()); |  | 
|   561   EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size()); |  | 
|   562   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |  | 
|   563 } |  | 
|   564  |  | 
|   565 TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) { |  | 
|   566   InitWithSingleOutput(); |  | 
|   567  |  | 
|   568   // Connect a second output and check that the configurator enters |  | 
|   569   // extended mode. |  | 
|   570   observer_.Reset(); |  | 
|   571   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|   572   UpdateOutputs(2, true); |  | 
|   573   const int kDualHeight = small_mode_.size().height() + |  | 
|   574                           DisplayConfigurator::kVerticalGap + |  | 
|   575                           big_mode_.size().height(); |  | 
|   576   EXPECT_EQ( |  | 
|   577       JoinActions( |  | 
|   578           kGrab, |  | 
|   579           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|   580                                outputs_[0].get(), outputs_[1].get()) |  | 
|   581               .c_str(), |  | 
|   582           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   583           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|   584                         gfx::Point(0, small_mode_.size().height() + |  | 
|   585                                           DisplayConfigurator::kVerticalGap)) |  | 
|   586               .c_str(), |  | 
|   587           kUngrab, nullptr), |  | 
|   588       log_->GetActionsAndClear()); |  | 
|   589   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   590   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   591  |  | 
|   592   observer_.Reset(); |  | 
|   593   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   594   EXPECT_EQ( |  | 
|   595       JoinActions( |  | 
|   596           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   597                                       outputs_[1].get()) |  | 
|   598                      .c_str(), |  | 
|   599           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   600           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   601           kUngrab, nullptr), |  | 
|   602       log_->GetActionsAndClear()); |  | 
|   603   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   604   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   605  |  | 
|   606   // Disconnect the second output. |  | 
|   607   observer_.Reset(); |  | 
|   608   UpdateOutputs(1, true); |  | 
|   609   EXPECT_EQ( |  | 
|   610       JoinActions( |  | 
|   611           kGrab, |  | 
|   612           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   613               .c_str(), |  | 
|   614           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   615           kUngrab, nullptr), |  | 
|   616       log_->GetActionsAndClear()); |  | 
|   617   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   618   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   619  |  | 
|   620   // Get rid of shared modes to force software mirroring. |  | 
|   621   outputs_[1] = display::FakeDisplaySnapshot::Builder() |  | 
|   622                     .SetId(kDisplayIds[1]) |  | 
|   623                     .SetNativeMode(big_mode_.Clone()) |  | 
|   624                     .SetCurrentMode(big_mode_.Clone()) |  | 
|   625                     .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|   626                     .SetIsAspectPerservingScaling(true) |  | 
|   627                     .Build(); |  | 
|   628  |  | 
|   629   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|   630   UpdateOutputs(2, true); |  | 
|   631   EXPECT_EQ( |  | 
|   632       JoinActions( |  | 
|   633           kGrab, |  | 
|   634           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|   635                                outputs_[0].get(), outputs_[1].get()) |  | 
|   636               .c_str(), |  | 
|   637           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   638           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|   639                         gfx::Point(0, small_mode_.size().height() + |  | 
|   640                                           DisplayConfigurator::kVerticalGap)) |  | 
|   641               .c_str(), |  | 
|   642           kUngrab, nullptr), |  | 
|   643       log_->GetActionsAndClear()); |  | 
|   644   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   645   const gfx::Size framebuffer_size = configurator_.framebuffer_size(); |  | 
|   646   DCHECK(!framebuffer_size.IsEmpty()); |  | 
|   647  |  | 
|   648   observer_.Reset(); |  | 
|   649   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   650   EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear()); |  | 
|   651   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   652             configurator_.display_state()); |  | 
|   653   EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   654   EXPECT_EQ(framebuffer_size.ToString(), |  | 
|   655             configurator_.framebuffer_size().ToString()); |  | 
|   656  |  | 
|   657   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   658  |  | 
|   659   // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure. |  | 
|   660   observer_.Reset(); |  | 
|   661   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|   662   EXPECT_EQ(JoinActions(nullptr), log_->GetActionsAndClear()); |  | 
|   663   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   664   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   665  |  | 
|   666   // Set back to software mirror mode. |  | 
|   667   observer_.Reset(); |  | 
|   668   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   669   EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear()); |  | 
|   670   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   671             configurator_.display_state()); |  | 
|   672   EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   673   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   674  |  | 
|   675   // Disconnect the second output. |  | 
|   676   observer_.Reset(); |  | 
|   677   UpdateOutputs(1, true); |  | 
|   678   EXPECT_EQ( |  | 
|   679       JoinActions( |  | 
|   680           kGrab, |  | 
|   681           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   682               .c_str(), |  | 
|   683           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   684           kUngrab, nullptr), |  | 
|   685       log_->GetActionsAndClear()); |  | 
|   686   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   687   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   688 } |  | 
|   689  |  | 
|   690 TEST_F(DisplayConfiguratorTest, SetDisplayPower) { |  | 
|   691   InitWithSingleOutput(); |  | 
|   692  |  | 
|   693   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   694   observer_.Reset(); |  | 
|   695   UpdateOutputs(2, true); |  | 
|   696   EXPECT_EQ( |  | 
|   697       JoinActions( |  | 
|   698           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   699                                       outputs_[1].get()) |  | 
|   700                      .c_str(), |  | 
|   701           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   702           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   703           kUngrab, nullptr), |  | 
|   704       log_->GetActionsAndClear()); |  | 
|   705   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   706   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   707  |  | 
|   708   // Turning off the internal display should switch the external display to |  | 
|   709   // its native mode. |  | 
|   710   observer_.Reset(); |  | 
|   711   config_waiter_.Reset(); |  | 
|   712   configurator_.SetDisplayPower( |  | 
|   713       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |  | 
|   714       DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   715       config_waiter_.on_configuration_callback()); |  | 
|   716   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   717   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   718   EXPECT_EQ( |  | 
|   719       JoinActions( |  | 
|   720           kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(), |  | 
|   721                                       outputs_[1].get()) |  | 
|   722                      .c_str(), |  | 
|   723           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   724           GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   725           kForceDPMS, kUngrab, nullptr), |  | 
|   726       log_->GetActionsAndClear()); |  | 
|   727   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |  | 
|   728   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   729  |  | 
|   730   // When all displays are turned off, the framebuffer should switch back |  | 
|   731   // to the mirrored size. |  | 
|   732   observer_.Reset(); |  | 
|   733   config_waiter_.Reset(); |  | 
|   734   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|   735                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   736                                 config_waiter_.on_configuration_callback()); |  | 
|   737   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   738   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   739   EXPECT_EQ( |  | 
|   740       JoinActions( |  | 
|   741           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   742                                       outputs_[1].get()) |  | 
|   743                      .c_str(), |  | 
|   744           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   745           GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   746           kUngrab, nullptr), |  | 
|   747       log_->GetActionsAndClear()); |  | 
|   748   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|   749   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   750   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   751  |  | 
|   752   // Turn all displays on and check that mirroring is still used. |  | 
|   753   observer_.Reset(); |  | 
|   754   config_waiter_.Reset(); |  | 
|   755   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|   756                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   757                                 config_waiter_.on_configuration_callback()); |  | 
|   758   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   759   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   760   EXPECT_EQ( |  | 
|   761       JoinActions( |  | 
|   762           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   763                                       outputs_[1].get()) |  | 
|   764                      .c_str(), |  | 
|   765           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   766           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   767           kForceDPMS, kUngrab, nullptr), |  | 
|   768       log_->GetActionsAndClear()); |  | 
|   769   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|   770   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   771   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   772  |  | 
|   773   // Get rid of shared modes to force software mirroring. |  | 
|   774   outputs_[1] = display::FakeDisplaySnapshot::Builder() |  | 
|   775                     .SetId(kDisplayIds[1]) |  | 
|   776                     .SetNativeMode(big_mode_.Clone()) |  | 
|   777                     .SetCurrentMode(big_mode_.Clone()) |  | 
|   778                     .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|   779                     .SetIsAspectPerservingScaling(true) |  | 
|   780                     .Build(); |  | 
|   781  |  | 
|   782   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   783   observer_.Reset(); |  | 
|   784   UpdateOutputs(2, true); |  | 
|   785   const int kDualHeight = small_mode_.size().height() + |  | 
|   786                           DisplayConfigurator::kVerticalGap + |  | 
|   787                           big_mode_.size().height(); |  | 
|   788   EXPECT_EQ( |  | 
|   789       JoinActions( |  | 
|   790           kGrab, |  | 
|   791           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|   792                                outputs_[0].get(), outputs_[1].get()) |  | 
|   793               .c_str(), |  | 
|   794           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   795           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|   796                         gfx::Point(0, small_mode_.size().height() + |  | 
|   797                                           DisplayConfigurator::kVerticalGap)) |  | 
|   798               .c_str(), |  | 
|   799           kUngrab, nullptr), |  | 
|   800       log_->GetActionsAndClear()); |  | 
|   801   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   802             configurator_.display_state()); |  | 
|   803   EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   804   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   805  |  | 
|   806   // Turning off the internal display should switch the external display to |  | 
|   807   // its native mode. |  | 
|   808   observer_.Reset(); |  | 
|   809   config_waiter_.Reset(); |  | 
|   810   configurator_.SetDisplayPower( |  | 
|   811       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |  | 
|   812       DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   813       config_waiter_.on_configuration_callback()); |  | 
|   814   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   815   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   816   EXPECT_EQ( |  | 
|   817       JoinActions( |  | 
|   818           kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(), |  | 
|   819                                       outputs_[1].get()) |  | 
|   820                      .c_str(), |  | 
|   821           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   822           GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   823           kForceDPMS, kUngrab, nullptr), |  | 
|   824       log_->GetActionsAndClear()); |  | 
|   825   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |  | 
|   826   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   827   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   828  |  | 
|   829   // When all displays are turned off, the framebuffer should switch back |  | 
|   830   // to the extended + software mirroring. |  | 
|   831   observer_.Reset(); |  | 
|   832   config_waiter_.Reset(); |  | 
|   833   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|   834                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   835                                 config_waiter_.on_configuration_callback()); |  | 
|   836   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   837   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   838   EXPECT_EQ( |  | 
|   839       JoinActions( |  | 
|   840           kGrab, |  | 
|   841           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|   842                                outputs_[0].get(), outputs_[1].get()) |  | 
|   843               .c_str(), |  | 
|   844           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   845           GetCrtcAction(*outputs_[1], nullptr, |  | 
|   846                         gfx::Point(0, small_mode_.size().height() + |  | 
|   847                                           DisplayConfigurator::kVerticalGap)) |  | 
|   848               .c_str(), |  | 
|   849           kUngrab, nullptr), |  | 
|   850       log_->GetActionsAndClear()); |  | 
|   851   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   852             configurator_.display_state()); |  | 
|   853   EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   854   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   855  |  | 
|   856   // Turn all displays on and check that mirroring is still used. |  | 
|   857   observer_.Reset(); |  | 
|   858   config_waiter_.Reset(); |  | 
|   859   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|   860                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   861                                 config_waiter_.on_configuration_callback()); |  | 
|   862   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   863   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   864   EXPECT_EQ( |  | 
|   865       JoinActions( |  | 
|   866           kGrab, |  | 
|   867           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|   868                                outputs_[0].get(), outputs_[1].get()) |  | 
|   869               .c_str(), |  | 
|   870           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   871           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|   872                         gfx::Point(0, small_mode_.size().height() + |  | 
|   873                                           DisplayConfigurator::kVerticalGap)) |  | 
|   874               .c_str(), |  | 
|   875           kForceDPMS, kUngrab, nullptr), |  | 
|   876       log_->GetActionsAndClear()); |  | 
|   877   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|   878             configurator_.display_state()); |  | 
|   879   EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|   880   EXPECT_EQ(1, observer_.num_changes()); |  | 
|   881 } |  | 
|   882  |  | 
|   883 TEST_F(DisplayConfiguratorTest, SuspendAndResume) { |  | 
|   884   InitWithSingleOutput(); |  | 
|   885  |  | 
|   886   // No preparation is needed before suspending when the display is already |  | 
|   887   // on.  The configurator should still reprobe on resume in case a display |  | 
|   888   // was connected while suspended. |  | 
|   889   const gfx::Size framebuffer_size = configurator_.framebuffer_size(); |  | 
|   890   DCHECK(!framebuffer_size.IsEmpty()); |  | 
|   891   config_waiter_.Reset(); |  | 
|   892   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|   893   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   894   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   895   EXPECT_EQ(framebuffer_size.ToString(), |  | 
|   896             configurator_.framebuffer_size().ToString()); |  | 
|   897   EXPECT_EQ(JoinActions( |  | 
|   898                 kGrab, GetFramebufferAction(small_mode_.size(), |  | 
|   899                                             outputs_[0].get(), nullptr) |  | 
|   900                            .c_str(), |  | 
|   901                 GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   902                 kUngrab, kSync, nullptr), |  | 
|   903             log_->GetActionsAndClear()); |  | 
|   904  |  | 
|   905   // No resume delay in single display mode. |  | 
|   906   config_waiter_.Reset(); |  | 
|   907   configurator_.ResumeDisplays(); |  | 
|   908   // The timer should not be running. |  | 
|   909   EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait()); |  | 
|   910   EXPECT_EQ( |  | 
|   911       JoinActions( |  | 
|   912           kGrab, |  | 
|   913           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   914               .c_str(), |  | 
|   915           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   916           kForceDPMS, kUngrab, nullptr), |  | 
|   917       log_->GetActionsAndClear()); |  | 
|   918  |  | 
|   919   // Now turn the display off before suspending and check that the |  | 
|   920   // configurator turns it back on and syncs with the server. |  | 
|   921   config_waiter_.Reset(); |  | 
|   922   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|   923                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   924                                 config_waiter_.on_configuration_callback()); |  | 
|   925   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   926   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   927   EXPECT_EQ(JoinActions( |  | 
|   928                 kGrab, GetFramebufferAction(small_mode_.size(), |  | 
|   929                                             outputs_[0].get(), nullptr) |  | 
|   930                            .c_str(), |  | 
|   931                 GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   932                 kUngrab, nullptr), |  | 
|   933             log_->GetActionsAndClear()); |  | 
|   934  |  | 
|   935   config_waiter_.Reset(); |  | 
|   936   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|   937   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   938   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   939   EXPECT_EQ(kSync, log_->GetActionsAndClear()); |  | 
|   940  |  | 
|   941   config_waiter_.Reset(); |  | 
|   942   configurator_.ResumeDisplays(); |  | 
|   943   // The timer should not be running. |  | 
|   944   EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait()); |  | 
|   945   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|   946  |  | 
|   947   config_waiter_.Reset(); |  | 
|   948   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|   949                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   950                                 config_waiter_.on_configuration_callback()); |  | 
|   951   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   952   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   953   EXPECT_EQ( |  | 
|   954       JoinActions( |  | 
|   955           kGrab, |  | 
|   956           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|   957               .c_str(), |  | 
|   958           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   959           kForceDPMS, kUngrab, nullptr), |  | 
|   960       log_->GetActionsAndClear()); |  | 
|   961  |  | 
|   962   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|   963   UpdateOutputs(2, true); |  | 
|   964   EXPECT_EQ( |  | 
|   965       JoinActions( |  | 
|   966           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   967                                       outputs_[1].get()) |  | 
|   968                      .c_str(), |  | 
|   969           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   970           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|   971           kUngrab, nullptr), |  | 
|   972       log_->GetActionsAndClear()); |  | 
|   973  |  | 
|   974   config_waiter_.Reset(); |  | 
|   975   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|   976                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|   977                                 config_waiter_.on_configuration_callback()); |  | 
|   978   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   979   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   980   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|   981   EXPECT_EQ( |  | 
|   982       JoinActions( |  | 
|   983           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|   984                                       outputs_[1].get()) |  | 
|   985                      .c_str(), |  | 
|   986           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   987           GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|   988           kUngrab, nullptr), |  | 
|   989       log_->GetActionsAndClear()); |  | 
|   990  |  | 
|   991   // No delay in suspend. |  | 
|   992   config_waiter_.Reset(); |  | 
|   993   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|   994   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|   995   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|   996   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|   997             configurator_.current_power_state()); |  | 
|   998   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|   999   EXPECT_EQ(kSync, log_->GetActionsAndClear()); |  | 
|  1000  |  | 
|  1001   // If a display is disconnected while suspended, the configurator should |  | 
|  1002   // pick up the change and only turn on the internal display. The should be |  | 
|  1003   // a longer configuration delay when we set the displays back to on. |  | 
|  1004   UpdateOutputs(1, false); |  | 
|  1005   config_waiter_.Reset(); |  | 
|  1006   configurator_.ResumeDisplays(); |  | 
|  1007   // Since we were in dual display mirror mode before suspend, the timer should |  | 
|  1008   // be running with kMinLongDelayMs. |  | 
|  1009   EXPECT_EQ(kLongDelay, test_api_.GetConfigureDelay()); |  | 
|  1010   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1011  |  | 
|  1012   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1013                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1014                                 config_waiter_.on_configuration_callback()); |  | 
|  1015   EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result()); |  | 
|  1016   EXPECT_EQ(kLongDelay, config_waiter_.Wait()); |  | 
|  1017   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1018   EXPECT_EQ( |  | 
|  1019       JoinActions( |  | 
|  1020           kGrab, |  | 
|  1021           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1022               .c_str(), |  | 
|  1023           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1024           kForceDPMS, kUngrab, nullptr), |  | 
|  1025       log_->GetActionsAndClear()); |  | 
|  1026 } |  | 
|  1027  |  | 
|  1028 TEST_F(DisplayConfiguratorTest, Headless) { |  | 
|  1029   UpdateOutputs(0, false); |  | 
|  1030   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1031   Init(false); |  | 
|  1032   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1033   configurator_.ForceInitialConfigure(0); |  | 
|  1034   EXPECT_EQ(JoinActions(kInitXRandR, kGrab, kForceDPMS, kUngrab, nullptr), |  | 
|  1035             log_->GetActionsAndClear()); |  | 
|  1036  |  | 
|  1037   // Not much should happen when the display power state is changed while |  | 
|  1038   // no displays are connected. |  | 
|  1039   config_waiter_.Reset(); |  | 
|  1040   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  1041                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1042                                 config_waiter_.on_configuration_callback()); |  | 
|  1043   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1044   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1045   EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear()); |  | 
|  1046   config_waiter_.Reset(); |  | 
|  1047   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1048                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1049                                 config_waiter_.on_configuration_callback()); |  | 
|  1050   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1051   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1052   EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, nullptr), |  | 
|  1053             log_->GetActionsAndClear()); |  | 
|  1054  |  | 
|  1055   // Connect an external display and check that it's configured correctly. |  | 
|  1056   outputs_[0] = display::FakeDisplaySnapshot::Builder() |  | 
|  1057                     .SetId(kDisplayIds[0]) |  | 
|  1058                     .SetNativeMode(big_mode_.Clone()) |  | 
|  1059                     .SetCurrentMode(big_mode_.Clone()) |  | 
|  1060                     .AddMode(small_mode_.Clone()) |  | 
|  1061                     .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL) |  | 
|  1062                     .SetIsAspectPerservingScaling(true) |  | 
|  1063                     .Build(); |  | 
|  1064  |  | 
|  1065   UpdateOutputs(1, true); |  | 
|  1066   EXPECT_EQ( |  | 
|  1067       JoinActions( |  | 
|  1068           kGrab, |  | 
|  1069           GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1070               .c_str(), |  | 
|  1071           GetCrtcAction(*outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1072           kUngrab, nullptr), |  | 
|  1073       log_->GetActionsAndClear()); |  | 
|  1074   const gfx::Size framebuffer_size = configurator_.framebuffer_size(); |  | 
|  1075   DCHECK(!framebuffer_size.IsEmpty()); |  | 
|  1076  |  | 
|  1077   UpdateOutputs(0, true); |  | 
|  1078   EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear()); |  | 
|  1079   EXPECT_EQ(framebuffer_size.ToString(), |  | 
|  1080             configurator_.framebuffer_size().ToString()); |  | 
|  1081 } |  | 
|  1082  |  | 
|  1083 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) { |  | 
|  1084   UpdateOutputs(2, false); |  | 
|  1085   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1086   Init(false); |  | 
|  1087   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1088  |  | 
|  1089   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1090   configurator_.ForceInitialConfigure(0); |  | 
|  1091   EXPECT_EQ( |  | 
|  1092       JoinActions( |  | 
|  1093           kInitXRandR, kGrab, |  | 
|  1094           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1095                                outputs_[1].get()) |  | 
|  1096               .c_str(), |  | 
|  1097           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1098           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1099           kForceDPMS, kUngrab, nullptr), |  | 
|  1100       log_->GetActionsAndClear()); |  | 
|  1101 } |  | 
|  1102  |  | 
|  1103 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) { |  | 
|  1104   UpdateOutputs(0, false); |  | 
|  1105   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1106   Init(false); |  | 
|  1107   configurator_.ForceInitialConfigure(0); |  | 
|  1108   observer_.Reset(); |  | 
|  1109   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS); |  | 
|  1110   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1111   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1112   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1113   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1114   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1115   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1116   EXPECT_EQ(3, observer_.num_failures()); |  | 
|  1117  |  | 
|  1118   UpdateOutputs(1, true); |  | 
|  1119   observer_.Reset(); |  | 
|  1120   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS); |  | 
|  1121   EXPECT_EQ(0, observer_.num_changes()); |  | 
|  1122   EXPECT_EQ(1, observer_.num_failures()); |  | 
|  1123   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1124   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1125   EXPECT_EQ(1, observer_.num_failures()); |  | 
|  1126   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1127   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1128   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1129   EXPECT_EQ(3, observer_.num_failures()); |  | 
|  1130  |  | 
|  1131   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1132   UpdateOutputs(2, true); |  | 
|  1133   observer_.Reset(); |  | 
|  1134   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS); |  | 
|  1135   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1136   EXPECT_EQ(0, observer_.num_changes()); |  | 
|  1137   EXPECT_EQ(2, observer_.num_failures()); |  | 
|  1138   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1139   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1140   EXPECT_EQ(2, observer_.num_changes()); |  | 
|  1141   EXPECT_EQ(2, observer_.num_failures()); |  | 
|  1142 } |  | 
|  1143  |  | 
|  1144 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForMirroredDisplays) { |  | 
|  1145   UpdateOutputs(2, false); |  | 
|  1146   Init(false); |  | 
|  1147   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1148   configurator_.ForceInitialConfigure(0); |  | 
|  1149   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|  1150 } |  | 
|  1151  |  | 
|  1152 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) { |  | 
|  1153   InitWithSingleOutput(); |  | 
|  1154   const DisplayConfigurator::DisplayStateList& cached = |  | 
|  1155       configurator_.cached_displays(); |  | 
|  1156   ASSERT_EQ(static_cast<size_t>(1), cached.size()); |  | 
|  1157   EXPECT_EQ(outputs_[0]->current_mode(), cached[0]->current_mode()); |  | 
|  1158  |  | 
|  1159   // After connecting a second output, check that it shows up in |  | 
|  1160   // |cached_displays_| even if an invalid state is requested. |  | 
|  1161   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1162   UpdateOutputs(2, true); |  | 
|  1163   ASSERT_EQ(static_cast<size_t>(2), cached.size()); |  | 
|  1164   EXPECT_EQ(outputs_[0]->current_mode(), cached[0]->current_mode()); |  | 
|  1165   EXPECT_EQ(outputs_[1]->current_mode(), cached[1]->current_mode()); |  | 
|  1166 } |  | 
|  1167  |  | 
|  1168 TEST_F(DisplayConfiguratorTest, PanelFitting) { |  | 
|  1169   // Configure the internal display to support only the big mode and the |  | 
|  1170   // external display to support only the small mode. |  | 
|  1171   outputs_[0] = display::FakeDisplaySnapshot::Builder() |  | 
|  1172                     .SetId(kDisplayIds[0]) |  | 
|  1173                     .SetNativeMode(big_mode_.Clone()) |  | 
|  1174                     .SetCurrentMode(big_mode_.Clone()) |  | 
|  1175                     .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL) |  | 
|  1176                     .SetIsAspectPerservingScaling(true) |  | 
|  1177                     .Build(); |  | 
|  1178  |  | 
|  1179   outputs_[1] = display::FakeDisplaySnapshot::Builder() |  | 
|  1180                     .SetId(kDisplayIds[1]) |  | 
|  1181                     .SetNativeMode(small_mode_.Clone()) |  | 
|  1182                     .SetCurrentMode(small_mode_.Clone()) |  | 
|  1183                     .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|  1184                     .SetIsAspectPerservingScaling(true) |  | 
|  1185                     .Build(); |  | 
|  1186  |  | 
|  1187   // The small mode should be added to the internal output when requesting |  | 
|  1188   // mirrored mode. |  | 
|  1189   UpdateOutputs(2, false); |  | 
|  1190   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1191   Init(true /* is_panel_fitting_enabled */); |  | 
|  1192   configurator_.ForceInitialConfigure(0); |  | 
|  1193   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); |  | 
|  1194   EXPECT_EQ( |  | 
|  1195       JoinActions( |  | 
|  1196           kInitXRandR, kGrab, |  | 
|  1197           GetAddOutputModeAction(*outputs_[0], &small_mode_).c_str(), |  | 
|  1198           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1199                                outputs_[1].get()) |  | 
|  1200               .c_str(), |  | 
|  1201           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1202           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1203           kForceDPMS, kUngrab, nullptr), |  | 
|  1204       log_->GetActionsAndClear()); |  | 
|  1205  |  | 
|  1206   // Both outputs should be using the small mode. |  | 
|  1207   ASSERT_EQ(1, observer_.num_changes()); |  | 
|  1208   ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size()); |  | 
|  1209   EXPECT_EQ(small_mode_.size(), |  | 
|  1210             observer_.latest_outputs()[0]->current_mode()->size()); |  | 
|  1211   EXPECT_EQ(small_mode_.size(), |  | 
|  1212             observer_.latest_outputs()[1]->current_mode()->size()); |  | 
|  1213  |  | 
|  1214   // Also test that there are 2 modes (instead of the initial one) in the |  | 
|  1215   // snapshot that was passed to the observer (http://crbug.com/289159). |  | 
|  1216   DisplaySnapshot* state = observer_.latest_outputs()[0]; |  | 
|  1217   ASSERT_EQ(2UL, state->modes().size()); |  | 
|  1218 } |  | 
|  1219  |  | 
|  1220 TEST_F(DisplayConfiguratorTest, ContentProtection) { |  | 
|  1221   Init(false); |  | 
|  1222   configurator_.ForceInitialConfigure(0); |  | 
|  1223   EXPECT_NE(kNoActions, log_->GetActionsAndClear()); |  | 
|  1224  |  | 
|  1225   DisplayConfigurator::ContentProtectionClientId id = |  | 
|  1226       configurator_.RegisterContentProtectionClient(); |  | 
|  1227   EXPECT_NE(0u, id); |  | 
|  1228  |  | 
|  1229   // One output. |  | 
|  1230   UpdateOutputs(1, true); |  | 
|  1231   EXPECT_NE(kNoActions, log_->GetActionsAndClear()); |  | 
|  1232   configurator_.QueryContentProtectionStatus( |  | 
|  1233       id, outputs_[0]->display_id(), |  | 
|  1234       base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, |  | 
|  1235                  base::Unretained(this))); |  | 
|  1236   EXPECT_EQ(1, query_content_protection_call_count_); |  | 
|  1237   EXPECT_TRUE(query_content_protection_response_.success); |  | 
|  1238   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), |  | 
|  1239             query_content_protection_response_.link_mask); |  | 
|  1240   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), |  | 
|  1241             query_content_protection_response_.protection_mask); |  | 
|  1242   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1243  |  | 
|  1244   // Two outputs. |  | 
|  1245   UpdateOutputs(2, true); |  | 
|  1246   EXPECT_NE(kNoActions, log_->GetActionsAndClear()); |  | 
|  1247   configurator_.QueryContentProtectionStatus( |  | 
|  1248       id, outputs_[1]->display_id(), |  | 
|  1249       base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, |  | 
|  1250                  base::Unretained(this))); |  | 
|  1251   EXPECT_EQ(2, query_content_protection_call_count_); |  | 
|  1252   EXPECT_TRUE(query_content_protection_response_.success); |  | 
|  1253   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), |  | 
|  1254             query_content_protection_response_.link_mask); |  | 
|  1255   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), |  | 
|  1256             query_content_protection_response_.protection_mask); |  | 
|  1257   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1258  |  | 
|  1259   configurator_.EnableContentProtection( |  | 
|  1260       id, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1261       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1262                  base::Unretained(this))); |  | 
|  1263   EXPECT_EQ(1, enable_content_protection_call_count_); |  | 
|  1264   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1265   EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED), |  | 
|  1266             log_->GetActionsAndClear()); |  | 
|  1267  |  | 
|  1268   // Enable protection. |  | 
|  1269   native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); |  | 
|  1270   configurator_.QueryContentProtectionStatus( |  | 
|  1271       id, outputs_[1]->display_id(), |  | 
|  1272       base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, |  | 
|  1273                  base::Unretained(this))); |  | 
|  1274   EXPECT_EQ(3, query_content_protection_call_count_); |  | 
|  1275   EXPECT_TRUE(query_content_protection_response_.success); |  | 
|  1276   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), |  | 
|  1277             query_content_protection_response_.link_mask); |  | 
|  1278   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP), |  | 
|  1279             query_content_protection_response_.protection_mask); |  | 
|  1280   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1281  |  | 
|  1282   // Protections should be disabled after unregister. |  | 
|  1283   configurator_.UnregisterContentProtectionClient(id); |  | 
|  1284   EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_UNDESIRED), |  | 
|  1285             log_->GetActionsAndClear()); |  | 
|  1286 } |  | 
|  1287  |  | 
|  1288 TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) { |  | 
|  1289   InitWithSingleOutput(); |  | 
|  1290  |  | 
|  1291   // The DisplayConfigurator may occasionally receive OnConfigurationChanged() |  | 
|  1292   // after the displays have been suspended.  This event should be ignored since |  | 
|  1293   // the DisplayConfigurator will force a probe and reconfiguration of displays |  | 
|  1294   // at resume time. |  | 
|  1295   config_waiter_.Reset(); |  | 
|  1296   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  1297   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1298   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1299   EXPECT_EQ(JoinActions( |  | 
|  1300                 kGrab, GetFramebufferAction(small_mode_.size(), |  | 
|  1301                                             outputs_[0].get(), nullptr) |  | 
|  1302                            .c_str(), |  | 
|  1303                 GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1304                 kUngrab, kSync, nullptr), |  | 
|  1305             log_->GetActionsAndClear()); |  | 
|  1306  |  | 
|  1307   // The configuration timer should not be started when the displays |  | 
|  1308   // are suspended. |  | 
|  1309   configurator_.OnConfigurationChanged(); |  | 
|  1310   EXPECT_FALSE(test_api_.TriggerConfigureTimeout()); |  | 
|  1311   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1312  |  | 
|  1313   // Calls to SetDisplayPower should do nothing if the power state doesn't |  | 
|  1314   // change. |  | 
|  1315   config_waiter_.Reset(); |  | 
|  1316   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  1317                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1318                                 config_waiter_.on_configuration_callback()); |  | 
|  1319   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1320   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1321   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1322   config_waiter_.Reset(); |  | 
|  1323   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1324                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1325                                 config_waiter_.on_configuration_callback()); |  | 
|  1326   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1327   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1328   EXPECT_EQ( |  | 
|  1329       JoinActions( |  | 
|  1330           kGrab, |  | 
|  1331           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1332               .c_str(), |  | 
|  1333           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1334           kForceDPMS, kUngrab, nullptr), |  | 
|  1335       log_->GetActionsAndClear()); |  | 
|  1336  |  | 
|  1337   UpdateOutputs(2, false); |  | 
|  1338   configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1339   EXPECT_EQ( |  | 
|  1340       JoinActions( |  | 
|  1341           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1342                                       outputs_[1].get()) |  | 
|  1343                      .c_str(), |  | 
|  1344           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1345           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1346           kUngrab, nullptr), |  | 
|  1347       log_->GetActionsAndClear()); |  | 
|  1348  |  | 
|  1349   // The DisplayConfigurator should do nothing at resume time if there is no |  | 
|  1350   // state change. |  | 
|  1351   config_waiter_.Reset(); |  | 
|  1352   UpdateOutputs(1, false); |  | 
|  1353   configurator_.ResumeDisplays(); |  | 
|  1354   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1355  |  | 
|  1356   // If a configuration task is pending when the displays are suspended, that |  | 
|  1357   // task should not run either and the timer should be stopped. The displays |  | 
|  1358   // should be turned off by suspend. |  | 
|  1359   configurator_.OnConfigurationChanged(); |  | 
|  1360   config_waiter_.Reset(); |  | 
|  1361   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  1362   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1363   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1364   EXPECT_EQ(JoinActions( |  | 
|  1365                 kGrab, GetFramebufferAction(small_mode_.size(), |  | 
|  1366                                             outputs_[0].get(), nullptr) |  | 
|  1367                            .c_str(), |  | 
|  1368                 GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1369                 kUngrab, kSync, nullptr), |  | 
|  1370             log_->GetActionsAndClear()); |  | 
|  1371   EXPECT_FALSE(test_api_.TriggerConfigureTimeout()); |  | 
|  1372   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1373  |  | 
|  1374   config_waiter_.Reset(); |  | 
|  1375   configurator_.ResumeDisplays(); |  | 
|  1376   // The timer should not be running. |  | 
|  1377   EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait()); |  | 
|  1378   EXPECT_EQ( |  | 
|  1379       JoinActions( |  | 
|  1380           kGrab, |  | 
|  1381           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1382               .c_str(), |  | 
|  1383           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1384           kForceDPMS, kUngrab, nullptr), |  | 
|  1385       log_->GetActionsAndClear()); |  | 
|  1386 } |  | 
|  1387  |  | 
|  1388 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) { |  | 
|  1389   DisplayConfigurator::ContentProtectionClientId client1 = |  | 
|  1390       configurator_.RegisterContentProtectionClient(); |  | 
|  1391   DisplayConfigurator::ContentProtectionClientId client2 = |  | 
|  1392       configurator_.RegisterContentProtectionClient(); |  | 
|  1393   EXPECT_NE(client1, client2); |  | 
|  1394  |  | 
|  1395   Init(false); |  | 
|  1396   configurator_.ForceInitialConfigure(0); |  | 
|  1397   UpdateOutputs(2, true); |  | 
|  1398   EXPECT_NE(kNoActions, log_->GetActionsAndClear()); |  | 
|  1399  |  | 
|  1400   // Clients never know state enableness for methods that they didn't request. |  | 
|  1401   configurator_.EnableContentProtection( |  | 
|  1402       client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1403       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1404                  base::Unretained(this))); |  | 
|  1405   EXPECT_EQ(1, enable_content_protection_call_count_); |  | 
|  1406   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1407   EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(), |  | 
|  1408             log_->GetActionsAndClear()); |  | 
|  1409   native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); |  | 
|  1410  |  | 
|  1411   configurator_.QueryContentProtectionStatus( |  | 
|  1412       client1, outputs_[1]->display_id(), |  | 
|  1413       base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, |  | 
|  1414                  base::Unretained(this))); |  | 
|  1415   EXPECT_EQ(1, query_content_protection_call_count_); |  | 
|  1416   EXPECT_TRUE(query_content_protection_response_.success); |  | 
|  1417   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), |  | 
|  1418             query_content_protection_response_.link_mask); |  | 
|  1419   EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1420             query_content_protection_response_.protection_mask); |  | 
|  1421  |  | 
|  1422   configurator_.QueryContentProtectionStatus( |  | 
|  1423       client2, outputs_[1]->display_id(), |  | 
|  1424       base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, |  | 
|  1425                  base::Unretained(this))); |  | 
|  1426   EXPECT_EQ(2, query_content_protection_call_count_); |  | 
|  1427   EXPECT_TRUE(query_content_protection_response_.success); |  | 
|  1428   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), |  | 
|  1429             query_content_protection_response_.link_mask); |  | 
|  1430   EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, |  | 
|  1431             query_content_protection_response_.protection_mask); |  | 
|  1432  |  | 
|  1433   // Protections will be disabled only if no more clients request them. |  | 
|  1434   configurator_.EnableContentProtection( |  | 
|  1435       client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE, |  | 
|  1436       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1437                  base::Unretained(this))); |  | 
|  1438   EXPECT_EQ(2, enable_content_protection_call_count_); |  | 
|  1439   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1440   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1441  |  | 
|  1442   configurator_.EnableContentProtection( |  | 
|  1443       client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE, |  | 
|  1444       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1445                  base::Unretained(this))); |  | 
|  1446   EXPECT_EQ(3, enable_content_protection_call_count_); |  | 
|  1447   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1448   EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_UNDESIRED).c_str(), |  | 
|  1449             log_->GetActionsAndClear()); |  | 
|  1450 } |  | 
|  1451  |  | 
|  1452 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClientsEnable) { |  | 
|  1453   DisplayConfigurator::ContentProtectionClientId client1 = |  | 
|  1454       configurator_.RegisterContentProtectionClient(); |  | 
|  1455   DisplayConfigurator::ContentProtectionClientId client2 = |  | 
|  1456       configurator_.RegisterContentProtectionClient(); |  | 
|  1457   EXPECT_NE(client1, client2); |  | 
|  1458  |  | 
|  1459   Init(false); |  | 
|  1460   configurator_.ForceInitialConfigure(0); |  | 
|  1461   UpdateOutputs(2, true); |  | 
|  1462   log_->GetActionsAndClear(); |  | 
|  1463  |  | 
|  1464   // Only enable once if HDCP is enabling. |  | 
|  1465   configurator_.EnableContentProtection( |  | 
|  1466       client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1467       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1468                  base::Unretained(this))); |  | 
|  1469   EXPECT_EQ(1, enable_content_protection_call_count_); |  | 
|  1470   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1471   native_display_delegate_->set_hdcp_state(HDCP_STATE_DESIRED); |  | 
|  1472   configurator_.EnableContentProtection( |  | 
|  1473       client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1474       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1475                  base::Unretained(this))); |  | 
|  1476   EXPECT_EQ(2, enable_content_protection_call_count_); |  | 
|  1477   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1478   EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(), |  | 
|  1479             log_->GetActionsAndClear()); |  | 
|  1480   native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); |  | 
|  1481  |  | 
|  1482   // Don't enable again if HDCP is already active. |  | 
|  1483   configurator_.EnableContentProtection( |  | 
|  1484       client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1485       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1486                  base::Unretained(this))); |  | 
|  1487   EXPECT_EQ(3, enable_content_protection_call_count_); |  | 
|  1488   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1489   configurator_.EnableContentProtection( |  | 
|  1490       client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, |  | 
|  1491       base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback, |  | 
|  1492                  base::Unretained(this))); |  | 
|  1493   EXPECT_EQ(4, enable_content_protection_call_count_); |  | 
|  1494   EXPECT_TRUE(enable_content_protection_status_); |  | 
|  1495   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1496 } |  | 
|  1497  |  | 
|  1498 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) { |  | 
|  1499   InitWithSingleOutput(); |  | 
|  1500  |  | 
|  1501   std::vector<std::unique_ptr<const DisplayMode>> modes; |  | 
|  1502   // The first mode is the mode we are requesting DisplayConfigurator to choose. |  | 
|  1503   // The test will be setup so that this mode will fail and it will have to |  | 
|  1504   // choose the next best option. |  | 
|  1505   modes.push_back(MakeDisplayMode(2560, 1600, false, 60.0)); |  | 
|  1506   modes.push_back(MakeDisplayMode(1024, 768, false, 60.0)); |  | 
|  1507   modes.push_back(MakeDisplayMode(1280, 720, false, 60.0)); |  | 
|  1508   modes.push_back(MakeDisplayMode(1920, 1080, false, 60.0)); |  | 
|  1509   modes.push_back(MakeDisplayMode(1920, 1080, false, 40.0)); |  | 
|  1510  |  | 
|  1511   outputs_[0] = display::FakeDisplaySnapshot::Builder() |  | 
|  1512                     .SetId(kDisplayIds[0]) |  | 
|  1513                     .SetNativeMode(modes[0]->Clone()) |  | 
|  1514                     .SetCurrentMode(modes[0]->Clone()) |  | 
|  1515                     .AddMode(modes[1]->Clone()) |  | 
|  1516                     .AddMode(modes[2]->Clone()) |  | 
|  1517                     .AddMode(modes[3]->Clone()) |  | 
|  1518                     .AddMode(modes[4]->Clone()) |  | 
|  1519                     .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL) |  | 
|  1520                     .SetIsAspectPerservingScaling(true) |  | 
|  1521                     .Build(); |  | 
|  1522  |  | 
|  1523   // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is |  | 
|  1524   // probably unrealistic but we want to make sure any assumptions don't creep |  | 
|  1525   // in. |  | 
|  1526   native_display_delegate_->set_max_configurable_pixels( |  | 
|  1527       modes[2]->size().GetArea()); |  | 
|  1528   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1529   UpdateOutputs(1, true); |  | 
|  1530  |  | 
|  1531   EXPECT_EQ( |  | 
|  1532       JoinActions( |  | 
|  1533           kGrab, |  | 
|  1534           GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1535               .c_str(), |  | 
|  1536           GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1537           GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1538           GetCrtcAction(*outputs_[0], modes[2].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1539           kUngrab, nullptr), |  | 
|  1540       log_->GetActionsAndClear()); |  | 
|  1541  |  | 
|  1542   outputs_[1] = display::FakeDisplaySnapshot::Builder() |  | 
|  1543                     .SetId(kDisplayIds[1]) |  | 
|  1544                     .SetNativeMode(modes[0]->Clone()) |  | 
|  1545                     .SetCurrentMode(modes[0]->Clone()) |  | 
|  1546                     .AddMode(modes[1]->Clone()) |  | 
|  1547                     .AddMode(modes[2]->Clone()) |  | 
|  1548                     .AddMode(modes[3]->Clone()) |  | 
|  1549                     .AddMode(modes[4]->Clone()) |  | 
|  1550                     .SetType(DISPLAY_CONNECTION_TYPE_HDMI) |  | 
|  1551                     .SetIsAspectPerservingScaling(true) |  | 
|  1552                     .Build(); |  | 
|  1553  |  | 
|  1554   // This test should attempt to configure a mirror mode that will not succeed |  | 
|  1555   // and should end up in extended mode. |  | 
|  1556   native_display_delegate_->set_max_configurable_pixels( |  | 
|  1557       modes[3]->size().GetArea()); |  | 
|  1558   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1559   UpdateOutputs(2, true); |  | 
|  1560  |  | 
|  1561   EXPECT_EQ( |  | 
|  1562       JoinActions( |  | 
|  1563           kGrab, GetFramebufferAction(modes[0]->size(), outputs_[0].get(), |  | 
|  1564                                       outputs_[1].get()) |  | 
|  1565                      .c_str(), |  | 
|  1566           GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1567           // Then attempt to configure crtc1 with the first mode. |  | 
|  1568           GetCrtcAction(*outputs_[1], modes[0].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1569           // First mode tried is expected to fail and it will |  | 
|  1570           // retry wil the 4th mode in the list. |  | 
|  1571           GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1572           GetCrtcAction(*outputs_[1], modes[3].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1573           // Since it was requested to go into mirror mode |  | 
|  1574           // and the configured modes were different, it |  | 
|  1575           // should now try and setup a valid configurable |  | 
|  1576           // extended mode. |  | 
|  1577           GetFramebufferAction( |  | 
|  1578               gfx::Size(modes[0]->size().width(), |  | 
|  1579                         modes[0]->size().height() + modes[0]->size().height() + |  | 
|  1580                             DisplayConfigurator::kVerticalGap), |  | 
|  1581               outputs_[0].get(), outputs_[1].get()) |  | 
|  1582               .c_str(), |  | 
|  1583           GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1584           GetCrtcAction(*outputs_[1], modes[0].get(), |  | 
|  1585                         gfx::Point(0, modes[0]->size().height() + |  | 
|  1586                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1587               .c_str(), |  | 
|  1588           GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(), |  | 
|  1589           GetCrtcAction(*outputs_[1], modes[3].get(), |  | 
|  1590                         gfx::Point(0, modes[0]->size().height() + |  | 
|  1591                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1592               .c_str(), |  | 
|  1593           kUngrab, nullptr), |  | 
|  1594       log_->GetActionsAndClear()); |  | 
|  1595 } |  | 
|  1596  |  | 
|  1597 // Tests that power state requests are saved after failed configuration attempts |  | 
|  1598 // so they can be reused later: http://crosbug.com/p/31571 |  | 
|  1599 TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) { |  | 
|  1600   // Start out with two displays in extended mode. |  | 
|  1601   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1602   Init(false); |  | 
|  1603   configurator_.ForceInitialConfigure(0); |  | 
|  1604   log_->GetActionsAndClear(); |  | 
|  1605   observer_.Reset(); |  | 
|  1606  |  | 
|  1607   // Turn off the internal display, simulating docked mode. |  | 
|  1608   config_waiter_.Reset(); |  | 
|  1609   configurator_.SetDisplayPower( |  | 
|  1610       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |  | 
|  1611       DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1612       config_waiter_.on_configuration_callback()); |  | 
|  1613   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1614   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1615   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1616   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1617   log_->GetActionsAndClear(); |  | 
|  1618  |  | 
|  1619   // Make all subsequent configuration requests fail and try to turn the |  | 
|  1620   // internal display back on. |  | 
|  1621   config_waiter_.Reset(); |  | 
|  1622   native_display_delegate_->set_max_configurable_pixels(1); |  | 
|  1623   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1624                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1625                                 config_waiter_.on_configuration_callback()); |  | 
|  1626   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1627   EXPECT_EQ(CALLBACK_FAILURE, config_waiter_.callback_result()); |  | 
|  1628   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1629   EXPECT_EQ(1, observer_.num_failures()); |  | 
|  1630   log_->GetActionsAndClear(); |  | 
|  1631  |  | 
|  1632   // Simulate the external display getting disconnected and check that the |  | 
|  1633   // internal display is turned on (i.e. DISPLAY_POWER_ALL_ON is used) rather |  | 
|  1634   // than the earlier DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON state. |  | 
|  1635   native_display_delegate_->set_max_configurable_pixels(0); |  | 
|  1636   UpdateOutputs(1, true); |  | 
|  1637   EXPECT_EQ( |  | 
|  1638       JoinActions( |  | 
|  1639           kGrab, |  | 
|  1640           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1641               .c_str(), |  | 
|  1642           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1643           kForceDPMS, kUngrab, nullptr), |  | 
|  1644       log_->GetActionsAndClear()); |  | 
|  1645 } |  | 
|  1646  |  | 
|  1647 // Tests that the SetDisplayPowerState() task posted by HandleResume() doesn't |  | 
|  1648 // use a stale state if a new state is requested before it runs: |  | 
|  1649 // http://crosbug.com/p/32393 |  | 
|  1650 TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) { |  | 
|  1651   // Start out with two displays in mirrored mode. |  | 
|  1652   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); |  | 
|  1653   Init(false); |  | 
|  1654   configurator_.ForceInitialConfigure(0); |  | 
|  1655   log_->GetActionsAndClear(); |  | 
|  1656   observer_.Reset(); |  | 
|  1657  |  | 
|  1658   // Turn off the internal display, simulating docked mode. |  | 
|  1659   configurator_.SetDisplayPower( |  | 
|  1660       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |  | 
|  1661       DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1662       config_waiter_.on_configuration_callback()); |  | 
|  1663   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1664   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1665   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1666   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1667   EXPECT_EQ( |  | 
|  1668       JoinActions( |  | 
|  1669           kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(), |  | 
|  1670                                       outputs_[1].get()) |  | 
|  1671                      .c_str(), |  | 
|  1672           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1673           GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1674           kForceDPMS, kUngrab, nullptr), |  | 
|  1675       log_->GetActionsAndClear()); |  | 
|  1676  |  | 
|  1677   // Suspend and resume the system. Resuming should restore the previous power |  | 
|  1678   // state and force a probe. Suspend should turn off the displays since an |  | 
|  1679   // external monitor is connected. |  | 
|  1680   config_waiter_.Reset(); |  | 
|  1681   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  1682   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1683   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1684   EXPECT_EQ(2, observer_.num_changes()); |  | 
|  1685   EXPECT_EQ( |  | 
|  1686       JoinActions( |  | 
|  1687           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1688                                       outputs_[1].get()) |  | 
|  1689                      .c_str(), |  | 
|  1690           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1691           GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1692           kUngrab, kSync, nullptr), |  | 
|  1693       log_->GetActionsAndClear()); |  | 
|  1694  |  | 
|  1695   // Before the task runs, exit docked mode. |  | 
|  1696   config_waiter_.Reset(); |  | 
|  1697   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1698                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1699                                 config_waiter_.on_configuration_callback()); |  | 
|  1700   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1701   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1702   EXPECT_EQ(3, observer_.num_changes()); |  | 
|  1703   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1704   EXPECT_EQ( |  | 
|  1705       JoinActions( |  | 
|  1706           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1707                                       outputs_[1].get()) |  | 
|  1708                      .c_str(), |  | 
|  1709           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1710           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1711           kForceDPMS, kUngrab, nullptr), |  | 
|  1712       log_->GetActionsAndClear()); |  | 
|  1713  |  | 
|  1714   // Check that the display states are not changed after resuming. |  | 
|  1715   config_waiter_.Reset(); |  | 
|  1716   // Since we are in dual display mode, a configuration task is scheduled after |  | 
|  1717   // kMinLongDelayMs delay. |  | 
|  1718   configurator_.ResumeDisplays(); |  | 
|  1719   EXPECT_EQ(kLongDelay, test_api_.GetConfigureDelay()); |  | 
|  1720   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1721             configurator_.current_power_state()); |  | 
|  1722   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  1723   // Now trigger that delayed configuration. |  | 
|  1724   EXPECT_EQ(kLongDelay, config_waiter_.Wait()); |  | 
|  1725   EXPECT_EQ( |  | 
|  1726       JoinActions( |  | 
|  1727           kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(), |  | 
|  1728                                       outputs_[1].get()) |  | 
|  1729                      .c_str(), |  | 
|  1730           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1731           GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1732           kUngrab, nullptr), |  | 
|  1733       log_->GetActionsAndClear()); |  | 
|  1734 } |  | 
|  1735  |  | 
|  1736 TEST_F(DisplayConfiguratorTest, ExternalControl) { |  | 
|  1737   InitWithSingleOutput(); |  | 
|  1738   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE); |  | 
|  1739   configurator_.RelinquishControl( |  | 
|  1740       base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated, |  | 
|  1741                  base::Unretained(this))); |  | 
|  1742   EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult()); |  | 
|  1743   EXPECT_EQ( |  | 
|  1744       JoinActions( |  | 
|  1745           kGrab, |  | 
|  1746           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1747               .c_str(), |  | 
|  1748           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1749           kUngrab, kRelinquishDisplayControl, nullptr), |  | 
|  1750       log_->GetActionsAndClear()); |  | 
|  1751   configurator_.TakeControl( |  | 
|  1752       base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated, |  | 
|  1753                  base::Unretained(this))); |  | 
|  1754   EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult()); |  | 
|  1755   EXPECT_EQ( |  | 
|  1756       JoinActions( |  | 
|  1757           kTakeDisplayControl, kGrab, |  | 
|  1758           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  1759               .c_str(), |  | 
|  1760           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1761           kForceDPMS, kUngrab, nullptr), |  | 
|  1762       log_->GetActionsAndClear()); |  | 
|  1763 } |  | 
|  1764  |  | 
|  1765 TEST_F(DisplayConfiguratorTest, |  | 
|  1766        SetDisplayPowerWhilePendingConfigurationTaskRunning) { |  | 
|  1767   // Start out with two displays in extended mode. |  | 
|  1768   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1769   Init(false); |  | 
|  1770   configurator_.ForceInitialConfigure(0); |  | 
|  1771   log_->GetActionsAndClear(); |  | 
|  1772   observer_.Reset(); |  | 
|  1773  |  | 
|  1774   native_display_delegate_->set_run_async(true); |  | 
|  1775  |  | 
|  1776   config_waiter_.Reset(); |  | 
|  1777   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  1778                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1779                                 config_waiter_.on_configuration_callback()); |  | 
|  1780   EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result()); |  | 
|  1781  |  | 
|  1782   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1783                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1784                                 config_waiter_.on_configuration_callback()); |  | 
|  1785  |  | 
|  1786   EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result()); |  | 
|  1787   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1788   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1789   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1790   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1791  |  | 
|  1792   const int kDualHeight = small_mode_.size().height() + |  | 
|  1793                           DisplayConfigurator::kVerticalGap + |  | 
|  1794                           big_mode_.size().height(); |  | 
|  1795   EXPECT_EQ( |  | 
|  1796       JoinActions( |  | 
|  1797           kGrab, |  | 
|  1798           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  1799                                outputs_[0].get(), outputs_[1].get()) |  | 
|  1800               .c_str(), |  | 
|  1801           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1802           GetCrtcAction(*outputs_[1], nullptr, |  | 
|  1803                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1804                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1805               .c_str(), |  | 
|  1806           kUngrab, nullptr), |  | 
|  1807       log_->GetActionsAndClear()); |  | 
|  1808  |  | 
|  1809   config_waiter_.Reset(); |  | 
|  1810   EXPECT_EQ( |  | 
|  1811       base::TimeDelta::FromMilliseconds(DisplayConfigurator::kConfigureDelayMs), |  | 
|  1812       config_waiter_.Wait()); |  | 
|  1813   EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result()); |  | 
|  1814   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1815   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1816   EXPECT_EQ(2, observer_.num_changes()); |  | 
|  1817   EXPECT_EQ(0, observer_.num_failures()); |  | 
|  1818  |  | 
|  1819   EXPECT_EQ( |  | 
|  1820       JoinActions( |  | 
|  1821           kGrab, |  | 
|  1822           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  1823                                outputs_[0].get(), outputs_[1].get()) |  | 
|  1824               .c_str(), |  | 
|  1825           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1826           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  1827                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1828                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1829               .c_str(), |  | 
|  1830           kForceDPMS, kUngrab, nullptr), |  | 
|  1831       log_->GetActionsAndClear()); |  | 
|  1832 } |  | 
|  1833  |  | 
|  1834 TEST_F(DisplayConfiguratorTest, |  | 
|  1835        SetDisplayPowerAfterFailedDisplayConfiguration) { |  | 
|  1836   // Start out with two displays in extended mode. |  | 
|  1837   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1838   Init(false); |  | 
|  1839   configurator_.ForceInitialConfigure(0); |  | 
|  1840   log_->GetActionsAndClear(); |  | 
|  1841   observer_.Reset(); |  | 
|  1842  |  | 
|  1843   // Fail display configuration. |  | 
|  1844   native_display_delegate_->set_max_configurable_pixels(-1); |  | 
|  1845  |  | 
|  1846   config_waiter_.Reset(); |  | 
|  1847   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  1848                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1849                                 config_waiter_.on_configuration_callback()); |  | 
|  1850   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1851   EXPECT_EQ(CALLBACK_FAILURE, config_waiter_.callback_result()); |  | 
|  1852   EXPECT_EQ(0, observer_.num_changes()); |  | 
|  1853   EXPECT_EQ(1, observer_.num_failures()); |  | 
|  1854  |  | 
|  1855   const int kDualHeight = small_mode_.size().height() + |  | 
|  1856                           DisplayConfigurator::kVerticalGap + |  | 
|  1857                           big_mode_.size().height(); |  | 
|  1858  |  | 
|  1859   EXPECT_EQ( |  | 
|  1860       JoinActions( |  | 
|  1861           kGrab, |  | 
|  1862           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  1863                                outputs_[0].get(), outputs_[1].get()) |  | 
|  1864               .c_str(), |  | 
|  1865           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1866           GetCrtcAction(*outputs_[1], nullptr, |  | 
|  1867                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1868                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1869               .c_str(), |  | 
|  1870           kUngrab, nullptr), |  | 
|  1871       log_->GetActionsAndClear()); |  | 
|  1872  |  | 
|  1873   // This configuration should trigger a display configuration since the |  | 
|  1874   // previous configuration failed. |  | 
|  1875   config_waiter_.Reset(); |  | 
|  1876   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1877                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1878                                 config_waiter_.on_configuration_callback()); |  | 
|  1879   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1880  |  | 
|  1881   EXPECT_EQ(0, observer_.num_changes()); |  | 
|  1882   EXPECT_EQ(2, observer_.num_failures()); |  | 
|  1883   EXPECT_EQ( |  | 
|  1884       JoinActions( |  | 
|  1885           kGrab, |  | 
|  1886           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  1887                                outputs_[0].get(), outputs_[1].get()) |  | 
|  1888               .c_str(), |  | 
|  1889           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1890           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  1891                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1892                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1893               .c_str(), |  | 
|  1894           GetCrtcAction(*outputs_[1], &small_mode_, |  | 
|  1895                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1896                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1897               .c_str(), |  | 
|  1898           kUngrab, nullptr), |  | 
|  1899       log_->GetActionsAndClear()); |  | 
|  1900  |  | 
|  1901   // Allow configuration to succeed. |  | 
|  1902   native_display_delegate_->set_max_configurable_pixels(0); |  | 
|  1903  |  | 
|  1904   // Validate that a configuration event has the proper power state (displays |  | 
|  1905   // should be on). |  | 
|  1906   configurator_.OnConfigurationChanged(); |  | 
|  1907   EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |  | 
|  1908  |  | 
|  1909   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  1910   EXPECT_EQ(2, observer_.num_failures()); |  | 
|  1911  |  | 
|  1912   EXPECT_EQ( |  | 
|  1913       JoinActions( |  | 
|  1914           kGrab, |  | 
|  1915           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  1916                                outputs_[0].get(), outputs_[1].get()) |  | 
|  1917               .c_str(), |  | 
|  1918           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1919           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  1920                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1921                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1922               .c_str(), |  | 
|  1923           kUngrab, nullptr), |  | 
|  1924       log_->GetActionsAndClear()); |  | 
|  1925 } |  | 
|  1926  |  | 
|  1927 TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) { |  | 
|  1928   // Start out with two displays in extended mode. |  | 
|  1929   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  1930   Init(false); |  | 
|  1931   configurator_.ForceInitialConfigure(0); |  | 
|  1932   log_->GetActionsAndClear(); |  | 
|  1933   observer_.Reset(); |  | 
|  1934  |  | 
|  1935   UpdateOutputs(3, true); |  | 
|  1936   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED); |  | 
|  1937  |  | 
|  1938   const int kDualHeight = small_mode_.size().height() + |  | 
|  1939                           DisplayConfigurator::kVerticalGap + |  | 
|  1940                           big_mode_.size().height(); |  | 
|  1941   const int kTripleHeight = 2 * small_mode_.size().height() + |  | 
|  1942                             2 * DisplayConfigurator::kVerticalGap + |  | 
|  1943                             big_mode_.size().height(); |  | 
|  1944   EXPECT_EQ( |  | 
|  1945       JoinActions( |  | 
|  1946           kGrab, GetFramebufferAction( |  | 
|  1947                      gfx::Size(big_mode_.size().width(), kTripleHeight), |  | 
|  1948                      outputs_[0].get(), outputs_[1].get()) |  | 
|  1949                      .c_str(), |  | 
|  1950           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  1951           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  1952                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1953                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1954               .c_str(), |  | 
|  1955           GetCrtcAction( |  | 
|  1956               *outputs_[2], &small_mode_, |  | 
|  1957               gfx::Point(0, small_mode_.size().height() + |  | 
|  1958                                 big_mode_.size().height() + |  | 
|  1959                                 2 * DisplayConfigurator::kVerticalGap)) |  | 
|  1960               .c_str(), |  | 
|  1961           kUngrab, nullptr), |  | 
|  1962       log_->GetActionsAndClear()); |  | 
|  1963  |  | 
|  1964   // Verify that turning the power off works. |  | 
|  1965   config_waiter_.Reset(); |  | 
|  1966   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  1967                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1968                                 config_waiter_.on_configuration_callback()); |  | 
|  1969   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1970   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1971   EXPECT_EQ( |  | 
|  1972       JoinActions( |  | 
|  1973           kGrab, GetFramebufferAction( |  | 
|  1974                      gfx::Size(big_mode_.size().width(), kTripleHeight), |  | 
|  1975                      outputs_[0].get(), outputs_[1].get()) |  | 
|  1976                      .c_str(), |  | 
|  1977           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  1978           GetCrtcAction(*outputs_[1], nullptr, |  | 
|  1979                         gfx::Point(0, small_mode_.size().height() + |  | 
|  1980                                           DisplayConfigurator::kVerticalGap)) |  | 
|  1981               .c_str(), |  | 
|  1982           GetCrtcAction( |  | 
|  1983               *outputs_[2], nullptr, |  | 
|  1984               gfx::Point(0, small_mode_.size().height() + |  | 
|  1985                                 big_mode_.size().height() + |  | 
|  1986                                 2 * DisplayConfigurator::kVerticalGap)) |  | 
|  1987               .c_str(), |  | 
|  1988           kUngrab, nullptr), |  | 
|  1989       log_->GetActionsAndClear()); |  | 
|  1990  |  | 
|  1991   config_waiter_.Reset(); |  | 
|  1992   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  1993                                 DisplayConfigurator::kSetDisplayPowerNoFlags, |  | 
|  1994                                 config_waiter_.on_configuration_callback()); |  | 
|  1995   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  1996   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  1997   EXPECT_EQ( |  | 
|  1998       JoinActions( |  | 
|  1999           kGrab, GetFramebufferAction( |  | 
|  2000                      gfx::Size(big_mode_.size().width(), kTripleHeight), |  | 
|  2001                      outputs_[0].get(), outputs_[1].get()) |  | 
|  2002                      .c_str(), |  | 
|  2003           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  2004           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  2005                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2006                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2007               .c_str(), |  | 
|  2008           GetCrtcAction( |  | 
|  2009               *outputs_[2], &small_mode_, |  | 
|  2010               gfx::Point(0, small_mode_.size().height() + |  | 
|  2011                                 big_mode_.size().height() + |  | 
|  2012                                 2 * DisplayConfigurator::kVerticalGap)) |  | 
|  2013               .c_str(), |  | 
|  2014           kForceDPMS, kUngrab, nullptr), |  | 
|  2015       log_->GetActionsAndClear()); |  | 
|  2016  |  | 
|  2017   // Disconnect the third output. |  | 
|  2018   observer_.Reset(); |  | 
|  2019   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  2020   UpdateOutputs(2, true); |  | 
|  2021   EXPECT_EQ( |  | 
|  2022       JoinActions( |  | 
|  2023           kGrab, |  | 
|  2024           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  2025                                outputs_[0].get(), outputs_[1].get()) |  | 
|  2026               .c_str(), |  | 
|  2027           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  2028           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  2029                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2030                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2031               .c_str(), |  | 
|  2032           kUngrab, nullptr), |  | 
|  2033       log_->GetActionsAndClear()); |  | 
|  2034 } |  | 
|  2035  |  | 
|  2036 // Tests the suspend and resume behavior when in dual or multi display modes. |  | 
|  2037 TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) { |  | 
|  2038   InitWithSingleOutput(); |  | 
|  2039   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); |  | 
|  2040   observer_.Reset(); |  | 
|  2041   UpdateOutputs(2, true); |  | 
|  2042   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|  2043             configurator_.display_state()); |  | 
|  2044   EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); |  | 
|  2045   EXPECT_EQ(1, observer_.num_changes()); |  | 
|  2046   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  2047             configurator_.current_power_state()); |  | 
|  2048   const int kDualHeight = small_mode_.size().height() + |  | 
|  2049                           DisplayConfigurator::kVerticalGap + |  | 
|  2050                           big_mode_.size().height(); |  | 
|  2051   EXPECT_EQ( |  | 
|  2052       JoinActions( |  | 
|  2053           kGrab, |  | 
|  2054           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  2055                                outputs_[0].get(), outputs_[1].get()) |  | 
|  2056               .c_str(), |  | 
|  2057           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  2058           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  2059                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2060                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2061               .c_str(), |  | 
|  2062           kUngrab, nullptr), |  | 
|  2063       log_->GetActionsAndClear()); |  | 
|  2064  |  | 
|  2065   // Suspending displays should result in an immediate configuration without |  | 
|  2066   // delays, even in dual display mode. |  | 
|  2067   config_waiter_.Reset(); |  | 
|  2068   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  2069   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  2070   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  2071   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  2072             configurator_.current_power_state()); |  | 
|  2073   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|  2074             configurator_.display_state()); |  | 
|  2075   EXPECT_EQ( |  | 
|  2076       JoinActions( |  | 
|  2077           kGrab, |  | 
|  2078           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  2079                                outputs_[0].get(), outputs_[1].get()) |  | 
|  2080               .c_str(), |  | 
|  2081           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  2082           GetCrtcAction(*outputs_[1], nullptr, |  | 
|  2083                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2084                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2085               .c_str(), |  | 
|  2086           kUngrab, kSync, nullptr), |  | 
|  2087       log_->GetActionsAndClear()); |  | 
|  2088  |  | 
|  2089   // Resuming from suspend with dual displays. Configuration should be done |  | 
|  2090   // after a long delay. Afterwards, we should still expect to be in a dual |  | 
|  2091   // display mode. |  | 
|  2092   config_waiter_.Reset(); |  | 
|  2093   configurator_.ResumeDisplays(); |  | 
|  2094   EXPECT_EQ(kLongDelay, config_waiter_.Wait()); |  | 
|  2095   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  2096             configurator_.current_power_state()); |  | 
|  2097   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|  2098             configurator_.display_state()); |  | 
|  2099   EXPECT_EQ( |  | 
|  2100       JoinActions( |  | 
|  2101           kGrab, |  | 
|  2102           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  2103                                outputs_[0].get(), outputs_[1].get()) |  | 
|  2104               .c_str(), |  | 
|  2105           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  2106           GetCrtcAction(*outputs_[1], &big_mode_, |  | 
|  2107                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2108                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2109               .c_str(), |  | 
|  2110           kForceDPMS, kUngrab, nullptr), |  | 
|  2111       log_->GetActionsAndClear()); |  | 
|  2112  |  | 
|  2113   // Suspend displays and disconnect one of them while in suspend. |  | 
|  2114   config_waiter_.Reset(); |  | 
|  2115   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  2116   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  2117   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  2118   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, |  | 
|  2119             configurator_.display_state()); |  | 
|  2120   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  2121             configurator_.current_power_state()); |  | 
|  2122   EXPECT_EQ( |  | 
|  2123       JoinActions( |  | 
|  2124           kGrab, |  | 
|  2125           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), |  | 
|  2126                                outputs_[0].get(), outputs_[1].get()) |  | 
|  2127               .c_str(), |  | 
|  2128           GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(), |  | 
|  2129           GetCrtcAction(*outputs_[1], nullptr, |  | 
|  2130                         gfx::Point(0, small_mode_.size().height() + |  | 
|  2131                                           DisplayConfigurator::kVerticalGap)) |  | 
|  2132               .c_str(), |  | 
|  2133           kUngrab, kSync, nullptr), |  | 
|  2134       log_->GetActionsAndClear()); |  | 
|  2135   UpdateOutputs(1, false); |  | 
|  2136   EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); |  | 
|  2137  |  | 
|  2138   // Now resume, and expect that we'll still have a long delay since we were in |  | 
|  2139   // dual mode before suspend. The configurator should pick up the change and |  | 
|  2140   // detect that we are in single display mode now. |  | 
|  2141   config_waiter_.Reset(); |  | 
|  2142   configurator_.ResumeDisplays(); |  | 
|  2143   EXPECT_EQ(kLongDelay, config_waiter_.Wait()); |  | 
|  2144   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  2145             configurator_.current_power_state()); |  | 
|  2146   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); |  | 
|  2147   EXPECT_EQ( |  | 
|  2148       JoinActions( |  | 
|  2149           kGrab, |  | 
|  2150           GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr) |  | 
|  2151               .c_str(), |  | 
|  2152           GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), |  | 
|  2153           kForceDPMS, kUngrab, nullptr), |  | 
|  2154       log_->GetActionsAndClear()); |  | 
|  2155  |  | 
|  2156   // Verify that the above is the exact same behavior for 3+ displays. |  | 
|  2157   UpdateOutputs(3, true); |  | 
|  2158   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |  | 
|  2159             configurator_.display_state()); |  | 
|  2160  |  | 
|  2161   // Suspend. |  | 
|  2162   config_waiter_.Reset(); |  | 
|  2163   configurator_.SuspendDisplays(config_waiter_.on_configuration_callback()); |  | 
|  2164   EXPECT_EQ(kNoDelay, config_waiter_.Wait()); |  | 
|  2165   EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result()); |  | 
|  2166   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |  | 
|  2167             configurator_.display_state()); |  | 
|  2168   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, |  | 
|  2169             configurator_.current_power_state()); |  | 
|  2170  |  | 
|  2171   // Resume and expect the correct delay. |  | 
|  2172   config_waiter_.Reset(); |  | 
|  2173   configurator_.ResumeDisplays(); |  | 
|  2174   EXPECT_EQ(kLongDelay, config_waiter_.Wait()); |  | 
|  2175   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, |  | 
|  2176             configurator_.current_power_state()); |  | 
|  2177   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, |  | 
|  2178             configurator_.display_state()); |  | 
|  2179 } |  | 
|  2180  |  | 
|  2181 }  // namespace test |  | 
|  2182 }  // namespace ui |  | 
| OLD | NEW |