Merge lp:~afrantzis/unity-system-compositor/proximity into lp:unity-system-compositor
- proximity
- Merge into trunk
Proposed by
Alexandros Frantzis
Status: | Merged |
---|---|
Approved by: | Alexandros Frantzis |
Approved revision: | 231 |
Merged at revision: | 237 |
Proposed branch: | lp:~afrantzis/unity-system-compositor/proximity |
Merge into: | lp:unity-system-compositor |
Prerequisite: | lp:~afrantzis/unity-system-compositor/notification-timeouts |
Diff against target: |
724 lines (+413/-35) 7 files modified
src/mir_screen.cpp (+71/-23) src/mir_screen.h (+4/-1) src/powerd_mediator.cpp (+26/-0) src/powerd_mediator.h (+5/-0) src/screen_hardware.h (+2/-0) tests/integration-tests/test_powerd_mediator.cpp (+81/-0) tests/unit-tests/test_mir_screen.cpp (+224/-11) |
To merge this branch: | bzr merge lp:~afrantzis/unity-system-compositor/proximity |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Kevin DuBois (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+265120@code.launchpad.net |
Commit message
Enable and handle proximity events properly
Description of the change
Enable and handle proximity events properly
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
Kevin DuBois (kdub) wrote : | # |
240 +void usc::PowerdMedi
I think this would be a bit more understandable if a force_proximity_l() function was split out, but other than that lgtm
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/mir_screen.cpp' | |||
2 | --- src/mir_screen.cpp 2015-07-17 12:45:10 +0000 | |||
3 | +++ src/mir_screen.cpp 2015-07-17 12:45:10 +0000 | |||
4 | @@ -55,7 +55,8 @@ | |||
5 | 55 | notification_timeouts(notification_timeouts), | 55 | notification_timeouts(notification_timeouts), |
6 | 56 | current_power_mode{MirPowerMode::mir_power_mode_on}, | 56 | current_power_mode{MirPowerMode::mir_power_mode_on}, |
7 | 57 | restart_timers{true}, | 57 | restart_timers{true}, |
9 | 58 | power_state_change_handler{[](MirPowerMode,PowerStateChangeReason){}} | 58 | power_state_change_handler{[](MirPowerMode,PowerStateChangeReason){}}, |
10 | 59 | allow_proximity_to_turn_on_screen{false} | ||
11 | 59 | { | 60 | { |
12 | 60 | /* | 61 | /* |
13 | 61 | * Make sure the compositor is running as certain conditions can | 62 | * Make sure the compositor is running as certain conditions can |
14 | @@ -73,7 +74,10 @@ | |||
15 | 73 | std::lock_guard<std::mutex> lock{guard}; | 74 | std::lock_guard<std::mutex> lock{guard}; |
16 | 74 | reset_timers_l(PowerStateChangeReason::inactivity); | 75 | reset_timers_l(PowerStateChangeReason::inactivity); |
17 | 75 | if (current_power_mode == MirPowerMode::mir_power_mode_on) | 76 | if (current_power_mode == MirPowerMode::mir_power_mode_on) |
18 | 77 | { | ||
19 | 76 | screen_hardware->set_normal_backlight(); | 78 | screen_hardware->set_normal_backlight(); |
20 | 79 | screen_hardware->enable_proximity(false); | ||
21 | 80 | } | ||
22 | 77 | } | 81 | } |
23 | 78 | 82 | ||
24 | 79 | void usc::MirScreen::enable_inactivity_timers(bool enable) | 83 | void usc::MirScreen::enable_inactivity_timers(bool enable) |
25 | @@ -129,12 +133,25 @@ | |||
26 | 129 | if (raw_dimmer_timeout >= 0) | 133 | if (raw_dimmer_timeout >= 0) |
27 | 130 | inactivity_timeouts.dimming_timeout = std::chrono::duration_cast<std::chrono::milliseconds>(the_dimming_timeout); | 134 | inactivity_timeouts.dimming_timeout = std::chrono::duration_cast<std::chrono::milliseconds>(the_dimming_timeout); |
28 | 131 | 135 | ||
30 | 132 | cancel_timers_l(); | 136 | cancel_timers_l(PowerStateChangeReason::inactivity); |
31 | 133 | reset_timers_l(PowerStateChangeReason::inactivity); | 137 | reset_timers_l(PowerStateChangeReason::inactivity); |
32 | 134 | } | 138 | } |
33 | 135 | 139 | ||
34 | 136 | void usc::MirScreen::set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason) | 140 | void usc::MirScreen::set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason) |
35 | 137 | { | 141 | { |
36 | 142 | if (!is_screen_change_allowed(mode, reason)) | ||
37 | 143 | return; | ||
38 | 144 | |||
39 | 145 | // Notifications don't turn on the screen directly, they rely on proximity events | ||
40 | 146 | if (mode == MirPowerMode::mir_power_mode_on && | ||
41 | 147 | reason == PowerStateChangeReason::notification) | ||
42 | 148 | { | ||
43 | 149 | allow_proximity_to_turn_on_screen = true; | ||
44 | 150 | screen_hardware->enable_proximity(true); | ||
45 | 151 | reset_timers_ignoring_power_mode_l(reason); | ||
46 | 152 | return; | ||
47 | 153 | } | ||
48 | 154 | |||
49 | 138 | if (mode == MirPowerMode::mir_power_mode_on) | 155 | if (mode == MirPowerMode::mir_power_mode_on) |
50 | 139 | { | 156 | { |
51 | 140 | /* The screen may be dim, but on - make sure to reset backlight */ | 157 | /* The screen may be dim, but on - make sure to reset backlight */ |
52 | @@ -145,16 +162,26 @@ | |||
53 | 145 | } | 162 | } |
54 | 146 | else | 163 | else |
55 | 147 | { | 164 | { |
57 | 148 | cancel_timers_l(); | 165 | cancel_timers_l(reason); |
58 | 149 | configure_display_l(mode, reason); | 166 | configure_display_l(mode, reason); |
59 | 150 | } | 167 | } |
60 | 151 | } | 168 | } |
61 | 152 | 169 | ||
62 | 153 | void usc::MirScreen::configure_display_l(MirPowerMode mode, PowerStateChangeReason reason) | 170 | void usc::MirScreen::configure_display_l(MirPowerMode mode, PowerStateChangeReason reason) |
63 | 154 | { | 171 | { |
64 | 172 | if (reason != PowerStateChangeReason::proximity) | ||
65 | 173 | { | ||
66 | 174 | screen_hardware->enable_proximity(false); | ||
67 | 175 | allow_proximity_to_turn_on_screen = false; | ||
68 | 176 | } | ||
69 | 177 | |||
70 | 155 | if (current_power_mode == mode) | 178 | if (current_power_mode == mode) |
71 | 156 | return; | 179 | return; |
72 | 157 | 180 | ||
73 | 181 | allow_proximity_to_turn_on_screen = | ||
74 | 182 | mode == mir_power_mode_off && | ||
75 | 183 | reason == PowerStateChangeReason::proximity; | ||
76 | 184 | |||
77 | 158 | std::shared_ptr<mg::DisplayConfiguration> displayConfig = display->configuration(); | 185 | std::shared_ptr<mg::DisplayConfiguration> displayConfig = display->configuration(); |
78 | 159 | 186 | ||
79 | 160 | displayConfig->for_each_output( | 187 | displayConfig->for_each_output( |
80 | @@ -193,8 +220,11 @@ | |||
81 | 193 | screen_hardware->allow_suspend(); | 220 | screen_hardware->allow_suspend(); |
82 | 194 | } | 221 | } |
83 | 195 | 222 | ||
85 | 196 | void usc::MirScreen::cancel_timers_l() | 223 | void usc::MirScreen::cancel_timers_l(PowerStateChangeReason reason) |
86 | 197 | { | 224 | { |
87 | 225 | if (reason == PowerStateChangeReason::proximity) | ||
88 | 226 | return; | ||
89 | 227 | |||
90 | 198 | power_off_alarm->cancel(); | 228 | power_off_alarm->cancel(); |
91 | 199 | dimmer_alarm->cancel(); | 229 | dimmer_alarm->cancel(); |
92 | 200 | next_power_off = {}; | 230 | next_power_off = {}; |
93 | @@ -203,29 +233,35 @@ | |||
94 | 203 | 233 | ||
95 | 204 | void usc::MirScreen::reset_timers_l(PowerStateChangeReason reason) | 234 | void usc::MirScreen::reset_timers_l(PowerStateChangeReason reason) |
96 | 205 | { | 235 | { |
98 | 206 | if (restart_timers && current_power_mode != MirPowerMode::mir_power_mode_off) | 236 | if (current_power_mode != MirPowerMode::mir_power_mode_off) |
99 | 237 | reset_timers_ignoring_power_mode_l(reason); | ||
100 | 238 | } | ||
101 | 239 | |||
102 | 240 | void usc::MirScreen::reset_timers_ignoring_power_mode_l(PowerStateChangeReason reason) | ||
103 | 241 | { | ||
104 | 242 | if (!restart_timers || reason == PowerStateChangeReason::proximity) | ||
105 | 243 | return; | ||
106 | 244 | |||
107 | 245 | auto const timeouts = timeouts_for(reason); | ||
108 | 246 | auto const now = clock->now(); | ||
109 | 247 | |||
110 | 248 | if (timeouts.power_off_timeout.count() > 0) | ||
111 | 207 | { | 249 | { |
116 | 208 | auto const timeouts = timeouts_for(reason); | 250 | auto const new_next_power_off = now + timeouts.power_off_timeout; |
117 | 209 | auto const now = clock->now(); | 251 | if (new_next_power_off > next_power_off) |
114 | 210 | |||
115 | 211 | if (timeouts.power_off_timeout.count() > 0) | ||
118 | 212 | { | 252 | { |
125 | 213 | auto const new_next_power_off = now + timeouts.power_off_timeout; | 253 | power_off_alarm->reschedule_in(timeouts.power_off_timeout); |
126 | 214 | if (new_next_power_off > next_power_off) | 254 | next_power_off = new_next_power_off; |
121 | 215 | { | ||
122 | 216 | power_off_alarm->reschedule_in(timeouts.power_off_timeout); | ||
123 | 217 | next_power_off = new_next_power_off; | ||
124 | 218 | } | ||
127 | 219 | } | 255 | } |
128 | 256 | } | ||
129 | 220 | 257 | ||
131 | 221 | if (timeouts.dimming_timeout.count() > 0) | 258 | if (timeouts.dimming_timeout.count() > 0) |
132 | 259 | { | ||
133 | 260 | auto const new_next_dimming = now + timeouts.dimming_timeout; | ||
134 | 261 | if (new_next_dimming > next_dimming) | ||
135 | 222 | { | 262 | { |
142 | 223 | auto const new_next_dimming = now + timeouts.dimming_timeout; | 263 | dimmer_alarm->reschedule_in(timeouts.dimming_timeout); |
143 | 224 | if (new_next_dimming > next_dimming) | 264 | next_dimming = new_next_dimming; |
138 | 225 | { | ||
139 | 226 | dimmer_alarm->reschedule_in(timeouts.dimming_timeout); | ||
140 | 227 | next_dimming = new_next_dimming; | ||
141 | 228 | } | ||
144 | 229 | } | 265 | } |
145 | 230 | } | 266 | } |
146 | 231 | } | 267 | } |
147 | @@ -235,7 +271,7 @@ | |||
148 | 235 | if (enable) | 271 | if (enable) |
149 | 236 | reset_timers_l(PowerStateChangeReason::inactivity); | 272 | reset_timers_l(PowerStateChangeReason::inactivity); |
150 | 237 | else | 273 | else |
152 | 238 | cancel_timers_l(); | 274 | cancel_timers_l(PowerStateChangeReason::inactivity); |
153 | 239 | } | 275 | } |
154 | 240 | 276 | ||
155 | 241 | usc::MirScreen::Timeouts usc::MirScreen::timeouts_for(PowerStateChangeReason reason) | 277 | usc::MirScreen::Timeouts usc::MirScreen::timeouts_for(PowerStateChangeReason reason) |
156 | @@ -246,6 +282,18 @@ | |||
157 | 246 | return inactivity_timeouts; | 282 | return inactivity_timeouts; |
158 | 247 | } | 283 | } |
159 | 248 | 284 | ||
160 | 285 | bool usc::MirScreen::is_screen_change_allowed(MirPowerMode mode, PowerStateChangeReason reason) | ||
161 | 286 | { | ||
162 | 287 | if (mode == MirPowerMode::mir_power_mode_on && | ||
163 | 288 | reason == PowerStateChangeReason::proximity && | ||
164 | 289 | !allow_proximity_to_turn_on_screen) | ||
165 | 290 | { | ||
166 | 291 | return false; | ||
167 | 292 | } | ||
168 | 293 | |||
169 | 294 | return true; | ||
170 | 295 | } | ||
171 | 296 | |||
172 | 249 | void usc::MirScreen::power_off_alarm_notification() | 297 | void usc::MirScreen::power_off_alarm_notification() |
173 | 250 | { | 298 | { |
174 | 251 | std::lock_guard<std::mutex> lock{guard}; | 299 | std::lock_guard<std::mutex> lock{guard}; |
175 | 252 | 300 | ||
176 | === modified file 'src/mir_screen.h' | |||
177 | --- src/mir_screen.h 2015-07-17 12:45:10 +0000 | |||
178 | +++ src/mir_screen.h 2015-07-17 12:45:10 +0000 | |||
179 | @@ -77,10 +77,12 @@ | |||
180 | 77 | void set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason); | 77 | void set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason); |
181 | 78 | void configure_display_l(MirPowerMode mode, PowerStateChangeReason reason); | 78 | void configure_display_l(MirPowerMode mode, PowerStateChangeReason reason); |
182 | 79 | 79 | ||
184 | 80 | void cancel_timers_l(); | 80 | void cancel_timers_l(PowerStateChangeReason reason); |
185 | 81 | void reset_timers_l(PowerStateChangeReason reason); | 81 | void reset_timers_l(PowerStateChangeReason reason); |
186 | 82 | void reset_timers_ignoring_power_mode_l(PowerStateChangeReason reason); | ||
187 | 82 | void enable_inactivity_timers_l(bool flag); | 83 | void enable_inactivity_timers_l(bool flag); |
188 | 83 | Timeouts timeouts_for(PowerStateChangeReason reason); | 84 | Timeouts timeouts_for(PowerStateChangeReason reason); |
189 | 85 | bool is_screen_change_allowed(MirPowerMode mode, PowerStateChangeReason reason); | ||
190 | 84 | 86 | ||
191 | 85 | void power_off_alarm_notification(); | 87 | void power_off_alarm_notification(); |
192 | 86 | void dimmer_alarm_notification(); | 88 | void dimmer_alarm_notification(); |
193 | @@ -103,6 +105,7 @@ | |||
194 | 103 | MirPowerMode current_power_mode; | 105 | MirPowerMode current_power_mode; |
195 | 104 | bool restart_timers; | 106 | bool restart_timers; |
196 | 105 | PowerStateChangeHandler power_state_change_handler; | 107 | PowerStateChangeHandler power_state_change_handler; |
197 | 108 | bool allow_proximity_to_turn_on_screen; | ||
198 | 106 | }; | 109 | }; |
199 | 107 | 110 | ||
200 | 108 | } | 111 | } |
201 | 109 | 112 | ||
202 | === modified file 'src/powerd_mediator.cpp' | |||
203 | --- src/powerd_mediator.cpp 2015-04-24 14:40:28 +0000 | |||
204 | +++ src/powerd_mediator.cpp 2015-07-17 12:45:10 +0000 | |||
205 | @@ -56,6 +56,7 @@ | |||
206 | 56 | backlight_state{BacklightState::normal}, | 56 | backlight_state{BacklightState::normal}, |
207 | 57 | auto_brightness_supported_{false}, | 57 | auto_brightness_supported_{false}, |
208 | 58 | auto_brightness_requested{false}, | 58 | auto_brightness_requested{false}, |
209 | 59 | proximity_enabled{false}, | ||
210 | 59 | sys_state{SysState::unknown} | 60 | sys_state{SysState::unknown} |
211 | 60 | { | 61 | { |
212 | 61 | connection.add_match( | 62 | connection.add_match( |
213 | @@ -197,6 +198,13 @@ | |||
214 | 197 | return max_brightness_; | 198 | return max_brightness_; |
215 | 198 | } | 199 | } |
216 | 199 | 200 | ||
217 | 201 | void usc::PowerdMediator::enable_proximity(bool enable) | ||
218 | 202 | { | ||
219 | 203 | std::lock_guard<decltype(mutex)> lock{mutex}; | ||
220 | 204 | |||
221 | 205 | enable_proximity_l(enable, ForceProximity::no); | ||
222 | 206 | } | ||
223 | 207 | |||
224 | 200 | bool usc::PowerdMediator::is_system_suspended() | 208 | bool usc::PowerdMediator::is_system_suspended() |
225 | 201 | { | 209 | { |
226 | 202 | std::lock_guard<decltype(mutex)> lock{mutex}; | 210 | std::lock_guard<decltype(mutex)> lock{mutex}; |
227 | @@ -290,6 +298,8 @@ | |||
228 | 290 | 298 | ||
229 | 291 | // Powerd may have restarted, re-apply backlight settings | 299 | // Powerd may have restarted, re-apply backlight settings |
230 | 292 | change_backlight_state(backlight_state, ForceBacklightState::yes); | 300 | change_backlight_state(backlight_state, ForceBacklightState::yes); |
231 | 301 | |||
232 | 302 | enable_proximity_l(false, ForceProximity::yes); | ||
233 | 293 | } | 303 | } |
234 | 294 | 304 | ||
235 | 295 | void usc::PowerdMediator::init_brightness_params() | 305 | void usc::PowerdMediator::init_brightness_params() |
236 | @@ -362,6 +372,22 @@ | |||
237 | 362 | } | 372 | } |
238 | 363 | } | 373 | } |
239 | 364 | 374 | ||
240 | 375 | void usc::PowerdMediator::enable_proximity_l( | ||
241 | 376 | bool enable, ForceProximity force_proximity) | ||
242 | 377 | { | ||
243 | 378 | if (proximity_enabled == enable && force_proximity == ForceProximity::no) | ||
244 | 379 | return; | ||
245 | 380 | |||
246 | 381 | auto const name = "unity-system-compositor"; | ||
247 | 382 | auto const request = enable ? "enableProximityHandling" : | ||
248 | 383 | "disableProximityHandling"; | ||
249 | 384 | invoke_with_reply(request, | ||
250 | 385 | DBUS_TYPE_STRING, &name, | ||
251 | 386 | DBUS_TYPE_INVALID); | ||
252 | 387 | |||
253 | 388 | proximity_enabled = enable; | ||
254 | 389 | } | ||
255 | 390 | |||
256 | 365 | bool usc::PowerdMediator::is_valid_brightness(int brightness) | 391 | bool usc::PowerdMediator::is_valid_brightness(int brightness) |
257 | 366 | { | 392 | { |
258 | 367 | return brightness >= min_brightness_ && brightness <= max_brightness_; | 393 | return brightness >= min_brightness_ && brightness <= max_brightness_; |
259 | 368 | 394 | ||
260 | === modified file 'src/powerd_mediator.h' | |||
261 | --- src/powerd_mediator.h 2015-04-07 13:36:48 +0000 | |||
262 | +++ src/powerd_mediator.h 2015-07-17 12:45:10 +0000 | |||
263 | @@ -46,6 +46,8 @@ | |||
264 | 46 | int min_brightness() override; | 46 | int min_brightness() override; |
265 | 47 | int max_brightness() override; | 47 | int max_brightness() override; |
266 | 48 | 48 | ||
267 | 49 | void enable_proximity(bool enable) override; | ||
268 | 50 | |||
269 | 49 | bool is_system_suspended(); | 51 | bool is_system_suspended(); |
270 | 50 | 52 | ||
271 | 51 | private: | 53 | private: |
272 | @@ -66,6 +68,7 @@ | |||
273 | 66 | 68 | ||
274 | 67 | enum class ForceDisableSuspend { no, yes }; | 69 | enum class ForceDisableSuspend { no, yes }; |
275 | 68 | enum class ForceBacklightState { no, yes }; | 70 | enum class ForceBacklightState { no, yes }; |
276 | 71 | enum class ForceProximity { no, yes }; | ||
277 | 69 | 72 | ||
278 | 70 | static ::DBusHandlerResult handle_dbus_message_thunk( | 73 | static ::DBusHandlerResult handle_dbus_message_thunk( |
279 | 71 | ::DBusConnection* connection, ::DBusMessage* message, void* user_data); | 74 | ::DBusConnection* connection, ::DBusMessage* message, void* user_data); |
280 | @@ -76,6 +79,7 @@ | |||
281 | 76 | void init_brightness_params(); | 79 | void init_brightness_params(); |
282 | 77 | void change_backlight_state( | 80 | void change_backlight_state( |
283 | 78 | BacklightState new_state, ForceBacklightState force_backlight_state); | 81 | BacklightState new_state, ForceBacklightState force_backlight_state); |
284 | 82 | void enable_proximity_l(bool enable, ForceProximity force_proximity); | ||
285 | 79 | bool is_valid_brightness(int brightness); | 83 | bool is_valid_brightness(int brightness); |
286 | 80 | bool request_suspend_block(); | 84 | bool request_suspend_block(); |
287 | 81 | void wait_for_sys_state(SysState state); | 85 | void wait_for_sys_state(SysState state); |
288 | @@ -98,6 +102,7 @@ | |||
289 | 98 | BacklightState backlight_state; | 102 | BacklightState backlight_state; |
290 | 99 | bool auto_brightness_supported_; | 103 | bool auto_brightness_supported_; |
291 | 100 | bool auto_brightness_requested; | 104 | bool auto_brightness_requested; |
292 | 105 | bool proximity_enabled; | ||
293 | 101 | std::string suspend_block_cookie; | 106 | std::string suspend_block_cookie; |
294 | 102 | std::mutex sys_state_mutex; | 107 | std::mutex sys_state_mutex; |
295 | 103 | SysState sys_state; | 108 | SysState sys_state; |
296 | 104 | 109 | ||
297 | === modified file 'src/screen_hardware.h' | |||
298 | --- src/screen_hardware.h 2015-02-18 14:40:29 +0000 | |||
299 | +++ src/screen_hardware.h 2015-07-17 12:45:10 +0000 | |||
300 | @@ -39,6 +39,8 @@ | |||
301 | 39 | virtual int min_brightness() = 0; | 39 | virtual int min_brightness() = 0; |
302 | 40 | virtual int max_brightness() = 0; | 40 | virtual int max_brightness() = 0; |
303 | 41 | 41 | ||
304 | 42 | virtual void enable_proximity(bool enable) = 0; | ||
305 | 43 | |||
306 | 42 | protected: | 44 | protected: |
307 | 43 | ScreenHardware() = default; | 45 | ScreenHardware() = default; |
308 | 44 | ScreenHardware(ScreenHardware const&) = delete; | 46 | ScreenHardware(ScreenHardware const&) = delete; |
309 | 45 | 47 | ||
310 | === modified file 'tests/integration-tests/test_powerd_mediator.cpp' | |||
311 | --- tests/integration-tests/test_powerd_mediator.cpp 2015-04-07 13:36:48 +0000 | |||
312 | +++ tests/integration-tests/test_powerd_mediator.cpp 2015-07-17 12:45:10 +0000 | |||
313 | @@ -84,6 +84,8 @@ | |||
314 | 84 | MOCK_METHOD1(dbus_userAutobrightnessEnable, void(dbus_bool_t enable)); | 84 | MOCK_METHOD1(dbus_userAutobrightnessEnable, void(dbus_bool_t enable)); |
315 | 85 | MOCK_METHOD2(dbus_requestSysState, std::string(char const* name, int state)); | 85 | MOCK_METHOD2(dbus_requestSysState, std::string(char const* name, int state)); |
316 | 86 | MOCK_METHOD1(dbus_clearSysState, void(char const* cookie)); | 86 | MOCK_METHOD1(dbus_clearSysState, void(char const* cookie)); |
317 | 87 | MOCK_METHOD1(dbus_enableProximityHandling, void(char const* name)); | ||
318 | 88 | MOCK_METHOD1(dbus_disableProximityHandling, void(char const* name)); | ||
319 | 87 | 89 | ||
320 | 88 | int32_t const dim_brightness = 13; | 90 | int32_t const dim_brightness = 13; |
321 | 89 | int32_t const min_brightness = 5; | 91 | int32_t const min_brightness = 5; |
322 | @@ -192,6 +194,32 @@ | |||
323 | 192 | 194 | ||
324 | 193 | emit_SysPowerStateChange(0); | 195 | emit_SysPowerStateChange(0); |
325 | 194 | } | 196 | } |
326 | 197 | else if (dbus_message_is_method_call(message, powerd_service_name, "enableProximityHandling")) | ||
327 | 198 | { | ||
328 | 199 | char const* name{nullptr}; | ||
329 | 200 | dbus_message_get_args( | ||
330 | 201 | message, nullptr, | ||
331 | 202 | DBUS_TYPE_STRING, &name, | ||
332 | 203 | DBUS_TYPE_INVALID); | ||
333 | 204 | |||
334 | 205 | dbus_enableProximityHandling(name); | ||
335 | 206 | |||
336 | 207 | usc::DBusMessageHandle reply{dbus_message_new_method_return(message)}; | ||
337 | 208 | dbus_connection_send(connection, reply, nullptr); | ||
338 | 209 | } | ||
339 | 210 | else if (dbus_message_is_method_call(message, powerd_service_name, "disableProximityHandling")) | ||
340 | 211 | { | ||
341 | 212 | char const* name{nullptr}; | ||
342 | 213 | dbus_message_get_args( | ||
343 | 214 | message, nullptr, | ||
344 | 215 | DBUS_TYPE_STRING, &name, | ||
345 | 216 | DBUS_TYPE_INVALID); | ||
346 | 217 | |||
347 | 218 | dbus_disableProximityHandling(name); | ||
348 | 219 | |||
349 | 220 | usc::DBusMessageHandle reply{dbus_message_new_method_return(message)}; | ||
350 | 221 | dbus_connection_send(connection, reply, nullptr); | ||
351 | 222 | } | ||
352 | 195 | 223 | ||
353 | 196 | return DBUS_HANDLER_RESULT_HANDLED; | 224 | return DBUS_HANDLER_RESULT_HANDLED; |
354 | 197 | } | 225 | } |
355 | @@ -462,6 +490,41 @@ | |||
356 | 462 | mediator->allow_suspend(); | 490 | mediator->allow_suspend(); |
357 | 463 | } | 491 | } |
358 | 464 | 492 | ||
359 | 493 | TEST_F(APowerdMediator, enables_and_disables_proximity_handling) | ||
360 | 494 | { | ||
361 | 495 | using namespace testing; | ||
362 | 496 | auto const proximity_name = "unity-system-compositor"; | ||
363 | 497 | |||
364 | 498 | InSequence s; | ||
365 | 499 | EXPECT_CALL(powerd_service, dbus_enableProximityHandling(StrEq(proximity_name))); | ||
366 | 500 | EXPECT_CALL(powerd_service, dbus_disableProximityHandling(StrEq(proximity_name))); | ||
367 | 501 | |||
368 | 502 | mediator->enable_proximity(true); | ||
369 | 503 | mediator->enable_proximity(false); | ||
370 | 504 | } | ||
371 | 505 | |||
372 | 506 | TEST_F(APowerdMediator, ignores_requests_for_redundant_proximity_handling) | ||
373 | 507 | { | ||
374 | 508 | using namespace testing; | ||
375 | 509 | |||
376 | 510 | auto const proximity_name = "unity-system-compositor"; | ||
377 | 511 | |||
378 | 512 | InSequence s; | ||
379 | 513 | EXPECT_CALL(powerd_service, dbus_enableProximityHandling(StrEq(proximity_name))); | ||
380 | 514 | EXPECT_CALL(powerd_service, dbus_disableProximityHandling(StrEq(proximity_name))); | ||
381 | 515 | |||
382 | 516 | // Should be ignore, proximity already disabled | ||
383 | 517 | mediator->enable_proximity(false); | ||
384 | 518 | |||
385 | 519 | // Should be handled only once | ||
386 | 520 | mediator->enable_proximity(true); | ||
387 | 521 | mediator->enable_proximity(true); | ||
388 | 522 | |||
389 | 523 | // Should be handled only once | ||
390 | 524 | mediator->enable_proximity(false); | ||
391 | 525 | mediator->enable_proximity(false); | ||
392 | 526 | } | ||
393 | 527 | |||
394 | 465 | namespace | 528 | namespace |
395 | 466 | { | 529 | { |
396 | 467 | 530 | ||
397 | @@ -637,6 +700,24 @@ | |||
398 | 637 | EXPECT_CALL(powerd_service, dbus_setUserBrightness(0)).Times(AtMost(1)); | 700 | EXPECT_CALL(powerd_service, dbus_setUserBrightness(0)).Times(AtMost(1)); |
399 | 638 | } | 701 | } |
400 | 639 | 702 | ||
401 | 703 | TEST(APowerdMediatorAtStartup, disables_proximity_handling) | ||
402 | 704 | { | ||
403 | 705 | using namespace testing; | ||
404 | 706 | |||
405 | 707 | dbus_bool_t const auto_brightness_supported{TRUE}; | ||
406 | 708 | |||
407 | 709 | ut::DBusBus bus; | ||
408 | 710 | NiceMock<PowerdService> powerd_service{ | ||
409 | 711 | bus.address(), auto_brightness_supported, PowerdService::StartNow::yes}; | ||
410 | 712 | |||
411 | 713 | EXPECT_CALL(powerd_service, dbus_disableProximityHandling(_)); | ||
412 | 714 | |||
413 | 715 | usc::PowerdMediator mediator{bus.address()}; | ||
414 | 716 | powerd_service.wait_for_initial_setup(); | ||
415 | 717 | |||
416 | 718 | Mock::VerifyAndClearExpectations(&powerd_service); | ||
417 | 719 | } | ||
418 | 720 | |||
419 | 640 | TEST(APowerdMediatorAtShutdown, turns_off_backlight) | 721 | TEST(APowerdMediatorAtShutdown, turns_off_backlight) |
420 | 641 | { | 722 | { |
421 | 642 | using namespace testing; | 723 | using namespace testing; |
422 | 643 | 724 | ||
423 | === modified file 'tests/unit-tests/test_mir_screen.cpp' | |||
424 | --- tests/unit-tests/test_mir_screen.cpp 2015-07-17 12:45:10 +0000 | |||
425 | +++ tests/unit-tests/test_mir_screen.cpp 2015-07-17 12:45:10 +0000 | |||
426 | @@ -116,6 +116,25 @@ | |||
427 | 116 | MOCK_METHOD1(set_brightness, void(int)); | 116 | MOCK_METHOD1(set_brightness, void(int)); |
428 | 117 | int min_brightness() override { return 100; } | 117 | int min_brightness() override { return 100; } |
429 | 118 | int max_brightness() override { return 0; } | 118 | int max_brightness() override { return 0; } |
430 | 119 | |||
431 | 120 | enum class Proximity {near, far}; | ||
432 | 121 | |||
433 | 122 | void enable_proximity(bool enable) override | ||
434 | 123 | { | ||
435 | 124 | proximity_enabled = enable; | ||
436 | 125 | set_proximity(current_proximity); | ||
437 | 126 | } | ||
438 | 127 | |||
439 | 128 | void set_proximity(Proximity proximity) | ||
440 | 129 | { | ||
441 | 130 | current_proximity = proximity; | ||
442 | 131 | if (proximity_enabled) | ||
443 | 132 | on_proximity_changed(current_proximity); | ||
444 | 133 | } | ||
445 | 134 | |||
446 | 135 | std::function<void(Proximity)> on_proximity_changed = [](Proximity){}; | ||
447 | 136 | Proximity current_proximity{Proximity::far}; | ||
448 | 137 | bool proximity_enabled{false}; | ||
449 | 119 | }; | 138 | }; |
450 | 120 | 139 | ||
451 | 121 | struct MockTouchVisualizer : mir::input::TouchVisualizer | 140 | struct MockTouchVisualizer : mir::input::TouchVisualizer |
452 | @@ -129,6 +148,36 @@ | |||
453 | 129 | 148 | ||
454 | 130 | struct AMirScreen : testing::Test | 149 | struct AMirScreen : testing::Test |
455 | 131 | { | 150 | { |
456 | 151 | AMirScreen() | ||
457 | 152 | { | ||
458 | 153 | using namespace testing; | ||
459 | 154 | |||
460 | 155 | screen_hardware->on_proximity_changed = | ||
461 | 156 | [this] (MockScreenHardware::Proximity p) { defer_proximity_event(p); }; | ||
462 | 157 | } | ||
463 | 158 | |||
464 | 159 | void defer_proximity_event(MockScreenHardware::Proximity proximity) | ||
465 | 160 | { | ||
466 | 161 | deferred_actions.push_back( | ||
467 | 162 | [this, proximity] | ||
468 | 163 | { | ||
469 | 164 | mir_screen.set_screen_power_mode( | ||
470 | 165 | proximity == MockScreenHardware::Proximity::far ? | ||
471 | 166 | MirPowerMode::mir_power_mode_on : | ||
472 | 167 | MirPowerMode::mir_power_mode_off, | ||
473 | 168 | PowerStateChangeReason::proximity); | ||
474 | 169 | }); | ||
475 | 170 | } | ||
476 | 171 | |||
477 | 172 | void process_deferred_actions() | ||
478 | 173 | { | ||
479 | 174 | for (auto const& a : deferred_actions) | ||
480 | 175 | a(); | ||
481 | 176 | deferred_actions.clear(); | ||
482 | 177 | } | ||
483 | 178 | |||
484 | 179 | std::vector<std::function<void(void)>> deferred_actions; | ||
485 | 180 | |||
486 | 132 | std::chrono::seconds const power_off_timeout{60}; | 181 | std::chrono::seconds const power_off_timeout{60}; |
487 | 133 | std::chrono::seconds const dimmer_timeout{50}; | 182 | std::chrono::seconds const dimmer_timeout{50}; |
488 | 134 | std::chrono::seconds const notification_power_off_timeout{15}; | 183 | std::chrono::seconds const notification_power_off_timeout{15}; |
489 | @@ -185,6 +234,26 @@ | |||
490 | 185 | verify_and_clear_expectations(); | 234 | verify_and_clear_expectations(); |
491 | 186 | } | 235 | } |
492 | 187 | 236 | ||
493 | 237 | void receive_notification() | ||
494 | 238 | { | ||
495 | 239 | mir_screen.set_screen_power_mode( | ||
496 | 240 | MirPowerMode::mir_power_mode_on, | ||
497 | 241 | PowerStateChangeReason::notification); | ||
498 | 242 | process_deferred_actions(); | ||
499 | 243 | } | ||
500 | 244 | |||
501 | 245 | void cover_screen() | ||
502 | 246 | { | ||
503 | 247 | screen_hardware->set_proximity(MockScreenHardware::Proximity::near); | ||
504 | 248 | process_deferred_actions(); | ||
505 | 249 | } | ||
506 | 250 | |||
507 | 251 | void uncover_screen() | ||
508 | 252 | { | ||
509 | 253 | screen_hardware->set_proximity(MockScreenHardware::Proximity::far); | ||
510 | 254 | process_deferred_actions(); | ||
511 | 255 | } | ||
512 | 256 | |||
513 | 188 | void verify_and_clear_expectations() | 257 | void verify_and_clear_expectations() |
514 | 189 | { | 258 | { |
515 | 190 | using namespace testing; | 259 | using namespace testing; |
516 | @@ -378,13 +447,12 @@ | |||
517 | 378 | EXPECT_THAT(handler_mode, Eq(MirPowerMode::mir_power_mode_off)); | 447 | EXPECT_THAT(handler_mode, Eq(MirPowerMode::mir_power_mode_off)); |
518 | 379 | } | 448 | } |
519 | 380 | 449 | ||
521 | 381 | TEST_F(AMirScreen, turns_screen_off_after_15s_for_notification) | 450 | TEST_F(AMirScreen, turns_screen_off_after_notification_timeout) |
522 | 382 | { | 451 | { |
523 | 383 | turn_screen_off(); | 452 | turn_screen_off(); |
524 | 384 | 453 | ||
525 | 385 | expect_screen_is_turned_on(); | 454 | expect_screen_is_turned_on(); |
528 | 386 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | 455 | receive_notification(); |
527 | 387 | PowerStateChangeReason::notification); | ||
529 | 388 | verify_and_clear_expectations(); | 456 | verify_and_clear_expectations(); |
530 | 389 | 457 | ||
531 | 390 | expect_screen_is_turned_off(); | 458 | expect_screen_is_turned_off(); |
532 | @@ -396,8 +464,7 @@ | |||
533 | 396 | turn_screen_off(); | 464 | turn_screen_off(); |
534 | 397 | 465 | ||
535 | 398 | expect_screen_is_turned_on(); | 466 | expect_screen_is_turned_on(); |
538 | 399 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | 467 | receive_notification(); |
537 | 400 | PowerStateChangeReason::notification); | ||
539 | 401 | verify_and_clear_expectations(); | 468 | verify_and_clear_expectations(); |
540 | 402 | 469 | ||
541 | 403 | // At T=10 we request a temporary keep display on (e.g. user has touched | 470 | // At T=10 we request a temporary keep display on (e.g. user has touched |
542 | @@ -426,8 +493,7 @@ | |||
543 | 426 | 493 | ||
544 | 427 | // At T=50 we get a notification | 494 | // At T=50 we get a notification |
545 | 428 | timer->advance_by(fifty_seconds); | 495 | timer->advance_by(fifty_seconds); |
548 | 429 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | 496 | receive_notification(); |
547 | 430 | PowerStateChangeReason::notification); | ||
549 | 431 | verify_and_clear_expectations(); | 497 | verify_and_clear_expectations(); |
550 | 432 | 498 | ||
551 | 433 | // At T=60 the screen should still be active because the notification | 499 | // At T=60 the screen should still be active because the notification |
552 | @@ -452,8 +518,7 @@ | |||
553 | 452 | 518 | ||
554 | 453 | // At T=30 we get a notification | 519 | // At T=30 we get a notification |
555 | 454 | timer->advance_by(thirty_seconds); | 520 | timer->advance_by(thirty_seconds); |
558 | 455 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | 521 | receive_notification(); |
557 | 456 | PowerStateChangeReason::notification); | ||
559 | 457 | verify_and_clear_expectations(); | 522 | verify_and_clear_expectations(); |
560 | 458 | 523 | ||
561 | 459 | // At T=45 the screen should still be active because the notification | 524 | // At T=45 the screen should still be active because the notification |
562 | @@ -485,8 +550,7 @@ | |||
563 | 485 | 550 | ||
564 | 486 | // At T=40 we get a notification | 551 | // At T=40 we get a notification |
565 | 487 | timer->advance_by(fourty_seconds); | 552 | timer->advance_by(fourty_seconds); |
568 | 488 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | 553 | receive_notification(); |
567 | 489 | PowerStateChangeReason::notification); | ||
569 | 490 | verify_and_clear_expectations(); | 554 | verify_and_clear_expectations(); |
570 | 491 | 555 | ||
571 | 492 | // At T=50 nothing should happen since the notification has | 556 | // At T=50 nothing should happen since the notification has |
572 | @@ -506,3 +570,152 @@ | |||
573 | 506 | expect_screen_is_turned_off(); | 570 | expect_screen_is_turned_off(); |
574 | 507 | timer->advance_by(eight_seconds); | 571 | timer->advance_by(eight_seconds); |
575 | 508 | } | 572 | } |
576 | 573 | |||
577 | 574 | TEST_F(AMirScreen, proximity_requests_affect_screen_state) | ||
578 | 575 | { | ||
579 | 576 | expect_screen_is_turned_off(); | ||
580 | 577 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_off, | ||
581 | 578 | PowerStateChangeReason::proximity); | ||
582 | 579 | verify_and_clear_expectations(); | ||
583 | 580 | |||
584 | 581 | expect_screen_is_turned_on(); | ||
585 | 582 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | ||
586 | 583 | PowerStateChangeReason::proximity); | ||
587 | 584 | verify_and_clear_expectations(); | ||
588 | 585 | } | ||
589 | 586 | |||
590 | 587 | TEST_F(AMirScreen, proximity_requests_do_not_reset_timeouts) | ||
591 | 588 | { | ||
592 | 589 | // At T=0 we turn the screen on, and normal inactivity timeouts | ||
593 | 590 | // are reset | ||
594 | 591 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | ||
595 | 592 | PowerStateChangeReason::power_key); | ||
596 | 593 | |||
597 | 594 | // At T=30 we get a screen off request due to proximity | ||
598 | 595 | timer->advance_by(thirty_seconds); | ||
599 | 596 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_off, | ||
600 | 597 | PowerStateChangeReason::proximity); | ||
601 | 598 | |||
602 | 599 | // At T=40 we get a screen on request due to proximity | ||
603 | 600 | timer->advance_by(ten_seconds); | ||
604 | 601 | mir_screen.set_screen_power_mode(MirPowerMode::mir_power_mode_on, | ||
605 | 602 | PowerStateChangeReason::proximity); | ||
606 | 603 | |||
607 | 604 | verify_and_clear_expectations(); | ||
608 | 605 | |||
609 | 606 | // At T=50 screen should be dimmed due to the inactivity | ||
610 | 607 | // dimming timeout | ||
611 | 608 | expect_screen_is_turned_dim(); | ||
612 | 609 | timer->advance_by(ten_seconds); | ||
613 | 610 | verify_and_clear_expectations(); | ||
614 | 611 | |||
615 | 612 | // At T=60 the screen should turn off due to the normal | ||
616 | 613 | // inactivity timeout | ||
617 | 614 | expect_screen_is_turned_off(); | ||
618 | 615 | timer->advance_by(ten_seconds); | ||
619 | 616 | } | ||
620 | 617 | |||
621 | 618 | TEST_F(AMirScreen, does_not_turn_on_screen_when_notification_arrives_with_phone_covered) | ||
622 | 619 | { | ||
623 | 620 | turn_screen_off(); | ||
624 | 621 | cover_screen(); | ||
625 | 622 | |||
626 | 623 | expect_no_reconfiguration(); | ||
627 | 624 | receive_notification(); | ||
628 | 625 | } | ||
629 | 626 | |||
630 | 627 | TEST_F(AMirScreen, turns_screen_on_when_phone_is_uncovered_after_notification_arrives) | ||
631 | 628 | { | ||
632 | 629 | turn_screen_off(); | ||
633 | 630 | cover_screen(); | ||
634 | 631 | |||
635 | 632 | expect_no_reconfiguration(); | ||
636 | 633 | receive_notification(); | ||
637 | 634 | verify_and_clear_expectations(); | ||
638 | 635 | |||
639 | 636 | expect_screen_is_turned_on(); | ||
640 | 637 | uncover_screen(); | ||
641 | 638 | } | ||
642 | 639 | |||
643 | 640 | TEST_F(AMirScreen, cancels_proximity_handling_when_phone_is_turned_off_after_notification) | ||
644 | 641 | { | ||
645 | 642 | turn_screen_off(); | ||
646 | 643 | cover_screen(); | ||
647 | 644 | |||
648 | 645 | receive_notification(); | ||
649 | 646 | timer->advance_by(notification_power_off_timeout); | ||
650 | 647 | verify_and_clear_expectations(); | ||
651 | 648 | |||
652 | 649 | expect_no_reconfiguration(); | ||
653 | 650 | uncover_screen(); | ||
654 | 651 | cover_screen(); | ||
655 | 652 | } | ||
656 | 653 | |||
657 | 654 | TEST_F(AMirScreen, cancels_proximity_handling_when_screen_is_touched_after_notification) | ||
658 | 655 | { | ||
659 | 656 | turn_screen_off(); | ||
660 | 657 | |||
661 | 658 | receive_notification(); | ||
662 | 659 | mir_screen.keep_display_on_temporarily(); | ||
663 | 660 | verify_and_clear_expectations(); | ||
664 | 661 | |||
665 | 662 | expect_no_reconfiguration(); | ||
666 | 663 | cover_screen(); | ||
667 | 664 | uncover_screen(); | ||
668 | 665 | } | ||
669 | 666 | |||
670 | 667 | TEST_F(AMirScreen, does_not_allow_proximity_to_turn_on_screen_not_turned_off_by_proximity) | ||
671 | 668 | { | ||
672 | 669 | turn_screen_off(); | ||
673 | 670 | |||
674 | 671 | expect_no_reconfiguration(); | ||
675 | 672 | mir_screen.set_screen_power_mode( | ||
676 | 673 | MirPowerMode::mir_power_mode_on, | ||
677 | 674 | PowerStateChangeReason::proximity); | ||
678 | 675 | verify_and_clear_expectations(); | ||
679 | 676 | |||
680 | 677 | expect_no_reconfiguration(); | ||
681 | 678 | mir_screen.set_screen_power_mode( | ||
682 | 679 | MirPowerMode::mir_power_mode_off, | ||
683 | 680 | PowerStateChangeReason::proximity); | ||
684 | 681 | verify_and_clear_expectations(); | ||
685 | 682 | |||
686 | 683 | expect_no_reconfiguration(); | ||
687 | 684 | mir_screen.set_screen_power_mode( | ||
688 | 685 | MirPowerMode::mir_power_mode_on, | ||
689 | 686 | PowerStateChangeReason::proximity); | ||
690 | 687 | } | ||
691 | 688 | |||
692 | 689 | TEST_F(AMirScreen, does_not_allow_proximity_to_turn_on_screen_not_turned_off_by_proximity_2) | ||
693 | 690 | { | ||
694 | 691 | mir_screen.set_screen_power_mode( | ||
695 | 692 | MirPowerMode::mir_power_mode_off, | ||
696 | 693 | PowerStateChangeReason::proximity); | ||
697 | 694 | |||
698 | 695 | mir_screen.set_screen_power_mode( | ||
699 | 696 | MirPowerMode::mir_power_mode_off, | ||
700 | 697 | PowerStateChangeReason::power_key); | ||
701 | 698 | |||
702 | 699 | verify_and_clear_expectations(); | ||
703 | 700 | |||
704 | 701 | expect_no_reconfiguration(); | ||
705 | 702 | mir_screen.set_screen_power_mode( | ||
706 | 703 | MirPowerMode::mir_power_mode_on, | ||
707 | 704 | PowerStateChangeReason::proximity); | ||
708 | 705 | } | ||
709 | 706 | |||
710 | 707 | TEST_F(AMirScreen, proximity_can_affect_screen_after_keep_display_on) | ||
711 | 708 | { | ||
712 | 709 | mir_screen.keep_display_on(true); | ||
713 | 710 | |||
714 | 711 | expect_screen_is_turned_off(); | ||
715 | 712 | mir_screen.set_screen_power_mode( | ||
716 | 713 | MirPowerMode::mir_power_mode_off, | ||
717 | 714 | PowerStateChangeReason::proximity); | ||
718 | 715 | verify_and_clear_expectations(); | ||
719 | 716 | |||
720 | 717 | expect_screen_is_turned_on(); | ||
721 | 718 | mir_screen.set_screen_power_mode( | ||
722 | 719 | MirPowerMode::mir_power_mode_on, | ||
723 | 720 | PowerStateChangeReason::proximity); | ||
724 | 721 | } |
PASSED: Continuous integration, rev:231 jenkins. qa.ubuntu. com/job/ unity-system- compositor- ci/247/ jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-amd64- ci/35 jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-armhf- ci/35 jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-armhf- ci/35/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-i386- ci/35
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- system- compositor- ci/247/ rebuild
http://