Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: ui/display/chromeos/display_configurator_unittest.cc

Issue 2540313002: Split //ui/display and create //ui/display/manager. (Closed)
Patch Set: Cleanup export header. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW
« no previous file with comments | « ui/display/chromeos/display_configurator.cc ('k') | ui/display/chromeos/display_layout_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698