Mir

Merge lp:~kdub/mir/deactive-notifications-when-display-off into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: kevin gunn
Approved revision: no longer in the source branch.
Merged at revision: 1102
Proposed branch: lp:~kdub/mir/deactive-notifications-when-display-off
Merge into: lp:mir
Diff against target: 381 lines (+124/-59)
12 files modified
include/test/mir_test_doubles/mock_display_support_provider.h (+1/-1)
include/test/mir_test_doubles/mock_hwc_interface.h (+1/-1)
include/test/mir_test_doubles/stub_display_support_provider.h (+1/-1)
src/server/graphics/android/android_display.cpp (+2/-5)
src/server/graphics/android/display_support_provider.h (+3/-2)
src/server/graphics/android/fb_device.cpp (+2/-2)
src/server/graphics/android/fb_device.h (+1/-1)
src/server/graphics/android/hwc_common_device.cpp (+54/-32)
src/server/graphics/android/hwc_common_device.h (+5/-2)
src/server/graphics/android/hwc_device.h (+1/-1)
tests/unit-tests/graphics/android/test_hwc_device.cpp (+45/-3)
tests/unit-tests/graphics/android/test_hwc_display.cpp (+8/-8)
To merge this branch: bzr merge lp:~kdub/mir/deactive-notifications-when-display-off
Reviewer Review Type Date Requested Status
Ricardo Mendoza (community) Approve
Alan Griffiths Approve
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+188751@code.launchpad.net

Commit message

graphics: android: disable vsync notifications when screen is off as per hwc specs. rename unblank_or_blank_display to apply_display_state() to remove ambiguity about what is being done.

fixes: lp1233870

Description of the change

graphics: android: disable vsync notifications when screen is off as per hwc specs. rename unblank_or_blank_display to apply_display_state() to remove ambiguity about what is being done.

fixes: lp1233870

as seen here:
http://androidxref.com/4.2.2_r1/xref/hardware/libhardware/include/hardware/hwcomposer.h#337
the vsync notifications should be off when the screen is off. This was causing the nexus4 vsync notification thread in the driver to spin.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

In terms of binary logic, I'd prefer to see these values reversed:

63 +enum class DisplayState
64 +{
65 + DisplayOn = 0,
66 + DisplayOff = 1,
67 +};

But then you have to ask... why am I not just using a boolean with a more obvious name?

Alternatively, use the existing MirPowerMode enum?

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

48 + display_provider->apply_display_state(mga::DisplayState::DisplayOn);

I approve the desire to have meaningful parameter values, but repeating "display state" and vague words like "apply" don't make for easy reading.

display_provider->state(mga::DisplayState::DisplayOn);

Or:

display_provider->mode(mir_power_mode_on);

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

@daniel, alan
should be fixed, it is much better to use the existing enum. thanks!

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

202 + if(err)

Whitespace nit

review: Approve
Revision history for this message
Ricardo Mendoza (ricmm) wrote :

