| // Copyright 2015 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 "ash/display/display_color_manager_chromeos.h" |
| |
| #include "base/files/file_util.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/strings/pattern.h" |
| #include "base/test/scoped_path_override.h" |
| #include "base/test/sequenced_worker_pool_owner.h" |
| #include "chromeos/chromeos_paths.h" |
| #include "components/quirks/quirks_manager.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/display/chromeos/test/action_logger_util.h" |
| #include "ui/display/chromeos/test/test_display_snapshot.h" |
| #include "ui/display/chromeos/test/test_native_display_delegate.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| const char kResetGammaAction[] = "*set_color_correction(id=123)"; |
| const char kSetGammaAction[] = |
| "set_color_correction(id=123,gamma[0]*gamma[255]=???????????\?)"; |
| const char kSetFullCTMAction[] = |
| "set_color_correction(id=123,degamma[0]*gamma[0]*ctm[0]*ctm[8]*)"; |
| |
| class DisplayColorManagerForTest : public DisplayColorManager { |
| public: |
| DisplayColorManagerForTest(ui::DisplayConfigurator* configurator, |
| base::SequencedWorkerPool* blocking_pool) |
| : DisplayColorManager(configurator, blocking_pool) {} |
| |
| void SetOnFinishedForTest(base::Closure on_finished_for_test) { |
| on_finished_for_test_ = on_finished_for_test; |
| } |
| |
| private: |
| void FinishLoadCalibrationForDisplay(int64_t display_id, |
| int64_t product_id, |
| bool has_color_correction_matrix, |
| ui::DisplayConnectionType type, |
| const base::FilePath& path, |
| bool file_downloaded) override { |
| DisplayColorManager::FinishLoadCalibrationForDisplay( |
| display_id, product_id, has_color_correction_matrix, type, path, |
| file_downloaded); |
| // If path is empty, there is no icc file, and the DCM's work is done. |
| if (path.empty() && !on_finished_for_test_.is_null()) { |
| on_finished_for_test_.Run(); |
| on_finished_for_test_.Reset(); |
| } |
| } |
| |
| void UpdateCalibrationData( |
| int64_t display_id, |
| int64_t product_id, |
| std::unique_ptr<ColorCalibrationData> data) override { |
| DisplayColorManager::UpdateCalibrationData(display_id, product_id, |
| std::move(data)); |
| if (!on_finished_for_test_.is_null()) { |
| on_finished_for_test_.Run(); |
| on_finished_for_test_.Reset(); |
| } |
| } |
| |
| base::Closure on_finished_for_test_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DisplayColorManagerForTest); |
| }; |
| |
| // Implementation of QuirksManager::Delegate to fake chrome-restricted parts. |
| class QuirksManagerDelegateTestImpl : public quirks::QuirksManager::Delegate { |
| public: |
| QuirksManagerDelegateTestImpl(base::FilePath color_path) |
| : color_path_(color_path) {} |
| |
| // Unused by these tests. |
| std::string GetApiKey() const override { return std::string(); } |
| |
| base::FilePath GetBuiltInDisplayProfileDirectory() const override { |
| return color_path_; |
| } |
| |
| // Unused by these tests. |
| base::FilePath GetDownloadDisplayProfileDirectory() const override { |
| return base::FilePath(); |
| } |
| |
| // |false| prevents attempts at Quirks Server contact. |
| bool DevicePolicyEnabled() const override { return false; } |
| |
| // Unused by these tests. |
| void GetDaysSinceOobe( |
| quirks::QuirksManager::DaysSinceOobeCallback callback) const override {} |
| |
| private: |
| ~QuirksManagerDelegateTestImpl() override = default; |
| |
| base::FilePath color_path_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuirksManagerDelegateTestImpl); |
| }; |
| |
| } // namespace |
| |
| class DisplayColorManagerTest : public testing::Test { |
| public: |
| void SetUp() override { |
| pool_owner_.reset( |
| new base::SequencedWorkerPoolOwner(3, "DisplayColorManagerTest")); |
| log_.reset(new ui::test::ActionLogger()); |
| |
| native_display_delegate_ = |
| new ui::test::TestNativeDisplayDelegate(log_.get()); |
| configurator_.SetDelegateForTesting( |
| std::unique_ptr<ui::NativeDisplayDelegate>(native_display_delegate_)); |
| |
| color_manager_.reset(new DisplayColorManagerForTest( |
| &configurator_, pool_owner_->pool().get())); |
| |
| EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &color_path_)); |
| |
| color_path_ = color_path_.Append(FILE_PATH_LITERAL("ash")) |
| .Append(FILE_PATH_LITERAL("display")) |
| .Append(FILE_PATH_LITERAL("test_data")); |
| path_override_.reset(new base::ScopedPathOverride( |
| chromeos::DIR_DEVICE_COLOR_CALIBRATION_PROFILES, color_path_)); |
| |
| quirks::QuirksManager::Initialize( |
| std::unique_ptr<quirks::QuirksManager::Delegate>( |
| new QuirksManagerDelegateTestImpl(color_path_)), |
| pool_owner_->pool().get(), nullptr, nullptr); |
| } |
| |
| void TearDown() override { |
| quirks::QuirksManager::Shutdown(); |
| pool_owner_->pool()->Shutdown(); |
| } |
| |
| void WaitOnColorCalibration() { |
| base::RunLoop run_loop; |
| color_manager_->SetOnFinishedForTest(run_loop.QuitClosure()); |
| run_loop.Run(); |
| } |
| |
| DisplayColorManagerTest() : test_api_(&configurator_) {} |
| ~DisplayColorManagerTest() override {} |
| |
| protected: |
| std::unique_ptr<base::ScopedPathOverride> path_override_; |
| base::FilePath color_path_; |
| std::unique_ptr<ui::test::ActionLogger> log_; |
| ui::DisplayConfigurator configurator_; |
| ui::DisplayConfigurator::TestApi test_api_; |
| ui::test::TestNativeDisplayDelegate* native_display_delegate_; // not owned |
| std::unique_ptr<DisplayColorManagerForTest> color_manager_; |
| |
| base::MessageLoopForUI ui_message_loop_; |
| std::unique_ptr<base::SequencedWorkerPoolOwner> pool_owner_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(DisplayColorManagerTest); |
| }; |
| |
| TEST_F(DisplayColorManagerTest, VCGTOnly) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0x06af5c10, /* product_id */ |
| false, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_TRUE(base::MatchPattern(log_->GetActionsAndClear(), kSetGammaAction)); |
| } |
| |
| TEST_F(DisplayColorManagerTest, VCGTOnlyWithPlatformCTM) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0x06af5c10, /* product_id */ |
| true, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| log_->GetActionsAndClear(); |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_TRUE(base::MatchPattern(log_->GetActionsAndClear(), kSetGammaAction)); |
| } |
| |
| TEST_F(DisplayColorManagerTest, FullWithPlatformCTM) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0x4c834a42, /* product_id */ |
| true, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kSetFullCTMAction)); |
| } |
| |
| TEST_F(DisplayColorManagerTest, FullWithoutPlatformCTM) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0x4c834a42, /* product_id */ |
| false, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_STREQ("", log_->GetActionsAndClear().c_str()); |
| } |
| |
| TEST_F(DisplayColorManagerTest, NoMatchProductID) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0, /* product_id */ |
| false, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_STREQ("", log_->GetActionsAndClear().c_str()); |
| } |
| |
| TEST_F(DisplayColorManagerTest, NoVCGT) { |
| std::vector<std::unique_ptr<const ui::DisplayMode>> modes; |
| ui::DisplayMode mode(gfx::Size(1024, 768), false, 60.0f); |
| modes.push_back(mode.Clone()); |
| const ui::DisplayMode* mode_ptr = modes.back().get(); |
| ui::TestDisplaySnapshot snapshot( |
| 123, gfx::Point(0, 0), /* origin */ |
| gfx::Size(0, 0), /* physical_size */ |
| ui::DISPLAY_CONNECTION_TYPE_INTERNAL, /* type */ |
| false, /* is_aspect_preserving_scaling */ |
| 0x0dae3211, /* product_id */ |
| false, /* has_color_correction_matrix */ |
| std::move(modes), /* modes */ |
| mode_ptr /* current_mode */, mode_ptr /* native_mode */); |
| std::vector<ui::DisplaySnapshot*> outputs; |
| outputs.push_back(&snapshot); |
| native_display_delegate_->set_outputs(outputs); |
| |
| configurator_.OnConfigurationChanged(); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_TRUE( |
| base::MatchPattern(log_->GetActionsAndClear(), kResetGammaAction)); |
| |
| WaitOnColorCalibration(); |
| EXPECT_STREQ("", log_->GetActionsAndClear().c_str()); |
| } |
| |
| } // namespace ash |