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