Fixes the power issue for me on N4.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/test/mir_test_doubles/mock_display_support_provider.h'
2--- include/test/mir_test_doubles/mock_display_support_provider.h 2013-09-16 19:16:30 +0000
3+++ include/test/mir_test_doubles/mock_display_support_provider.h 2013-10-02 17:00:39 +0000
4@@ -37,7 +37,7 @@
5 MOCK_CONST_METHOD0(number_of_framebuffers_available, unsigned int());
6 MOCK_METHOD1(set_next_frontbuffer, void(std::shared_ptr<mir::graphics::Buffer> const&));
7 MOCK_METHOD1(sync_to_display, void(bool));
8- MOCK_METHOD1(blank_or_unblank_screen, void(bool));
9+ MOCK_METHOD1(mode, void(MirPowerMode));
10 };
11 }
12 }
13
14=== modified file 'include/test/mir_test_doubles/mock_hwc_interface.h'
15--- include/test/mir_test_doubles/mock_hwc_interface.h 2013-09-11 19:50:31 +0000
16+++ include/test/mir_test_doubles/mock_hwc_interface.h 2013-10-02 17:00:39 +0000
17@@ -41,7 +41,7 @@
18 MOCK_CONST_METHOD0(number_of_framebuffers_available, unsigned int());
19 MOCK_METHOD1(set_next_frontbuffer, void(std::shared_ptr<mir::graphics::Buffer> const&));
20 MOCK_METHOD1(sync_to_display, void(bool));
21- MOCK_METHOD1(blank_or_unblank_screen, void(bool));
22+ MOCK_METHOD1(mode, void(MirPowerMode));
23 };
24
25 }
26
27=== modified file 'include/test/mir_test_doubles/stub_display_support_provider.h'
28--- include/test/mir_test_doubles/stub_display_support_provider.h 2013-09-16 21:00:32 +0000
29+++ include/test/mir_test_doubles/stub_display_support_provider.h 2013-10-02 17:00:39 +0000
30@@ -36,7 +36,7 @@
31 unsigned int number_of_framebuffers_available() const { return 0; }
32 void set_next_frontbuffer(std::shared_ptr<mir::graphics::Buffer> const&) {}
33 void sync_to_display(bool) {}
34- void blank_or_unblank_screen(bool) {}
35+ void mode(MirPowerMode) {}
36 };
37
38 }
39
40=== modified file 'src/server/graphics/android/android_display.cpp'
41--- src/server/graphics/android/android_display.cpp 2013-09-17 19:46:15 +0000
42+++ src/server/graphics/android/android_display.cpp 2013-10-02 17:00:39 +0000
43@@ -156,13 +156,10 @@
44
45 void mga::AndroidDisplay::configure(mg::DisplayConfiguration const& configuration)
46 {
47- configuration.for_each_output([&](mg::DisplayConfigurationOutput const& output) -> void
48+ configuration.for_each_output([&](mg::DisplayConfigurationOutput const& output)
49 {
50 // TODO: Properly support multiple outputs
51- if (output.power_mode == mir_power_mode_on)
52- display_provider->blank_or_unblank_screen(false);
53- else
54- display_provider->blank_or_unblank_screen(true);
55+ display_provider->mode(output.power_mode);
56 });
57 current_configuration = dynamic_cast<mga::AndroidDisplayConfiguration const&>(configuration);
58 }
59
60=== modified file 'src/server/graphics/android/display_support_provider.h'
61--- src/server/graphics/android/display_support_provider.h 2013-09-16 19:16:30 +0000
62+++ src/server/graphics/android/display_support_provider.h 2013-10-02 17:00:39 +0000
63@@ -19,6 +19,7 @@
64 #ifndef MIR_GRAPHICS_ANDROID_DISPLAY_SUPPORT_PROVIDER_H_
65 #define MIR_GRAPHICS_ANDROID_DISPLAY_SUPPORT_PROVIDER_H_
66
67+#include "mir_toolkit/common.h"
68 #include "mir/geometry/size.h"
69 #include "mir/geometry/pixel_format.h"
70 #include <memory>
71@@ -44,8 +45,8 @@
72 //post immediately, or be deferred.
73 virtual void set_next_frontbuffer(std::shared_ptr<graphics::Buffer> const& buffer) = 0;
74 virtual void sync_to_display(bool sync) = 0;
75-
76- virtual void blank_or_unblank_screen(bool blank) = 0;
77+ virtual void mode(MirPowerMode mode) = 0;
78+
79 protected:
80 DisplaySupportProvider() = default;
81 DisplaySupportProvider& operator=(DisplaySupportProvider const&) = delete;
82
83=== modified file 'src/server/graphics/android/fb_device.cpp'
84--- src/server/graphics/android/fb_device.cpp 2013-09-16 19:16:30 +0000
85+++ src/server/graphics/android/fb_device.cpp 2013-10-02 17:00:39 +0000
86@@ -79,8 +79,8 @@
87 }
88 }
89
90-void mga::FBDevice::blank_or_unblank_screen(bool blank)
91+void mga::FBDevice::mode(MirPowerMode mode)
92 {
93 // TODO: Implement
94- (void) blank;
95+ (void) mode;
96 }
97
98=== modified file 'src/server/graphics/android/fb_device.h'
99--- src/server/graphics/android/fb_device.h 2013-09-16 19:16:30 +0000
100+++ src/server/graphics/android/fb_device.h 2013-10-02 17:00:39 +0000
101@@ -42,7 +42,7 @@
102 void set_next_frontbuffer(std::shared_ptr<graphics::Buffer> const& buffer);
103 void sync_to_display(bool sync);
104
105- void blank_or_unblank_screen(bool blank);
106+ virtual void mode(MirPowerMode mode);
107 private:
108 std::shared_ptr<framebuffer_device_t> const fb_device;
109 };
110
111=== modified file 'src/server/graphics/android/hwc_common_device.cpp'
112--- src/server/graphics/android/hwc_common_device.cpp 2013-09-26 18:17:11 +0000
113+++ src/server/graphics/android/hwc_common_device.cpp 2013-10-02 17:00:39 +0000
114@@ -47,7 +47,7 @@
115 std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)
116 : hwc_device(hwc_device),
117 coordinator(coordinator),
118- blanked(false)
119+ current_mode(mir_power_mode_on)
120 {
121 callbacks.hooks.invalidate = invalidate_hook;
122 callbacks.hooks.vsync = vsync_hook;
123@@ -56,30 +56,20 @@
124
125 hwc_device->registerProcs(hwc_device.get(), &callbacks.hooks);
126
127- int err = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 0);
128- if (err)
129+ if (auto err = turn_screen_on())
130 {
131 BOOST_THROW_EXCEPTION(
132 boost::enable_error_info(
133 std::runtime_error("Could not unblank display")) <<
134 boost::errinfo_errno(-err));
135 }
136-
137- err = hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 1);
138- if (err)
139- {
140- BOOST_THROW_EXCEPTION(
141- boost::enable_error_info(
142- std::runtime_error("Could not enable HWC vsync "
143- "notifications")) <<
144- boost::errinfo_errno(-err));
145- }
146 }
147
148 mga::HWCCommonDevice::~HWCCommonDevice() noexcept
149 {
150- hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 0);
151- hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 1);
152+ std::unique_lock<std::mutex> lg(blanked_mutex);
153+ if (current_mode == mir_power_mode_on)
154+ turn_screen_off();
155 }
156
157 geom::PixelFormat mga::HWCCommonDevice::display_format() const
158@@ -97,30 +87,62 @@
159 coordinator->notify_vsync();
160 }
161
162-void mga::HWCCommonDevice::blank_or_unblank_screen(bool blank_request)
163+void mga::HWCCommonDevice::mode(MirPowerMode mode_request)
164 {
165 std::unique_lock<std::mutex> lg(blanked_mutex);
166-
167- if (blank_request != blanked)
168- {
169- if(auto err = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, blank_request))
170- {
171- std::string blanking_status_msg = "Could not " +
172- (blank_request ? std::string("blank") : std::string("unblank")) + " display";
173- BOOST_THROW_EXCEPTION(
174- boost::enable_error_info(
175- std::runtime_error(blanking_status_msg)) <<
176- boost::errinfo_errno(-err));
177- }
178- blanked = blank_request;
179- blanked_cond.notify_all();
180- }
181+ int err = 0;
182+
183+ //note: mir_power_mode_standby, mir_power_mode_suspend, mir_power_mode_off
184+ // are all treated like mir_power_mode_off
185+ if ((mode_request == mir_power_mode_suspend) ||
186+ (mode_request == mir_power_mode_standby))
187+ {
188+ mode_request = mir_power_mode_off;
189+ }
190+
191+ if ((mode_request == mir_power_mode_on) &&
192+ (current_mode == mir_power_mode_off))
193+ {
194+ err = turn_screen_on();
195+ }
196+ else if ((mode_request == mir_power_mode_off) &&
197+ (current_mode == mir_power_mode_on))
198+ {
199+ err = turn_screen_off();
200+ }
201+
202+ if (err)
203+ {
204+ std::string blanking_status_msg = "Could not " +
205+ ((mode_request == mir_power_mode_off) ? std::string("blank") : std::string("unblank")) + " display";
206+ BOOST_THROW_EXCEPTION(
207+ boost::enable_error_info(
208+ std::runtime_error(blanking_status_msg)) <<
209+ boost::errinfo_errno(-err));
210+ }
211+
212+ current_mode = mode_request;
213+ blanked_cond.notify_all();
214 }
215
216 std::unique_lock<std::mutex> mga::HWCCommonDevice::lock_unblanked()
217 {
218 std::unique_lock<std::mutex> lg(blanked_mutex);
219- while(blanked)
220+ while(current_mode == mir_power_mode_off)
221 blanked_cond.wait(lg);
222 return std::move(lg);
223 }
224+
225+int mga::HWCCommonDevice::turn_screen_on() const noexcept(true)
226+{
227+ if (auto err = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 0))
228+ return err;
229+ return hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 1);
230+}
231+
232+int mga::HWCCommonDevice::turn_screen_off() const noexcept(true)
233+{
234+ if (auto err = hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 0))
235+ return err;
236+ return hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 1);
237+}
238
239=== modified file 'src/server/graphics/android/hwc_common_device.h'
240--- src/server/graphics/android/hwc_common_device.h 2013-09-18 16:08:14 +0000
241+++ src/server/graphics/android/hwc_common_device.h 2013-10-02 17:00:39 +0000
242@@ -53,7 +53,7 @@
243 virtual void set_next_frontbuffer(std::shared_ptr<Buffer> const& buffer) = 0;
244 virtual void commit_frame(EGLDisplay dpy, EGLSurface sur) = 0;
245
246- void blank_or_unblank_screen(bool blank);
247+ virtual void mode(MirPowerMode mode);
248
249 void notify_vsync();
250 protected:
251@@ -66,11 +66,14 @@
252 std::unique_lock<std::mutex> lock_unblanked();
253
254 private:
255+ int turn_screen_on() const noexcept(true);
256+ int turn_screen_off() const noexcept(true);
257+
258 HWCCallbacks callbacks;
259
260 std::mutex blanked_mutex;
261 std::condition_variable blanked_cond;
262- bool blanked;
263+ MirPowerMode current_mode;
264 };
265
266 }
267
268=== modified file 'src/server/graphics/android/hwc_device.h'
269--- src/server/graphics/android/hwc_device.h 2013-09-05 17:46:22 +0000
270+++ src/server/graphics/android/hwc_device.h 2013-10-02 17:00:39 +0000
271@@ -43,7 +43,7 @@
272
273 virtual void commit_frame(EGLDisplay dpy, EGLSurface sur) = 0;
274
275- virtual void blank_or_unblank_screen(bool blank) = 0;
276+ virtual void mode(MirPowerMode mode) = 0;
277 private:
278 HWCDevice(HWCDevice const&) = delete;
279 HWCDevice& operator=(HWCDevice const&) = delete;
280
281=== modified file 'tests/unit-tests/graphics/android/test_hwc_device.cpp'
282--- tests/unit-tests/graphics/android/test_hwc_device.cpp 2013-09-26 18:17:11 +0000
283+++ tests/unit-tests/graphics/android/test_hwc_device.cpp 2013-10-02 17:00:39 +0000
284@@ -176,7 +176,7 @@
285 }, std::runtime_error);
286 }
287
288-TYPED_TEST(HWCCommon, test_hwc_throws_on_blank_or_unblank_error)
289+TYPED_TEST(HWCCommon, test_hwc_throws_on_blanking_error)
290 {
291 using namespace testing;
292
293@@ -194,10 +194,52 @@
294 auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_layer_list,
295 this->mock_fbdev, this->mock_vsync);
296 EXPECT_THROW({
297- device->blank_or_unblank_screen(true);
298+ device->mode(mir_power_mode_off);
299 }, std::runtime_error);
300 }
301
302+TYPED_TEST(HWCCommon, test_hwc_suspend_standby_turn_off)
303+{
304+ using namespace testing;
305+
306+ EXPECT_CALL(*this->mock_device, blank_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, 0))
307+ .Times(3)
308+ .WillOnce(Return(0));
309+ EXPECT_CALL(*this->mock_device, blank_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, 1))
310+ .Times(3)
311+ .WillOnce(Return(0));
312+
313+ auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_layer_list,
314+ this->mock_fbdev, this->mock_vsync);
315+ device->mode(mir_power_mode_off);
316+ device->mode(mir_power_mode_on);
317+ device->mode(mir_power_mode_suspend);
318+ device->mode(mir_power_mode_on);
319+ device->mode(mir_power_mode_standby);
320+}
321+
322+TYPED_TEST(HWCCommon, test_hwc_deactivates_vsync_on_blank)
323+{
324+ using namespace testing;
325+
326+ InSequence seq;
327+ EXPECT_CALL(*this->mock_device, blank_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, 0))
328+ .Times(1)
329+ .WillOnce(Return(0));
330+ EXPECT_CALL(*this->mock_device, eventControl_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 1))
331+ .Times(1);
332+
333+ EXPECT_CALL(*this->mock_device, eventControl_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0))
334+ .Times(1);
335+ EXPECT_CALL(*this->mock_device, blank_interface(this->mock_device.get(), HWC_DISPLAY_PRIMARY, 1))
336+ .Times(1)
337+ .WillOnce(Return(0));
338+
339+ auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_layer_list,
340+ this->mock_fbdev, this->mock_vsync);
341+ device->mode(mir_power_mode_off);
342+}
343+
344 TYPED_TEST(HWCCommon, test_blank_is_ignored_if_already_in_correct_state)
345 {
346 using namespace testing;
347@@ -216,7 +258,7 @@
348
349 auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_layer_list,
350 this->mock_fbdev, this->mock_vsync);
351- device->blank_or_unblank_screen(false);
352+ device->mode(mir_power_mode_on);
353 }
354
355 TYPED_TEST(HWCCommon, test_hwc_display_is_deactivated_on_destroy)
356
357=== modified file 'tests/unit-tests/graphics/android/test_hwc_display.cpp'
358--- tests/unit-tests/graphics/android/test_hwc_display.cpp 2013-09-16 19:16:30 +0000
359+++ tests/unit-tests/graphics/android/test_hwc_display.cpp 2013-10-02 17:00:39 +0000
360@@ -142,13 +142,13 @@
361
362 {
363 InSequence seq;
364- EXPECT_CALL(*mock_hwc_device, blank_or_unblank_screen(false));
365- EXPECT_CALL(*mock_hwc_device, blank_or_unblank_screen(true));
366- EXPECT_CALL(*mock_hwc_device, blank_or_unblank_screen(true));
367- EXPECT_CALL(*mock_hwc_device, blank_or_unblank_screen(true));
368+ EXPECT_CALL(*mock_hwc_device, mode(mir_power_mode_on));
369+ EXPECT_CALL(*mock_hwc_device, mode(mir_power_mode_off));
370+ EXPECT_CALL(*mock_hwc_device, mode(mir_power_mode_suspend));
371+ EXPECT_CALL(*mock_hwc_device, mode(mir_power_mode_standby));
372 }
373- display->configure(*on_configuration.get());
374- display->configure(*off_configuration.get());
375- display->configure(*suspend_configuration.get());
376- display->configure(*standby_configuration.get());
377+ display->configure(*on_configuration);
378+ display->configure(*off_configuration);
379+ display->configure(*suspend_configuration);
380+ display->configure(*standby_configuration);
381 }

Subscribers

People subscribed via source and target branches