2
* Copyright © 2015 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
19
#include "src/platforms/android/server/display.h"
20
#include "src/platforms/android/server/hal_component_factory.h"
21
#include "src/server/graphics/program_factory.h"
22
#include "src/server/report/null_report_factory.h"
23
#include "mir/glib_main_loop.h"
24
#include "mir/time/steady_clock.h"
25
#include "mir_test_doubles/mock_display_device.h"
26
#include "mir_test_doubles/mock_framebuffer_bundle.h"
27
#include "mir_test_doubles/stub_gl_config.h"
28
#include "mir_test_doubles/mock_egl.h"
29
#include "mir_test_doubles/mock_gl.h"
30
#include "mir_test/auto_unblock_thread.h"
31
#include <gtest/gtest.h>
33
namespace mga=mir::graphics::android;
34
namespace mg=mir::graphics;
35
namespace geom=mir::geometry;
36
namespace mtd=mir::test::doubles;
38
//doesn't use the HW modules, rather tests mainloop integration
39
struct DisplayHotplug : ::testing::Test
41
struct StubHwcConfig : public mga::HwcConfiguration
43
void power_mode(mga::DisplayName, MirPowerMode) override {}
44
mga::DisplayAttribs active_attribs_for(mga::DisplayName) override
46
return mga::DisplayAttribs{{0,0}, {0,0}, 0.0, true, mir_pixel_format_abgr_8888, 2};
48
mga::ConfigChangeSubscription subscribe_to_config_changes(
49
std::function<void()> const& cb) override
54
void simulate_hotplug()
58
std::function<void()> hotplug_fn{[]{}};
61
struct WrappingConfig : public mga::HwcConfiguration
63
WrappingConfig(mga::HwcConfiguration& config) : wrapped(config) {}
65
void power_mode(mga::DisplayName d, MirPowerMode m) override
67
wrapped.power_mode(d, m);
69
mga::DisplayAttribs active_attribs_for(mga::DisplayName d) override
71
return wrapped.active_attribs_for(d);
73
mga::ConfigChangeSubscription subscribe_to_config_changes(
74
std::function<void()> const& cb) override
76
return wrapped.subscribe_to_config_changes(cb);
78
mga::HwcConfiguration& wrapped;
81
struct StubOutputBuilder : public mga::DisplayComponentFactory
83
std::unique_ptr<mga::FramebufferBundle> create_framebuffers(mga::DisplayAttribs const&) override
85
return std::unique_ptr<mga::FramebufferBundle>(new testing::NiceMock<mtd::MockFBBundle>());
88
std::unique_ptr<mga::DisplayDevice> create_display_device() override
90
return std::unique_ptr<mga::DisplayDevice>(new testing::NiceMock<mtd::MockDisplayDevice>());
93
std::unique_ptr<mga::HwcConfiguration> create_hwc_configuration() override
95
return std::unique_ptr<mga::HwcConfiguration>(new WrappingConfig(stub_config));
97
StubHwcConfig stub_config;
100
testing::NiceMock<mtd::MockEGL> mock_egl;
101
testing::NiceMock<mtd::MockGL> mock_gl;
102
mir::GLibMainLoop mainloop{std::make_shared<mir::time::SteadyClock>()};
103
mir::test::AutoUnblockThread loop{
104
[this]{ mainloop.enqueue(this, [this] { mainloop.stop(); }); },
105
[this]{ mainloop.run(); }};
106
std::shared_ptr<StubOutputBuilder> stub_output_builder{std::make_shared<StubOutputBuilder>()};
107
mga::Display display{
109
std::make_shared<mg::ProgramFactory>(),
110
std::make_shared<mtd::StubGLConfig>(),
111
mir::report::null_display_report(),
112
mga::OverlayOptimization::enabled};
115
TEST_F(DisplayHotplug, hotplug_generates_mainloop_event)
118
std::condition_variable cv;
120
std::function<void()> change_handler{[&]
122
std::unique_lock<decltype(mutex)> lk(mutex);
126
std::unique_lock<decltype(mutex)> lk(mutex);
127
display.register_configuration_change_handler(mainloop, change_handler);
128
stub_output_builder->stub_config.simulate_hotplug();
129
EXPECT_TRUE(cv.wait_for(lk, std::chrono::seconds(2), [&]{ return call_count == 1; }));
131
stub_output_builder->stub_config.simulate_hotplug();
132
EXPECT_TRUE(cv.wait_for(lk, std::chrono::seconds(2), [&]{ return call_count == 2; }));
133
mainloop.unregister_fd_handler(&display);