| Index: ui/display/chromeos/display_configurator_unittest.cc
|
| diff --git a/ui/display/chromeos/display_configurator_unittest.cc b/ui/display/chromeos/display_configurator_unittest.cc
|
| deleted file mode 100644
|
| index 61692539c2b7bb093b1d0027b174e0088865d2ca..0000000000000000000000000000000000000000
|
| --- a/ui/display/chromeos/display_configurator_unittest.cc
|
| +++ /dev/null
|
| @@ -1,2182 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "ui/display/chromeos/display_configurator.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/memory/scoped_vector.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/run_loop.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "ui/display/chromeos/test/action_logger_util.h"
|
| -#include "ui/display/chromeos/test/test_native_display_delegate.h"
|
| -#include "ui/display/fake_display_snapshot.h"
|
| -#include "ui/display/util/display_util.h"
|
| -
|
| -namespace ui {
|
| -namespace test {
|
| -
|
| -namespace {
|
| -
|
| -int64_t kDisplayIds[3] = {123, 456, 789};
|
| -
|
| -std::unique_ptr<ui::DisplayMode> MakeDisplayMode(int width,
|
| - int height,
|
| - bool is_interlaced,
|
| - float refresh_rate) {
|
| - return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height),
|
| - is_interlaced, refresh_rate);
|
| -}
|
| -
|
| -enum CallbackResult {
|
| - CALLBACK_FAILURE,
|
| - CALLBACK_SUCCESS,
|
| - CALLBACK_NOT_CALLED,
|
| -};
|
| -
|
| -// Expected immediate configurations should be done without any delays.
|
| -constexpr base::TimeDelta kNoDelay = base::TimeDelta::FromMilliseconds(0);
|
| -
|
| -// The expected configuration delay when resuming from suspend while in 2+
|
| -// display mode.
|
| -constexpr base::TimeDelta kLongDelay = base::TimeDelta::FromMilliseconds(
|
| - DisplayConfigurator::kResumeConfigureMultiDisplayDelayMs);
|
| -
|
| -class TestObserver : public DisplayConfigurator::Observer {
|
| - public:
|
| - explicit TestObserver(DisplayConfigurator* configurator)
|
| - : configurator_(configurator) {
|
| - Reset();
|
| - configurator_->AddObserver(this);
|
| - }
|
| - ~TestObserver() override { configurator_->RemoveObserver(this); }
|
| -
|
| - int num_changes() const { return num_changes_; }
|
| - int num_failures() const { return num_failures_; }
|
| - const DisplayConfigurator::DisplayStateList& latest_outputs() const {
|
| - return latest_outputs_;
|
| - }
|
| - MultipleDisplayState latest_failed_state() const {
|
| - return latest_failed_state_;
|
| - }
|
| -
|
| - void Reset() {
|
| - num_changes_ = 0;
|
| - num_failures_ = 0;
|
| - latest_outputs_.clear();
|
| - latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
|
| - }
|
| -
|
| - // DisplayConfigurator::Observer overrides:
|
| - void OnDisplayModeChanged(
|
| - const DisplayConfigurator::DisplayStateList& outputs) override {
|
| - num_changes_++;
|
| - latest_outputs_ = outputs;
|
| - }
|
| -
|
| - void OnDisplayModeChangeFailed(
|
| - const DisplayConfigurator::DisplayStateList& outputs,
|
| - MultipleDisplayState failed_new_state) override {
|
| - num_failures_++;
|
| - latest_failed_state_ = failed_new_state;
|
| - }
|
| -
|
| - private:
|
| - DisplayConfigurator* configurator_; // Not owned.
|
| -
|
| - // Number of times that OnDisplayMode*() has been called.
|
| - int num_changes_;
|
| - int num_failures_;
|
| -
|
| - // Parameters most recently passed to OnDisplayMode*().
|
| - DisplayConfigurator::DisplayStateList latest_outputs_;
|
| - MultipleDisplayState latest_failed_state_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestObserver);
|
| -};
|
| -
|
| -class TestStateController : public DisplayConfigurator::StateController {
|
| - public:
|
| - TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {}
|
| - ~TestStateController() override {}
|
| -
|
| - void set_state(MultipleDisplayState state) { state_ = state; }
|
| -
|
| - // DisplayConfigurator::StateController overrides:
|
| - MultipleDisplayState GetStateForDisplayIds(
|
| - const DisplayConfigurator::DisplayStateList& outputs) const override {
|
| - return state_;
|
| - }
|
| - bool GetResolutionForDisplayId(int64_t display_id,
|
| - gfx::Size* size) const override {
|
| - return false;
|
| - }
|
| -
|
| - private:
|
| - MultipleDisplayState state_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestStateController);
|
| -};
|
| -
|
| -class TestMirroringController
|
| - : public DisplayConfigurator::SoftwareMirroringController {
|
| - public:
|
| - TestMirroringController() : software_mirroring_enabled_(false) {}
|
| - ~TestMirroringController() override {}
|
| -
|
| - void SetSoftwareMirroring(bool enabled) override {
|
| - software_mirroring_enabled_ = enabled;
|
| - }
|
| -
|
| - bool SoftwareMirroringEnabled() const override {
|
| - return software_mirroring_enabled_;
|
| - }
|
| -
|
| - private:
|
| - bool software_mirroring_enabled_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
|
| -};
|
| -
|
| -// Abstracts waiting for the display configuration to be completed and getting
|
| -// the time it took to complete.
|
| -class ConfigurationWaiter {
|
| - public:
|
| - ConfigurationWaiter(DisplayConfigurator::TestApi* test_api)
|
| - : on_configured_callback_(base::Bind(&ConfigurationWaiter::OnConfigured,
|
| - base::Unretained(this))),
|
| - test_api_(test_api),
|
| - callback_result_(CALLBACK_NOT_CALLED) {}
|
| -
|
| - ~ConfigurationWaiter() = default;
|
| -
|
| - const DisplayConfigurator::ConfigurationCallback& on_configuration_callback()
|
| - const {
|
| - return on_configured_callback_;
|
| - }
|
| -
|
| - CallbackResult callback_result() const { return callback_result_; }
|
| -
|
| - void Reset() { callback_result_ = CALLBACK_NOT_CALLED; }
|
| -
|
| - // Simulates waiting for the next configuration. If an async task is pending,
|
| - // runs it and returns base::TimeDelta(). Otherwise, triggers the
|
| - // configuration timer and returns its delay. If the timer wasn't running,
|
| - // returns base::TimeDelta::Max().
|
| - base::TimeDelta Wait() WARN_UNUSED_RESULT {
|
| - base::RunLoop().RunUntilIdle();
|
| - if (callback_result_ != CALLBACK_NOT_CALLED)
|
| - return base::TimeDelta();
|
| -
|
| - const base::TimeDelta delay = test_api_->GetConfigureDelay();
|
| - if (!test_api_->TriggerConfigureTimeout())
|
| - return base::TimeDelta::Max();
|
| -
|
| - return delay;
|
| - }
|
| -
|
| - private:
|
| - void OnConfigured(bool status) {
|
| - CHECK_EQ(callback_result_, CALLBACK_NOT_CALLED);
|
| - callback_result_ = status ? CALLBACK_SUCCESS : CALLBACK_FAILURE;
|
| - }
|
| -
|
| - // Passed with configuration requests to run OnConfigured().
|
| - const DisplayConfigurator::ConfigurationCallback on_configured_callback_;
|
| -
|
| - DisplayConfigurator::TestApi* test_api_; // Not owned.
|
| -
|
| - // The status of the display configuration.
|
| - CallbackResult callback_result_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ConfigurationWaiter);
|
| -};
|
| -
|
| -class DisplayConfiguratorTest : public testing::Test {
|
| - public:
|
| - DisplayConfiguratorTest()
|
| - : small_mode_(gfx::Size(1366, 768), false, 60.0f),
|
| - big_mode_(gfx::Size(2560, 1600), false, 60.0f),
|
| - observer_(&configurator_),
|
| - test_api_(&configurator_),
|
| - config_waiter_(&test_api_),
|
| - enable_content_protection_status_(0),
|
| - enable_content_protection_call_count_(0),
|
| - query_content_protection_call_count_(0),
|
| - display_control_result_(CALLBACK_NOT_CALLED) {}
|
| - ~DisplayConfiguratorTest() override {}
|
| -
|
| - void SetUp() override {
|
| - log_.reset(new ActionLogger());
|
| -
|
| - native_display_delegate_ = new TestNativeDisplayDelegate(log_.get());
|
| - configurator_.SetDelegateForTesting(
|
| - std::unique_ptr<NativeDisplayDelegate>(native_display_delegate_));
|
| -
|
| - configurator_.set_state_controller(&state_controller_);
|
| - configurator_.set_mirroring_controller(&mirroring_controller_);
|
| -
|
| - outputs_[0] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[0])
|
| - .SetNativeMode(small_mode_.Clone())
|
| - .SetCurrentMode(small_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - outputs_[1] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[1])
|
| - .SetNativeMode(big_mode_.Clone())
|
| - .SetCurrentMode(big_mode_.Clone())
|
| - .AddMode(small_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - outputs_[2] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[2])
|
| - .SetNativeMode(small_mode_.Clone())
|
| - .SetCurrentMode(small_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - UpdateOutputs(2, false);
|
| - }
|
| -
|
| - void OnDisplayControlUpdated(bool status) {
|
| - display_control_result_ = (status ? CALLBACK_SUCCESS : CALLBACK_FAILURE);
|
| - }
|
| -
|
| - void EnableContentProtectionCallback(bool status) {
|
| - enable_content_protection_status_ = status;
|
| - enable_content_protection_call_count_++;
|
| - }
|
| -
|
| - void QueryContentProtectionCallback(
|
| - const DisplayConfigurator::QueryProtectionResponse& response) {
|
| - query_content_protection_response_ = response;
|
| - query_content_protection_call_count_++;
|
| - }
|
| -
|
| - // Predefined modes that can be used by outputs.
|
| - const DisplayMode small_mode_;
|
| - const DisplayMode big_mode_;
|
| -
|
| - protected:
|
| - // Configures |native_display_delegate_| to return the first |num_outputs|
|
| - // entries from
|
| - // |outputs_|. If |send_events| is true, also sends screen-change and
|
| - // output-change events to |configurator_| and triggers the configure
|
| - // timeout if one was scheduled.
|
| - void UpdateOutputs(size_t num_outputs, bool send_events) {
|
| - ASSERT_LE(num_outputs, arraysize(outputs_));
|
| - std::vector<DisplaySnapshot*> outputs;
|
| - for (size_t i = 0; i < num_outputs; ++i)
|
| - outputs.push_back(outputs_[i].get());
|
| - native_display_delegate_->set_outputs(outputs);
|
| -
|
| - if (send_events) {
|
| - configurator_.OnConfigurationChanged();
|
| - EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
|
| - }
|
| - }
|
| -
|
| - void Init(bool panel_fitting_enabled) {
|
| - configurator_.Init(nullptr, panel_fitting_enabled);
|
| - }
|
| -
|
| - // Initializes |configurator_| with a single internal display.
|
| - void InitWithSingleOutput() {
|
| - UpdateOutputs(1, false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - configurator_.Init(nullptr, false);
|
| -
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kInitXRandR, kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - }
|
| -
|
| - CallbackResult PopDisplayControlResult() {
|
| - CallbackResult result = display_control_result_;
|
| - display_control_result_ = CALLBACK_NOT_CALLED;
|
| - return result;
|
| - }
|
| -
|
| - base::MessageLoop message_loop_;
|
| - TestStateController state_controller_;
|
| - TestMirroringController mirroring_controller_;
|
| - DisplayConfigurator configurator_;
|
| - TestObserver observer_;
|
| - std::unique_ptr<ActionLogger> log_;
|
| - TestNativeDisplayDelegate* native_display_delegate_; // not owned
|
| - DisplayConfigurator::TestApi test_api_;
|
| - ConfigurationWaiter config_waiter_;
|
| - bool enable_content_protection_status_;
|
| - int enable_content_protection_call_count_;
|
| - DisplayConfigurator::QueryProtectionResponse
|
| - query_content_protection_response_;
|
| - int query_content_protection_call_count_;
|
| -
|
| - std::unique_ptr<DisplaySnapshot> outputs_[3];
|
| -
|
| - CallbackResult display_control_result_;
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) {
|
| - std::unique_ptr<ui::DisplaySnapshot> output =
|
| - display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[0])
|
| - .AddMode(MakeDisplayMode(1920, 1200, false, 60.0))
|
| - .SetNativeMode(MakeDisplayMode(1920, 1200, false, 50.0))
|
| - // Different rates.
|
| - .AddMode(MakeDisplayMode(1920, 1080, false, 30.0))
|
| - .AddMode(MakeDisplayMode(1920, 1080, false, 50.0))
|
| - .AddMode(MakeDisplayMode(1920, 1080, false, 40.0))
|
| - .AddMode(MakeDisplayMode(1920, 1080, false, 0.0))
|
| - // Interlaced vs non-interlaced.
|
| - .AddMode(MakeDisplayMode(1280, 720, true, 60.0))
|
| - .AddMode(MakeDisplayMode(1280, 720, false, 40.0))
|
| - // Interlaced only.
|
| - .AddMode(MakeDisplayMode(1024, 768, true, 0.0))
|
| - .AddMode(MakeDisplayMode(1024, 768, true, 40.0))
|
| - .AddMode(MakeDisplayMode(1024, 768, true, 60.0))
|
| - // Mixed.
|
| - .AddMode(MakeDisplayMode(1024, 600, true, 60.0))
|
| - .AddMode(MakeDisplayMode(1024, 600, false, 40.0))
|
| - .AddMode(MakeDisplayMode(1024, 600, false, 50.0))
|
| - // Just one interlaced mode.
|
| - .AddMode(MakeDisplayMode(640, 480, true, 60.0))
|
| - // Refresh rate not available.
|
| - .AddMode(MakeDisplayMode(320, 200, false, 0.0))
|
| - .Build();
|
| -
|
| - const std::vector<std::unique_ptr<const DisplayMode>>& modes =
|
| - output->modes();
|
| -
|
| - // Should pick native over highest refresh rate.
|
| - EXPECT_EQ(modes[1].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1920, 1200)));
|
| -
|
| - // Should pick highest refresh rate.
|
| - EXPECT_EQ(modes[3].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1920, 1080)));
|
| -
|
| - // Should pick non-interlaced mode.
|
| - EXPECT_EQ(modes[7].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1280, 720)));
|
| -
|
| - // Interlaced only. Should pick one with the highest refresh rate in
|
| - // interlaced mode.
|
| - EXPECT_EQ(modes[10].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1024, 768)));
|
| -
|
| - // Mixed: Should pick one with the highest refresh rate in
|
| - // interlaced mode.
|
| - EXPECT_EQ(modes[13].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1024, 600)));
|
| -
|
| - // Just one interlaced mode.
|
| - EXPECT_EQ(modes[14].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(640, 480)));
|
| -
|
| - // Refresh rate not available.
|
| - EXPECT_EQ(modes[15].get(), DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(320, 200)));
|
| -
|
| - // No mode found.
|
| - EXPECT_EQ(nullptr, DisplayConfigurator::FindDisplayModeMatchingSize(
|
| - *output, gfx::Size(1440, 900)));
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, EnableVirtualDisplay) {
|
| - InitWithSingleOutput();
|
| -
|
| - observer_.Reset();
|
| - const DisplayConfigurator::DisplayStateList& cached =
|
| - configurator_.cached_displays();
|
| - ASSERT_EQ(static_cast<size_t>(1u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| -
|
| - // Add virtual display.
|
| - int64_t virtual_display_id =
|
| - configurator_.AddVirtualDisplay(big_mode_.size());
|
| - EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 1), virtual_display_id);
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| -
|
| - // Virtual should not trigger addition of added crtc but does change FB
|
| - // height.
|
| - const int kVirtualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kVirtualHeight),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(2u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size());
|
| - EXPECT_EQ(virtual_display_id, cached[1]->display_id());
|
| -
|
| - // Remove virtual display.
|
| - observer_.Reset();
|
| - EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id));
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(1u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, EnableTwoVirtualDisplays) {
|
| - InitWithSingleOutput();
|
| -
|
| - observer_.Reset();
|
| - const DisplayConfigurator::DisplayStateList& cached =
|
| - configurator_.cached_displays();
|
| - ASSERT_EQ(static_cast<size_t>(1u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| -
|
| - // Add 1st virtual display.
|
| - int64_t virtual_display_id_1 =
|
| - configurator_.AddVirtualDisplay(big_mode_.size());
|
| - EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 1), virtual_display_id_1);
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| -
|
| - // Virtual should not trigger addition of added crtc but does change FB
|
| - // height.
|
| - const int kSingleVirtualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kSingleVirtualHeight),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(2), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size());
|
| - EXPECT_EQ(virtual_display_id_1, cached[1]->display_id());
|
| -
|
| - // Add 2nd virtual display
|
| - int64_t virtual_display_id_2 =
|
| - configurator_.AddVirtualDisplay(big_mode_.size());
|
| - EXPECT_EQ(display::GenerateDisplayID(0x8000, 0x0, 2), virtual_display_id_2);
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED,
|
| - configurator_.display_state());
|
| -
|
| - const int kDualVirtualHeight =
|
| - small_mode_.size().height() +
|
| - (DisplayConfigurator::kVerticalGap + big_mode_.size().height()) * 2;
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kDualVirtualHeight),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(2, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(3u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size());
|
| - EXPECT_EQ(big_mode_.size(), cached[2]->current_mode()->size());
|
| - EXPECT_EQ(virtual_display_id_1, cached[1]->display_id());
|
| - EXPECT_EQ(virtual_display_id_2, cached[2]->display_id());
|
| -
|
| - // Remove 1st virtual display.
|
| - observer_.Reset();
|
| - EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id_1));
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kSingleVirtualHeight),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(2u), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(big_mode_.size(), cached[1]->current_mode()->size());
|
| - EXPECT_EQ(virtual_display_id_2, cached[1]->display_id());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| -
|
| - // Remove 2nd virtual display.
|
| - observer_.Reset();
|
| - EXPECT_TRUE(configurator_.RemoveVirtualDisplay(virtual_display_id_2));
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(1), cached.size());
|
| - EXPECT_EQ(small_mode_.size(), cached[0]->current_mode()->size());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
|
| - InitWithSingleOutput();
|
| -
|
| - // Connect a second output and check that the configurator enters
|
| - // extended mode.
|
| - observer_.Reset();
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - UpdateOutputs(2, true);
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Disconnect the second output.
|
| - observer_.Reset();
|
| - UpdateOutputs(1, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Get rid of shared modes to force software mirroring.
|
| - outputs_[1] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[1])
|
| - .SetNativeMode(big_mode_.Clone())
|
| - .SetCurrentMode(big_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - UpdateOutputs(2, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - const gfx::Size framebuffer_size = configurator_.framebuffer_size();
|
| - DCHECK(!framebuffer_size.IsEmpty());
|
| -
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(framebuffer_size.ToString(),
|
| - configurator_.framebuffer_size().ToString());
|
| -
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - EXPECT_EQ(JoinActions(nullptr), log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Set back to software mirror mode.
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Disconnect the second output.
|
| - observer_.Reset();
|
| - UpdateOutputs(1, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
|
| - InitWithSingleOutput();
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - observer_.Reset();
|
| - UpdateOutputs(2, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Turning off the internal display should switch the external display to
|
| - // its native mode.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(
|
| - chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // When all displays are turned off, the framebuffer should switch back
|
| - // to the mirrored size.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Turn all displays on and check that mirroring is still used.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Get rid of shared modes to force software mirroring.
|
| - outputs_[1] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[1])
|
| - .SetNativeMode(big_mode_.Clone())
|
| - .SetCurrentMode(big_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - observer_.Reset();
|
| - UpdateOutputs(2, true);
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Turning off the internal display should switch the external display to
|
| - // its native mode.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(
|
| - chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // When all displays are turned off, the framebuffer should switch back
|
| - // to the extended + software mirroring.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -
|
| - // Turn all displays on and check that mirroring is still used.
|
| - observer_.Reset();
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
|
| - InitWithSingleOutput();
|
| -
|
| - // No preparation is needed before suspending when the display is already
|
| - // on. The configurator should still reprobe on resume in case a display
|
| - // was connected while suspended.
|
| - const gfx::Size framebuffer_size = configurator_.framebuffer_size();
|
| - DCHECK(!framebuffer_size.IsEmpty());
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(framebuffer_size.ToString(),
|
| - configurator_.framebuffer_size().ToString());
|
| - EXPECT_EQ(JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // No resume delay in single display mode.
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - // The timer should not be running.
|
| - EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Now turn the display off before suspending and check that the
|
| - // configurator turns it back on and syncs with the server.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(kSync, log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - // The timer should not be running.
|
| - EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - UpdateOutputs(2, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // No delay in suspend.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| - EXPECT_EQ(kSync, log_->GetActionsAndClear());
|
| -
|
| - // If a display is disconnected while suspended, the configurator should
|
| - // pick up the change and only turn on the internal display. The should be
|
| - // a longer configuration delay when we set the displays back to on.
|
| - UpdateOutputs(1, false);
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - // Since we were in dual display mirror mode before suspend, the timer should
|
| - // be running with kMinLongDelayMs.
|
| - EXPECT_EQ(kLongDelay, test_api_.GetConfigureDelay());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result());
|
| - EXPECT_EQ(kLongDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, Headless) {
|
| - UpdateOutputs(0, false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - Init(false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_EQ(JoinActions(kInitXRandR, kGrab, kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Not much should happen when the display power state is changed while
|
| - // no displays are connected.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Connect an external display and check that it's configured correctly.
|
| - outputs_[0] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[0])
|
| - .SetNativeMode(big_mode_.Clone())
|
| - .SetCurrentMode(big_mode_.Clone())
|
| - .AddMode(small_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - UpdateOutputs(1, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| - const gfx::Size framebuffer_size = configurator_.framebuffer_size();
|
| - DCHECK(!framebuffer_size.IsEmpty());
|
| -
|
| - UpdateOutputs(0, true);
|
| - EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
|
| - EXPECT_EQ(framebuffer_size.ToString(),
|
| - configurator_.framebuffer_size().ToString());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
|
| - UpdateOutputs(2, false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - Init(false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kInitXRandR, kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
|
| - UpdateOutputs(0, false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS);
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(3, observer_.num_failures());
|
| -
|
| - UpdateOutputs(1, true);
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS);
|
| - EXPECT_EQ(0, observer_.num_changes());
|
| - EXPECT_EQ(1, observer_.num_failures());
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(1, observer_.num_failures());
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(3, observer_.num_failures());
|
| -
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - UpdateOutputs(2, true);
|
| - observer_.Reset();
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - EXPECT_EQ(0, observer_.num_changes());
|
| - EXPECT_EQ(2, observer_.num_failures());
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - EXPECT_EQ(2, observer_.num_changes());
|
| - EXPECT_EQ(2, observer_.num_failures());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForMirroredDisplays) {
|
| - UpdateOutputs(2, false);
|
| - Init(false);
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
|
| - InitWithSingleOutput();
|
| - const DisplayConfigurator::DisplayStateList& cached =
|
| - configurator_.cached_displays();
|
| - ASSERT_EQ(static_cast<size_t>(1), cached.size());
|
| - EXPECT_EQ(outputs_[0]->current_mode(), cached[0]->current_mode());
|
| -
|
| - // After connecting a second output, check that it shows up in
|
| - // |cached_displays_| even if an invalid state is requested.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - UpdateOutputs(2, true);
|
| - ASSERT_EQ(static_cast<size_t>(2), cached.size());
|
| - EXPECT_EQ(outputs_[0]->current_mode(), cached[0]->current_mode());
|
| - EXPECT_EQ(outputs_[1]->current_mode(), cached[1]->current_mode());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, PanelFitting) {
|
| - // Configure the internal display to support only the big mode and the
|
| - // external display to support only the small mode.
|
| - outputs_[0] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[0])
|
| - .SetNativeMode(big_mode_.Clone())
|
| - .SetCurrentMode(big_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - outputs_[1] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[1])
|
| - .SetNativeMode(small_mode_.Clone())
|
| - .SetCurrentMode(small_mode_.Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - // The small mode should be added to the internal output when requesting
|
| - // mirrored mode.
|
| - UpdateOutputs(2, false);
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - Init(true /* is_panel_fitting_enabled */);
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kInitXRandR, kGrab,
|
| - GetAddOutputModeAction(*outputs_[0], &small_mode_).c_str(),
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Both outputs should be using the small mode.
|
| - ASSERT_EQ(1, observer_.num_changes());
|
| - ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
|
| - EXPECT_EQ(small_mode_.size(),
|
| - observer_.latest_outputs()[0]->current_mode()->size());
|
| - EXPECT_EQ(small_mode_.size(),
|
| - observer_.latest_outputs()[1]->current_mode()->size());
|
| -
|
| - // Also test that there are 2 modes (instead of the initial one) in the
|
| - // snapshot that was passed to the observer (http://crbug.com/289159).
|
| - DisplaySnapshot* state = observer_.latest_outputs()[0];
|
| - ASSERT_EQ(2UL, state->modes().size());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, ContentProtection) {
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - EXPECT_NE(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - DisplayConfigurator::ContentProtectionClientId id =
|
| - configurator_.RegisterContentProtectionClient();
|
| - EXPECT_NE(0u, id);
|
| -
|
| - // One output.
|
| - UpdateOutputs(1, true);
|
| - EXPECT_NE(kNoActions, log_->GetActionsAndClear());
|
| - configurator_.QueryContentProtectionStatus(
|
| - id, outputs_[0]->display_id(),
|
| - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(1, query_content_protection_call_count_);
|
| - EXPECT_TRUE(query_content_protection_response_.success);
|
| - EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL),
|
| - query_content_protection_response_.link_mask);
|
| - EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
|
| - query_content_protection_response_.protection_mask);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // Two outputs.
|
| - UpdateOutputs(2, true);
|
| - EXPECT_NE(kNoActions, log_->GetActionsAndClear());
|
| - configurator_.QueryContentProtectionStatus(
|
| - id, outputs_[1]->display_id(),
|
| - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(2, query_content_protection_call_count_);
|
| - EXPECT_TRUE(query_content_protection_response_.success);
|
| - EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI),
|
| - query_content_protection_response_.link_mask);
|
| - EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
|
| - query_content_protection_response_.protection_mask);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - configurator_.EnableContentProtection(
|
| - id, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(1, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Enable protection.
|
| - native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
|
| - configurator_.QueryContentProtectionStatus(
|
| - id, outputs_[1]->display_id(),
|
| - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(3, query_content_protection_call_count_);
|
| - EXPECT_TRUE(query_content_protection_response_.success);
|
| - EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI),
|
| - query_content_protection_response_.link_mask);
|
| - EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP),
|
| - query_content_protection_response_.protection_mask);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // Protections should be disabled after unregister.
|
| - configurator_.UnregisterContentProtectionClient(id);
|
| - EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_UNDESIRED),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) {
|
| - InitWithSingleOutput();
|
| -
|
| - // The DisplayConfigurator may occasionally receive OnConfigurationChanged()
|
| - // after the displays have been suspended. This event should be ignored since
|
| - // the DisplayConfigurator will force a probe and reconfiguration of displays
|
| - // at resume time.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // The configuration timer should not be started when the displays
|
| - // are suspended.
|
| - configurator_.OnConfigurationChanged();
|
| - EXPECT_FALSE(test_api_.TriggerConfigureTimeout());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // Calls to SetDisplayPower should do nothing if the power state doesn't
|
| - // change.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - UpdateOutputs(2, false);
|
| - configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // The DisplayConfigurator should do nothing at resume time if there is no
|
| - // state change.
|
| - config_waiter_.Reset();
|
| - UpdateOutputs(1, false);
|
| - configurator_.ResumeDisplays();
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // If a configuration task is pending when the displays are suspended, that
|
| - // task should not run either and the timer should be stopped. The displays
|
| - // should be turned off by suspend.
|
| - configurator_.OnConfigurationChanged();
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(),
|
| - outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| - EXPECT_FALSE(test_api_.TriggerConfigureTimeout());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - // The timer should not be running.
|
| - EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
|
| - DisplayConfigurator::ContentProtectionClientId client1 =
|
| - configurator_.RegisterContentProtectionClient();
|
| - DisplayConfigurator::ContentProtectionClientId client2 =
|
| - configurator_.RegisterContentProtectionClient();
|
| - EXPECT_NE(client1, client2);
|
| -
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - UpdateOutputs(2, true);
|
| - EXPECT_NE(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // Clients never know state enableness for methods that they didn't request.
|
| - configurator_.EnableContentProtection(
|
| - client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(1, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(),
|
| - log_->GetActionsAndClear());
|
| - native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
|
| -
|
| - configurator_.QueryContentProtectionStatus(
|
| - client1, outputs_[1]->display_id(),
|
| - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(1, query_content_protection_call_count_);
|
| - EXPECT_TRUE(query_content_protection_response_.success);
|
| - EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI),
|
| - query_content_protection_response_.link_mask);
|
| - EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP,
|
| - query_content_protection_response_.protection_mask);
|
| -
|
| - configurator_.QueryContentProtectionStatus(
|
| - client2, outputs_[1]->display_id(),
|
| - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(2, query_content_protection_call_count_);
|
| - EXPECT_TRUE(query_content_protection_response_.success);
|
| - EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI),
|
| - query_content_protection_response_.link_mask);
|
| - EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE,
|
| - query_content_protection_response_.protection_mask);
|
| -
|
| - // Protections will be disabled only if no more clients request them.
|
| - configurator_.EnableContentProtection(
|
| - client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(2, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - configurator_.EnableContentProtection(
|
| - client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(3, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_UNDESIRED).c_str(),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClientsEnable) {
|
| - DisplayConfigurator::ContentProtectionClientId client1 =
|
| - configurator_.RegisterContentProtectionClient();
|
| - DisplayConfigurator::ContentProtectionClientId client2 =
|
| - configurator_.RegisterContentProtectionClient();
|
| - EXPECT_NE(client1, client2);
|
| -
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - UpdateOutputs(2, true);
|
| - log_->GetActionsAndClear();
|
| -
|
| - // Only enable once if HDCP is enabling.
|
| - configurator_.EnableContentProtection(
|
| - client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(1, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - native_display_delegate_->set_hdcp_state(HDCP_STATE_DESIRED);
|
| - configurator_.EnableContentProtection(
|
| - client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(2, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(),
|
| - log_->GetActionsAndClear());
|
| - native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
|
| -
|
| - // Don't enable again if HDCP is already active.
|
| - configurator_.EnableContentProtection(
|
| - client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(3, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - configurator_.EnableContentProtection(
|
| - client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP,
|
| - base::Bind(&DisplayConfiguratorTest::EnableContentProtectionCallback,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(4, enable_content_protection_call_count_);
|
| - EXPECT_TRUE(enable_content_protection_status_);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
|
| - InitWithSingleOutput();
|
| -
|
| - std::vector<std::unique_ptr<const DisplayMode>> modes;
|
| - // The first mode is the mode we are requesting DisplayConfigurator to choose.
|
| - // The test will be setup so that this mode will fail and it will have to
|
| - // choose the next best option.
|
| - modes.push_back(MakeDisplayMode(2560, 1600, false, 60.0));
|
| - modes.push_back(MakeDisplayMode(1024, 768, false, 60.0));
|
| - modes.push_back(MakeDisplayMode(1280, 720, false, 60.0));
|
| - modes.push_back(MakeDisplayMode(1920, 1080, false, 60.0));
|
| - modes.push_back(MakeDisplayMode(1920, 1080, false, 40.0));
|
| -
|
| - outputs_[0] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[0])
|
| - .SetNativeMode(modes[0]->Clone())
|
| - .SetCurrentMode(modes[0]->Clone())
|
| - .AddMode(modes[1]->Clone())
|
| - .AddMode(modes[2]->Clone())
|
| - .AddMode(modes[3]->Clone())
|
| - .AddMode(modes[4]->Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is
|
| - // probably unrealistic but we want to make sure any assumptions don't creep
|
| - // in.
|
| - native_display_delegate_->set_max_configurable_pixels(
|
| - modes[2]->size().GetArea());
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - UpdateOutputs(1, true);
|
| -
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[2].get(), gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - outputs_[1] = display::FakeDisplaySnapshot::Builder()
|
| - .SetId(kDisplayIds[1])
|
| - .SetNativeMode(modes[0]->Clone())
|
| - .SetCurrentMode(modes[0]->Clone())
|
| - .AddMode(modes[1]->Clone())
|
| - .AddMode(modes[2]->Clone())
|
| - .AddMode(modes[3]->Clone())
|
| - .AddMode(modes[4]->Clone())
|
| - .SetType(DISPLAY_CONNECTION_TYPE_HDMI)
|
| - .SetIsAspectPerservingScaling(true)
|
| - .Build();
|
| -
|
| - // This test should attempt to configure a mirror mode that will not succeed
|
| - // and should end up in extended mode.
|
| - native_display_delegate_->set_max_configurable_pixels(
|
| - modes[3]->size().GetArea());
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - UpdateOutputs(2, true);
|
| -
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(modes[0]->size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
|
| - // Then attempt to configure crtc1 with the first mode.
|
| - GetCrtcAction(*outputs_[1], modes[0].get(), gfx::Point(0, 0)).c_str(),
|
| - // First mode tried is expected to fail and it will
|
| - // retry wil the 4th mode in the list.
|
| - GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], modes[3].get(), gfx::Point(0, 0)).c_str(),
|
| - // Since it was requested to go into mirror mode
|
| - // and the configured modes were different, it
|
| - // should now try and setup a valid configurable
|
| - // extended mode.
|
| - GetFramebufferAction(
|
| - gfx::Size(modes[0]->size().width(),
|
| - modes[0]->size().height() + modes[0]->size().height() +
|
| - DisplayConfigurator::kVerticalGap),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], modes[0].get(),
|
| - gfx::Point(0, modes[0]->size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], modes[3].get(),
|
| - gfx::Point(0, modes[0]->size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -// Tests that power state requests are saved after failed configuration attempts
|
| -// so they can be reused later: http://crosbug.com/p/31571
|
| -TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) {
|
| - // Start out with two displays in extended mode.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - log_->GetActionsAndClear();
|
| - observer_.Reset();
|
| -
|
| - // Turn off the internal display, simulating docked mode.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(
|
| - chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| - log_->GetActionsAndClear();
|
| -
|
| - // Make all subsequent configuration requests fail and try to turn the
|
| - // internal display back on.
|
| - config_waiter_.Reset();
|
| - native_display_delegate_->set_max_configurable_pixels(1);
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_FAILURE, config_waiter_.callback_result());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(1, observer_.num_failures());
|
| - log_->GetActionsAndClear();
|
| -
|
| - // Simulate the external display getting disconnected and check that the
|
| - // internal display is turned on (i.e. DISPLAY_POWER_ALL_ON is used) rather
|
| - // than the earlier DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON state.
|
| - native_display_delegate_->set_max_configurable_pixels(0);
|
| - UpdateOutputs(1, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -// Tests that the SetDisplayPowerState() task posted by HandleResume() doesn't
|
| -// use a stale state if a new state is requested before it runs:
|
| -// http://crosbug.com/p/32393
|
| -TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
|
| - // Start out with two displays in mirrored mode.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - log_->GetActionsAndClear();
|
| - observer_.Reset();
|
| -
|
| - // Turn off the internal display, simulating docked mode.
|
| - configurator_.SetDisplayPower(
|
| - chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Suspend and resume the system. Resuming should restore the previous power
|
| - // state and force a probe. Suspend should turn off the displays since an
|
| - // external monitor is connected.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(2, observer_.num_changes());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Before the task runs, exit docked mode.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(3, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Check that the display states are not changed after resuming.
|
| - config_waiter_.Reset();
|
| - // Since we are in dual display mode, a configuration task is scheduled after
|
| - // kMinLongDelayMs delay.
|
| - configurator_.ResumeDisplays();
|
| - EXPECT_EQ(kLongDelay, test_api_.GetConfigureDelay());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| - // Now trigger that delayed configuration.
|
| - EXPECT_EQ(kLongDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
|
| - outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, ExternalControl) {
|
| - InitWithSingleOutput();
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
|
| - configurator_.RelinquishControl(
|
| - base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - kUngrab, kRelinquishDisplayControl, nullptr),
|
| - log_->GetActionsAndClear());
|
| - configurator_.TakeControl(
|
| - base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
|
| - base::Unretained(this)));
|
| - EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kTakeDisplayControl, kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest,
|
| - SetDisplayPowerWhilePendingConfigurationTaskRunning) {
|
| - // Start out with two displays in extended mode.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - log_->GetActionsAndClear();
|
| - observer_.Reset();
|
| -
|
| - native_display_delegate_->set_run_async(true);
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result());
|
| -
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| -
|
| - EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| -
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - EXPECT_EQ(
|
| - base::TimeDelta::FromMilliseconds(DisplayConfigurator::kConfigureDelayMs),
|
| - config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_NOT_CALLED, config_waiter_.callback_result());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(2, observer_.num_changes());
|
| - EXPECT_EQ(0, observer_.num_failures());
|
| -
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest,
|
| - SetDisplayPowerAfterFailedDisplayConfiguration) {
|
| - // Start out with two displays in extended mode.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - log_->GetActionsAndClear();
|
| - observer_.Reset();
|
| -
|
| - // Fail display configuration.
|
| - native_display_delegate_->set_max_configurable_pixels(-1);
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_FAILURE, config_waiter_.callback_result());
|
| - EXPECT_EQ(0, observer_.num_changes());
|
| - EXPECT_EQ(1, observer_.num_failures());
|
| -
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| -
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // This configuration should trigger a display configuration since the
|
| - // previous configuration failed.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| -
|
| - EXPECT_EQ(0, observer_.num_changes());
|
| - EXPECT_EQ(2, observer_.num_failures());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[1], &small_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Allow configuration to succeed.
|
| - native_display_delegate_->set_max_configurable_pixels(0);
|
| -
|
| - // Validate that a configuration event has the proper power state (displays
|
| - // should be on).
|
| - configurator_.OnConfigurationChanged();
|
| - EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
|
| -
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(2, observer_.num_failures());
|
| -
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
|
| - // Start out with two displays in extended mode.
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - Init(false);
|
| - configurator_.ForceInitialConfigure(0);
|
| - log_->GetActionsAndClear();
|
| - observer_.Reset();
|
| -
|
| - UpdateOutputs(3, true);
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED);
|
| -
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - const int kTripleHeight = 2 * small_mode_.size().height() +
|
| - 2 * DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kTripleHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - GetCrtcAction(
|
| - *outputs_[2], &small_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - big_mode_.size().height() +
|
| - 2 * DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Verify that turning the power off works.
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kTripleHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - GetCrtcAction(
|
| - *outputs_[2], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - big_mode_.size().height() +
|
| - 2 * DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - config_waiter_.Reset();
|
| - configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
|
| - DisplayConfigurator::kSetDisplayPowerNoFlags,
|
| - config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab, GetFramebufferAction(
|
| - gfx::Size(big_mode_.size().width(), kTripleHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - GetCrtcAction(
|
| - *outputs_[2], &small_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - big_mode_.size().height() +
|
| - 2 * DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Disconnect the third output.
|
| - observer_.Reset();
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - UpdateOutputs(2, true);
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -}
|
| -
|
| -// Tests the suspend and resume behavior when in dual or multi display modes.
|
| -TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
|
| - InitWithSingleOutput();
|
| - state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
|
| - observer_.Reset();
|
| - UpdateOutputs(2, true);
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
|
| - EXPECT_EQ(1, observer_.num_changes());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
|
| - configurator_.current_power_state());
|
| - const int kDualHeight = small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap +
|
| - big_mode_.size().height();
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Suspending displays should result in an immediate configuration without
|
| - // delays, even in dual display mode.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Resuming from suspend with dual displays. Configuration should be done
|
| - // after a long delay. Afterwards, we should still expect to be in a dual
|
| - // display mode.
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - EXPECT_EQ(kLongDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], &big_mode_,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Suspend displays and disconnect one of them while in suspend.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
|
| - outputs_[0].get(), outputs_[1].get())
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
|
| - GetCrtcAction(*outputs_[1], nullptr,
|
| - gfx::Point(0, small_mode_.size().height() +
|
| - DisplayConfigurator::kVerticalGap))
|
| - .c_str(),
|
| - kUngrab, kSync, nullptr),
|
| - log_->GetActionsAndClear());
|
| - UpdateOutputs(1, false);
|
| - EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
|
| -
|
| - // Now resume, and expect that we'll still have a long delay since we were in
|
| - // dual mode before suspend. The configurator should pick up the change and
|
| - // detect that we are in single display mode now.
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - EXPECT_EQ(kLongDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
|
| - EXPECT_EQ(
|
| - JoinActions(
|
| - kGrab,
|
| - GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
|
| - .c_str(),
|
| - GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
|
| - kForceDPMS, kUngrab, nullptr),
|
| - log_->GetActionsAndClear());
|
| -
|
| - // Verify that the above is the exact same behavior for 3+ displays.
|
| - UpdateOutputs(3, true);
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED,
|
| - configurator_.display_state());
|
| -
|
| - // Suspend.
|
| - config_waiter_.Reset();
|
| - configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
|
| - EXPECT_EQ(kNoDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED,
|
| - configurator_.display_state());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF,
|
| - configurator_.current_power_state());
|
| -
|
| - // Resume and expect the correct delay.
|
| - config_waiter_.Reset();
|
| - configurator_.ResumeDisplays();
|
| - EXPECT_EQ(kLongDelay, config_waiter_.Wait());
|
| - EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
|
| - configurator_.current_power_state());
|
| - EXPECT_EQ(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED,
|
| - configurator_.display_state());
|
| -}
|
| -
|
| -} // namespace test
|
| -} // namespace ui
|
|
|