Merge lp:~phablet-team/powerd/dbus-stuff into lp:powerd
- dbus-stuff
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michael Frey |
Approved revision: | 37 |
Merged at revision: | 10 |
Proposed branch: | lp:~phablet-team/powerd/dbus-stuff |
Merge into: | lp:powerd |
Diff against target: |
2175 lines (+1749/-104) 29 files modified
CMakeLists.txt (+43/-4) cmake/COPYING-CMAKE-SCRIPTS (+22/-0) cmake/UseGdbusCodegen.cmake (+35/-0) data/com.canonical.powerd.xml (+25/-0) debian/changelog (+14/-0) debian/control (+3/-2) debian/install (+1/-0) debian/powerd.conf (+24/-0) debian/upstart (+4/-2) libsuspend/CMakeLists.txt (+12/-0) libsuspend/autosleep.c (+49/-0) libsuspend/common.h (+35/-0) libsuspend/earlysuspend.c (+55/-0) libsuspend/legacy.c (+82/-0) libsuspend/libsuspend.c (+78/-0) libsuspend/libsuspend.h (+35/-0) libsuspend/mocksuspend.c (+49/-0) libsuspend/sysfs.c (+62/-0) libsuspend/sysfs.h (+26/-0) src/CMakeLists.txt (+18/-0) src/power-request.c (+446/-0) src/powerd-internal.h (+63/-0) src/powerd-object.c (+125/-0) src/powerd-object.h (+60/-0) src/powerd.cpp (+134/-96) src/powerd.h (+41/-0) testclient/CMakeLists.txt (+37/-0) testclient/testclient.c (+120/-0) tester.sh (+51/-0) |
To merge this branch: | bzr merge lp:~phablet-team/powerd/dbus-stuff |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Frey (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+164811@code.launchpad.net |
Commit message
Massive influx of changes including:
1) control file cleanup and new deps
2) support for listening for power requests on dbus
3) tie in to seth's low level libsuspend code
4) a simple C based test client for the power requests
Description of the change
Massive influx of changes including:
1) control file cleanup and new deps
2) support for listening for power requests on dbus
3) tie in to seth's low level libsuspend code
4) a simple C based test client for the power requests
What did not land:
1) full internal use of power state requests, for example, the activity timer could hold an active request until it expired. Seth is working on this now, but it will not impact the functionality
We have more work to do before we move on to display power states but we should merge this and release now or the merges will get larger and larger.
No new changelog entry, we can discuss whether we're releasing this tomorrow.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 33. By Matt Fischer
-
removing bzrignore which should not be committed
- 34. By Matt Fischer
-
merging seth's changes also remove the debug line from the find function, it's too chatty
- 35. By Matt Fischer
-
Adding more debug info by printing the string and not the number in most
places, some whitespace cleanup - 36. By Matt Fischer
-
fixing merge mistake
- 37. By Matt Fischer
-
update changelog
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:36
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:37
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michael Frey (mfrey) wrote : | # |
Tested. All working well. Approved.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-02-13 17:41:38 +0000 |
3 | +++ CMakeLists.txt 2013-05-21 14:54:26 +0000 |
4 | @@ -1,39 +1,78 @@ |
5 | project(powerd) |
6 | +cmake_minimum_required(VERSION 2.8.9) |
7 | + |
8 | +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") |
9 | +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb -g") |
10 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -ggdb -g") |
11 | + |
12 | +set(GDBUS_NAME powerd-dbus) |
13 | + |
14 | +find_package(PkgConfig) |
15 | +pkg_check_modules(GLIB glib-2.0) |
16 | +pkg_check_modules(GUDEV gudev-1.0) |
17 | +pkg_check_modules(GIO gio-2.0) |
18 | +pkg_check_modules(GIO-UNIX gio-unix-2.0) |
19 | + |
20 | +set(POWERD_GENERATED_SOURCES |
21 | + ${GDBUS_NAME}.c |
22 | +) |
23 | +set(POWERD_GENERATED_HEADERS |
24 | + ${GDBUS_NAME}.h |
25 | +) |
26 | +SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/src/${POWERD_GENERATED_SOURCES} PROPERTIES GENERATED 1) |
27 | |
28 | set( |
29 | SRCS |
30 | |
31 | src/powerd.cpp |
32 | + src/powerd-object.c |
33 | + src/power-request.c |
34 | + src/${GDBUS_NAME}.c |
35 | ) |
36 | |
37 | -find_package(PkgConfig) |
38 | -pkg_check_modules(GLIB glib-2.0) |
39 | -pkg_check_modules(GUDEV gudev-1.0) |
40 | - |
41 | link_directories( |
42 | ${GLIB_LIBRARY_DIRS} |
43 | + ${GIO_LIBRARY_DIRS} |
44 | + ${GIO-UNIX_LIBRARY_DIRS} |
45 | ${GUDEV_LIBRARY_DIRS} |
46 | ) |
47 | |
48 | include_directories( |
49 | ${GLIB_INCLUDE_DIRS} |
50 | + ${GIO_INCLUDE_DIRS} |
51 | + ${GIO-UNIX_INCLUDE_DIRS} |
52 | ${GUDEV_INCLUDE_DIRS} |
53 | + ${PROJECT_SOURCE_DIR}/libsuspend |
54 | + ${CMAKE_CURRENT_BINARY_DIR}/src |
55 | ) |
56 | |
57 | +add_subdirectory(libsuspend) |
58 | +add_subdirectory(src) |
59 | +add_subdirectory(testclient) |
60 | + |
61 | add_executable( |
62 | powerd |
63 | |
64 | ${SRCS} |
65 | ) |
66 | |
67 | +add_dependencies( |
68 | + powerd |
69 | + |
70 | + dbus_bindings |
71 | +) |
72 | + |
73 | target_link_libraries( |
74 | powerd |
75 | + suspend |
76 | |
77 | is |
78 | sf |
79 | hybris_ics |
80 | ${GLIB_LIBRARIES} |
81 | ${GUDEV_LIBRARIES} |
82 | + ${GIO_LIBRARIES} |
83 | + ${GIO-UNIX_LIBRARIES} |
84 | ) |
85 | |
86 | install( |
87 | |
88 | === added directory 'cmake' |
89 | === added file 'cmake/COPYING-CMAKE-SCRIPTS' |
90 | --- cmake/COPYING-CMAKE-SCRIPTS 1970-01-01 00:00:00 +0000 |
91 | +++ cmake/COPYING-CMAKE-SCRIPTS 2013-05-21 14:54:26 +0000 |
92 | @@ -0,0 +1,22 @@ |
93 | +Redistribution and use in source and binary forms, with or without |
94 | +modification, are permitted provided that the following conditions |
95 | +are met: |
96 | + |
97 | +1. Redistributions of source code must retain the copyright |
98 | + notice, this list of conditions and the following disclaimer. |
99 | +2. Redistributions in binary form must reproduce the copyright |
100 | + notice, this list of conditions and the following disclaimer in the |
101 | + documentation and/or other materials provided with the distribution. |
102 | +3. The name of the author may not be used to endorse or promote products |
103 | + derived from this software without specific prior written permission. |
104 | + |
105 | +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
106 | +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
107 | +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
108 | +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
109 | +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
110 | +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
111 | +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
112 | +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
113 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
114 | +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
115 | |
116 | === added file 'cmake/UseGdbusCodegen.cmake' |
117 | --- cmake/UseGdbusCodegen.cmake 1970-01-01 00:00:00 +0000 |
118 | +++ cmake/UseGdbusCodegen.cmake 2013-05-21 14:54:26 +0000 |
119 | @@ -0,0 +1,35 @@ |
120 | +cmake_minimum_required(VERSION 2.6) |
121 | +if(POLICY CMP0011) |
122 | + cmake_policy(SET CMP0011 NEW) |
123 | +endif(POLICY CMP0011) |
124 | + |
125 | +find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable") |
126 | +if(NOT GDBUS_CODEGEN) |
127 | + message(FATAL_ERROR "Excutable gdbus-codegen not found") |
128 | +endif() |
129 | + |
130 | +function(add_gdbus_codegen) |
131 | + set(_one_value OUTFILES NAME PREFIX NAMESPACE SERVICE_XML) |
132 | + set(_multi_value DEPENDS) |
133 | + cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN}) |
134 | + |
135 | + if(arg_PREFIX) |
136 | + set(PREFIX --interface-prefix ${arg_PREFIX}) |
137 | + endif() |
138 | + |
139 | + if(arg_NAMESPACE) |
140 | + set(NAMESPACE --c-namespace ${arg_NAMESPACE}) |
141 | + endif() |
142 | + |
143 | + add_custom_command( |
144 | + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.h" "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" |
145 | + COMMAND "${GDBUS_CODEGEN}" |
146 | + --generate-c-code "${arg_NAME}" |
147 | + ${PREFIX} |
148 | + ${NAMESPACE} |
149 | + "${arg_SERVICE_XML}" |
150 | + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
151 | + DEPENDS ${arg_DEPENDS} "${arg_SERVICE_XML}" |
152 | + ) |
153 | + set(${arg_OUTFILES} ${${arg_OUTFILES}} "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" PARENT_SCOPE) |
154 | +endfunction(add_gdbus_codegen) |
155 | |
156 | === added directory 'data' |
157 | === added file 'data/com.canonical.powerd.xml' |
158 | --- data/com.canonical.powerd.xml 1970-01-01 00:00:00 +0000 |
159 | +++ data/com.canonical.powerd.xml 2013-05-21 14:54:26 +0000 |
160 | @@ -0,0 +1,25 @@ |
161 | +<?xml version="1.0" encoding="UTF-8"?> |
162 | +<node name="/"> |
163 | + <interface name="com.canonical.powerd"> |
164 | + <!-- Properties --> |
165 | + |
166 | + <!-- Functions --> |
167 | + <method name="requestSysState"> |
168 | + <arg type="i" name="state" direction="in" /> |
169 | + <arg type="i" name="pid" direction="in" /> |
170 | + <arg type="u" name="cookie" direction="out" /> |
171 | + </method> |
172 | + |
173 | + <method name="clearSysState"> |
174 | + <arg type="u" name="cookie" direction="in" /> |
175 | + </method> |
176 | + |
177 | + <!-- for debug/testing --> |
178 | + <method name="listSysRequests"> |
179 | + <arg type="a(si)" name="requestList" direction="out" /> |
180 | + </method> |
181 | + |
182 | + <!-- Signals --> |
183 | + <!-- None --> |
184 | + </interface> |
185 | +</node> |
186 | |
187 | === modified file 'debian/changelog' |
188 | --- debian/changelog 2013-02-13 17:41:38 +0000 |
189 | +++ debian/changelog 2013-05-21 14:54:26 +0000 |
190 | @@ -1,3 +1,17 @@ |
191 | +powerd (0.6) raring; urgency=low |
192 | + |
193 | + [ Michael Frey ] |
194 | + * Automatically suspend the device when inactive |
195 | + |
196 | + [ Matthew Fischer ] |
197 | + * Add dbus methods for requesting system power states |
198 | + |
199 | + [ Seth Forshee ] |
200 | + * Add a low-level platform-neutral suspend library |
201 | + * Modify code internally to use system power requests |
202 | + |
203 | + -- Matthew Fischer <matthew.fischer@canonical.com> Tue, 21 May 2013 08:45:06 -0600 |
204 | + |
205 | powerd (0.5) quantal; urgency=low |
206 | |
207 | * Dim / un-dim screen on suspend / resume. |
208 | |
209 | === modified file 'debian/control' |
210 | --- debian/control 2013-02-20 15:52:29 +0000 |
211 | +++ debian/control 2013-05-21 14:54:26 +0000 |
212 | @@ -8,11 +8,12 @@ |
213 | libgudev-1.0-dev, |
214 | libhybris-dev, |
215 | libgles2-mesa-dev, |
216 | + python |
217 | Standards-Version: 3.9.3 |
218 | -Vcs-Bzr: lp:phablet-powerd |
219 | +Vcs-Bzr: lp:powerd |
220 | |
221 | Package: powerd |
222 | -Architecture: armel armhf |
223 | +Architecture: armhf |
224 | Depends: ${misc:Depends}, ${shlibs:Depends} |
225 | Description: Power daemon to monitor power button events. |
226 | This daemon provides monitoring capabilities for the ubuntu phone |
227 | |
228 | === added file 'debian/install' |
229 | --- debian/install 1970-01-01 00:00:00 +0000 |
230 | +++ debian/install 2013-05-21 14:54:26 +0000 |
231 | @@ -0,0 +1,1 @@ |
232 | +debian/powerd.conf etc/dbus-1/system.d/ |
233 | |
234 | === added file 'debian/powerd.conf' |
235 | --- debian/powerd.conf 1970-01-01 00:00:00 +0000 |
236 | +++ debian/powerd.conf 2013-05-21 14:54:26 +0000 |
237 | @@ -0,0 +1,24 @@ |
238 | +<!-- This configuration file specifies the required security policies |
239 | + for powerd daemon to work. --> |
240 | + |
241 | +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" |
242 | + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> |
243 | +<busconfig> |
244 | + |
245 | + <!-- ../system.conf have denied everything, so we just punch some holes --> |
246 | + |
247 | + <policy user="root"> |
248 | + <allow own="com.canonical.powerd"/> |
249 | + <allow send_destination="com.canonical.powerd"/> |
250 | + <allow send_interface="com.canonical.powerd"/> |
251 | + </policy> |
252 | + |
253 | + <policy at_console="true"> |
254 | + <allow send_destination="com.canonical.powerd"/> |
255 | + </policy> |
256 | + |
257 | + <policy context="default"> |
258 | + <deny send_destination="com.canonical.powerd"/> |
259 | + </policy> |
260 | + |
261 | +</busconfig> |
262 | |
263 | === modified file 'debian/upstart' |
264 | --- debian/upstart 2012-11-01 04:56:16 +0000 |
265 | +++ debian/upstart 2013-05-21 14:54:26 +0000 |
266 | @@ -24,8 +24,10 @@ |
267 | export ANDROID_ROOT=/system |
268 | export EXTERNAL_STORAGE=/mnt/sdcard |
269 | export QT_PLUGIN_PATH=/opt/qt5/plugins |
270 | - |
271 | - |
272 | +# for debugging purposes, remove when closer to shipping (mfisch) |
273 | +export G_MESSAGES_DEBUG=all |
274 | + |
275 | + |
276 | exec /usr/bin/powerd |
277 | |
278 | end script |
279 | |
280 | === added directory 'libsuspend' |
281 | === added file 'libsuspend/CMakeLists.txt' |
282 | --- libsuspend/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
283 | +++ libsuspend/CMakeLists.txt 2013-05-21 14:54:26 +0000 |
284 | @@ -0,0 +1,12 @@ |
285 | +set(CMAKE_C_FLAGS "-Wall -Werror -Wextra") |
286 | + |
287 | +add_library( |
288 | + suspend |
289 | + |
290 | + libsuspend.c |
291 | + sysfs.c |
292 | + autosleep.c |
293 | + earlysuspend.c |
294 | + legacy.c |
295 | + mocksuspend.c |
296 | +) |
297 | |
298 | === added file 'libsuspend/autosleep.c' |
299 | --- libsuspend/autosleep.c 1970-01-01 00:00:00 +0000 |
300 | +++ libsuspend/autosleep.c 2013-05-21 14:54:26 +0000 |
301 | @@ -0,0 +1,49 @@ |
302 | +/* |
303 | + * Copyright 2013 Canonical Ltd. |
304 | + * |
305 | + * This file is part of powerd. |
306 | + * |
307 | + * powerd is free software; you can redistribute it and/or modify |
308 | + * it under the terms of the GNU General Public License as published by |
309 | + * the Free Software Foundation; version 3. |
310 | + * |
311 | + * powerd is distributed in the hope that it will be useful, |
312 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
313 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
314 | + * GNU General Public License for more details. |
315 | + * |
316 | + * You should have received a copy of the GNU General Public License |
317 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
318 | + */ |
319 | + |
320 | +#include <stdio.h> |
321 | +#include "common.h" |
322 | +#include "sysfs.h" |
323 | + |
324 | +static const char autosleep_path[] = "/sys/power/autosleep"; |
325 | +static const char mem_str[] = "mem"; |
326 | +static const char off_str[] = "off"; |
327 | + |
328 | +static int autosleep_enter(void) |
329 | +{ |
330 | + int ret = sysfs_write(autosleep_path, mem_str, ARRAY_SIZE(mem_str) - 1); |
331 | + return ret < 0 ? ret : 0; |
332 | +} |
333 | + |
334 | +static int autosleep_exit(void) |
335 | +{ |
336 | + int ret = sysfs_write(autosleep_path, mem_str, ARRAY_SIZE(off_str) - 1); |
337 | + return ret < 0 ? ret : 0; |
338 | +} |
339 | + |
340 | +static const struct suspend_handler autosleep_handler = { |
341 | + .enter = autosleep_enter, |
342 | + .exit = autosleep_exit, |
343 | +}; |
344 | + |
345 | +const struct suspend_handler *autosleep_detect(void) |
346 | +{ |
347 | + if (!sysfs_file_exists(autosleep_path)) |
348 | + return NULL; |
349 | + return &autosleep_handler; |
350 | +} |
351 | |
352 | === added file 'libsuspend/common.h' |
353 | --- libsuspend/common.h 1970-01-01 00:00:00 +0000 |
354 | +++ libsuspend/common.h 2013-05-21 14:54:26 +0000 |
355 | @@ -0,0 +1,35 @@ |
356 | +/* |
357 | + * Copyright 2013 Canonical Ltd. |
358 | + * |
359 | + * This file is part of powerd. |
360 | + * |
361 | + * powerd is free software; you can redistribute it and/or modify |
362 | + * it under the terms of the GNU General Public License as published by |
363 | + * the Free Software Foundation; version 3. |
364 | + * |
365 | + * powerd is distributed in the hope that it will be useful, |
366 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
367 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
368 | + * GNU General Public License for more details. |
369 | + * |
370 | + * You should have received a copy of the GNU General Public License |
371 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
372 | + */ |
373 | + |
374 | +#ifndef SUSPENDIF_H |
375 | +#define SUSPENDIF_H |
376 | + |
377 | +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) |
378 | + |
379 | +struct suspend_handler { |
380 | + int (*prepare)(void); |
381 | + int (*enter)(void); |
382 | + int (*exit)(void); |
383 | +}; |
384 | + |
385 | +const struct suspend_handler *autosleep_detect(void); |
386 | +const struct suspend_handler *earlysuspend_detect(void); |
387 | +const struct suspend_handler *legacy_detect(void); |
388 | +const struct suspend_handler *mocksuspend_detect(void); |
389 | + |
390 | +#endif /* SUSPENDIF_H */ |
391 | |
392 | === added file 'libsuspend/earlysuspend.c' |
393 | --- libsuspend/earlysuspend.c 1970-01-01 00:00:00 +0000 |
394 | +++ libsuspend/earlysuspend.c 2013-05-21 14:54:26 +0000 |
395 | @@ -0,0 +1,55 @@ |
396 | +/* |
397 | + * Copyright 2013 Canonical Ltd. |
398 | + * |
399 | + * This file is part of powerd. |
400 | + * |
401 | + * powerd is free software; you can redistribute it and/or modify |
402 | + * it under the terms of the GNU General Public License as published by |
403 | + * the Free Software Foundation; version 3. |
404 | + * |
405 | + * powerd is distributed in the hope that it will be useful, |
406 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
407 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
408 | + * GNU General Public License for more details. |
409 | + * |
410 | + * You should have received a copy of the GNU General Public License |
411 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
412 | + */ |
413 | + |
414 | +#include <stdio.h> |
415 | +#include "common.h" |
416 | +#include "sysfs.h" |
417 | + |
418 | +static const char state_path[] = "/sys/power/state"; |
419 | +static const char wakelock_path[] = "/sys/power/wake_lock"; |
420 | +static const char autosleep_path[] = "/sys/power/autosleep"; |
421 | + |
422 | +static const char mem_str[] = "mem"; |
423 | +static const char on_str[] = "on"; |
424 | + |
425 | +static int earlysuspend_enter(void) |
426 | +{ |
427 | + int ret = sysfs_write(state_path, mem_str, ARRAY_SIZE(mem_str) - 1); |
428 | + return ret < 0 ? ret : 0; |
429 | +} |
430 | + |
431 | +static int earlysuspend_exit(void) |
432 | +{ |
433 | + int ret = sysfs_write(state_path, on_str, ARRAY_SIZE(on_str) - 1); |
434 | + return ret < 0 ? ret : 0; |
435 | +} |
436 | + |
437 | +static const struct suspend_handler earlysuspend_handler = { |
438 | + .enter = earlysuspend_enter, |
439 | + .exit = earlysuspend_exit, |
440 | +}; |
441 | + |
442 | +const struct suspend_handler *earlysuspend_detect(void) |
443 | +{ |
444 | + if (!sysfs_file_exists(autosleep_path) && |
445 | + sysfs_file_exists(wakelock_path) && |
446 | + sysfs_file_exists(state_path)) |
447 | + return &earlysuspend_handler; |
448 | + |
449 | + return NULL; |
450 | +} |
451 | |
452 | === added file 'libsuspend/legacy.c' |
453 | --- libsuspend/legacy.c 1970-01-01 00:00:00 +0000 |
454 | +++ libsuspend/legacy.c 2013-05-21 14:54:26 +0000 |
455 | @@ -0,0 +1,82 @@ |
456 | +/* |
457 | + * Copyright 2013 Canonical Ltd. |
458 | + * |
459 | + * This file is part of powerd. |
460 | + * |
461 | + * powerd is free software; you can redistribute it and/or modify |
462 | + * it under the terms of the GNU General Public License as published by |
463 | + * the Free Software Foundation; version 3. |
464 | + * |
465 | + * powerd is distributed in the hope that it will be useful, |
466 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
467 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
468 | + * GNU General Public License for more details. |
469 | + * |
470 | + * You should have received a copy of the GNU General Public License |
471 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
472 | + */ |
473 | + |
474 | +#include <stdio.h> |
475 | +#include <string.h> |
476 | +#include "common.h" |
477 | +#include "sysfs.h" |
478 | + |
479 | +static const char state_path[] = "/sys/power/state"; |
480 | +static const char wakelock_path[] = "/sys/power/wake_lock"; |
481 | +static const char wakeup_count_path[] = "/sys/power/wakeup_count"; |
482 | +static const char mem_str[] = "mem"; |
483 | + |
484 | +#define WAKEUP_COUNT_LEN 64 |
485 | + |
486 | +static int wakeup_count_supported, wakeup_count_valid; |
487 | +static char wakeup_count[WAKEUP_COUNT_LEN]; |
488 | + |
489 | +static int legacy_prepare(void) |
490 | +{ |
491 | + int ret; |
492 | + |
493 | + if (wakeup_count_supported) { |
494 | + ret = sysfs_read(wakeup_count_path, wakeup_count, WAKEUP_COUNT_LEN); |
495 | + if (ret < 0) { |
496 | + wakeup_count_valid = 0; |
497 | + return ret; |
498 | + } |
499 | + wakeup_count_valid = 1; |
500 | + } |
501 | + |
502 | + return 0; |
503 | +} |
504 | + |
505 | +static int legacy_enter(void) |
506 | +{ |
507 | + int ret; |
508 | + |
509 | + if (wakeup_count_supported && wakeup_count_valid) { |
510 | + wakeup_count_valid = 0; |
511 | + |
512 | + ret = sysfs_write(wakeup_count_path, wakeup_count, |
513 | + strlen(wakeup_count)); |
514 | + if (ret < 0) { |
515 | + /* Wakup happened since reading wakeup_count */ |
516 | + return ret; |
517 | + } |
518 | + } |
519 | + |
520 | + ret = sysfs_write(state_path, mem_str, ARRAY_SIZE(mem_str) - 1); |
521 | + return ret < 0 ? ret : 0; |
522 | +} |
523 | + |
524 | +static const struct suspend_handler legacy_handler = { |
525 | + .prepare = legacy_prepare, |
526 | + .enter = legacy_enter, |
527 | +}; |
528 | + |
529 | +const struct suspend_handler *legacy_detect(void) |
530 | +{ |
531 | + if (sysfs_file_exists(state_path) && !sysfs_file_exists(wakelock_path)) { |
532 | + wakeup_count_supported = sysfs_file_exists(wakeup_count_path); |
533 | + return &legacy_handler; |
534 | + } |
535 | + |
536 | + return NULL; |
537 | +} |
538 | |
539 | === added file 'libsuspend/libsuspend.c' |
540 | --- libsuspend/libsuspend.c 1970-01-01 00:00:00 +0000 |
541 | +++ libsuspend/libsuspend.c 2013-05-21 14:54:26 +0000 |
542 | @@ -0,0 +1,78 @@ |
543 | +/* |
544 | + * Copyright 2013 Canonical Ltd. |
545 | + * |
546 | + * This file is part of powerd. |
547 | + * |
548 | + * powerd is free software; you can redistribute it and/or modify |
549 | + * it under the terms of the GNU General Public License as published by |
550 | + * the Free Software Foundation; version 3. |
551 | + * |
552 | + * powerd is distributed in the hope that it will be useful, |
553 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
554 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
555 | + * GNU General Public License for more details. |
556 | + * |
557 | + * You should have received a copy of the GNU General Public License |
558 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
559 | + */ |
560 | + |
561 | +#include <stdio.h> |
562 | +#include <errno.h> |
563 | +#include "libsuspend.h" |
564 | +#include "common.h" |
565 | + |
566 | +const struct suspend_handler *handler; |
567 | + |
568 | +void libsuspend_init(int force_mock) |
569 | +{ |
570 | + if (!force_mock) { |
571 | + handler = autosleep_detect(); |
572 | + if (handler) |
573 | + return; |
574 | + |
575 | + handler = earlysuspend_detect(); |
576 | + if (handler) |
577 | + return; |
578 | + |
579 | + handler = legacy_detect(); |
580 | + if (handler) |
581 | + return; |
582 | + |
583 | + printf("No suspend interface detected, using mock suspend\n"); |
584 | + } |
585 | + |
586 | + handler = mocksuspend_detect(); |
587 | +} |
588 | + |
589 | +int libsuspend_prepare_suspend(void) |
590 | +{ |
591 | + if (!handler) |
592 | + return -ENODEV; |
593 | + |
594 | + if (handler->prepare) |
595 | + return handler->prepare(); |
596 | + |
597 | + return 0; |
598 | +} |
599 | + |
600 | +int libsuspend_enter_suspend(void) |
601 | +{ |
602 | + if (!handler) |
603 | + return -ENODEV; |
604 | + |
605 | + if (handler->enter) |
606 | + return handler->enter(); |
607 | + |
608 | + return 0; |
609 | +} |
610 | + |
611 | +int libsuspend_exit_suspend(void) |
612 | +{ |
613 | + if (!handler) |
614 | + return -ENODEV; |
615 | + |
616 | + if (handler->exit) |
617 | + return handler->exit(); |
618 | + |
619 | + return 0; |
620 | +} |
621 | |
622 | === added file 'libsuspend/libsuspend.h' |
623 | --- libsuspend/libsuspend.h 1970-01-01 00:00:00 +0000 |
624 | +++ libsuspend/libsuspend.h 2013-05-21 14:54:26 +0000 |
625 | @@ -0,0 +1,35 @@ |
626 | +/* |
627 | + * Copyright 2013 Canonical Ltd. |
628 | + * |
629 | + * This file is part of powerd. |
630 | + * |
631 | + * powerd is free software; you can redistribute it and/or modify |
632 | + * it under the terms of the GNU General Public License as published by |
633 | + * the Free Software Foundation; version 3. |
634 | + * |
635 | + * powerd is distributed in the hope that it will be useful, |
636 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
637 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
638 | + * GNU General Public License for more details. |
639 | + * |
640 | + * You should have received a copy of the GNU General Public License |
641 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
642 | + */ |
643 | + |
644 | +#ifndef LIBSUSPEND_H |
645 | +#define LIBSUSPEND_H |
646 | + |
647 | +#ifdef __cplusplus |
648 | +extern "C" { |
649 | +#endif |
650 | + |
651 | +void libsuspend_init(int force_mock); |
652 | +int libsuspend_prepare_suspend(void); |
653 | +int libsuspend_enter_suspend(void); |
654 | +int libsuspend_exit_suspend(void); |
655 | + |
656 | +#ifdef __cplusplus |
657 | +} |
658 | +#endif |
659 | + |
660 | +#endif /* LIBSUSPEND_H */ |
661 | |
662 | === added file 'libsuspend/mocksuspend.c' |
663 | --- libsuspend/mocksuspend.c 1970-01-01 00:00:00 +0000 |
664 | +++ libsuspend/mocksuspend.c 2013-05-21 14:54:26 +0000 |
665 | @@ -0,0 +1,49 @@ |
666 | +/* |
667 | + * Copyright 2013 Canonical Ltd. |
668 | + * |
669 | + * This file is part of powerd. |
670 | + * |
671 | + * powerd is free software; you can redistribute it and/or modify |
672 | + * it under the terms of the GNU General Public License as published by |
673 | + * the Free Software Foundation; version 3. |
674 | + * |
675 | + * powerd is distributed in the hope that it will be useful, |
676 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
677 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
678 | + * GNU General Public License for more details. |
679 | + * |
680 | + * You should have received a copy of the GNU General Public License |
681 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
682 | + */ |
683 | + |
684 | +#include <stdio.h> |
685 | +#include "common.h" |
686 | + |
687 | +static int mocksuspend_prepare(void) |
688 | +{ |
689 | + printf("mocksuspend prepare\n"); |
690 | + return 0; |
691 | +} |
692 | + |
693 | +static int mocksuspend_enter(void) |
694 | +{ |
695 | + printf("mocksuspend enter\n"); |
696 | + return 0; |
697 | +} |
698 | + |
699 | +static int mocksuspend_exit(void) |
700 | +{ |
701 | + printf("mocksuspend exit\n"); |
702 | + return 0; |
703 | +} |
704 | + |
705 | +static const struct suspend_handler mocksuspend_handler = { |
706 | + .prepare = mocksuspend_prepare, |
707 | + .enter = mocksuspend_enter, |
708 | + .exit = mocksuspend_exit, |
709 | +}; |
710 | + |
711 | +const struct suspend_handler *mocksuspend_detect(void) |
712 | +{ |
713 | + return &mocksuspend_handler; |
714 | +} |
715 | |
716 | === added file 'libsuspend/sysfs.c' |
717 | --- libsuspend/sysfs.c 1970-01-01 00:00:00 +0000 |
718 | +++ libsuspend/sysfs.c 2013-05-21 14:54:26 +0000 |
719 | @@ -0,0 +1,62 @@ |
720 | +/* |
721 | + * Copyright 2013 Canonical Ltd. |
722 | + * |
723 | + * This file is part of powerd. |
724 | + * |
725 | + * powerd is free software; you can redistribute it and/or modify |
726 | + * it under the terms of the GNU General Public License as published by |
727 | + * the Free Software Foundation; version 3. |
728 | + * |
729 | + * powerd is distributed in the hope that it will be useful, |
730 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
731 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
732 | + * GNU General Public License for more details. |
733 | + * |
734 | + * You should have received a copy of the GNU General Public License |
735 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
736 | + */ |
737 | + |
738 | +#include <sys/types.h> |
739 | +#include <sys/stat.h> |
740 | +#include <fcntl.h> |
741 | +#include <unistd.h> |
742 | +#include <errno.h> |
743 | + |
744 | +int sysfs_file_exists(const char *path) |
745 | +{ |
746 | + return !access(path, F_OK); |
747 | +} |
748 | + |
749 | +int sysfs_read(const char *path, void *buf, int len) |
750 | +{ |
751 | + int fd; |
752 | + ssize_t ret; |
753 | + |
754 | + fd = open(path, O_RDONLY); |
755 | + if (fd == -1) |
756 | + return -errno; |
757 | + |
758 | + ret = read(fd, buf, len); |
759 | + if (ret == -1) |
760 | + ret = -errno; |
761 | + |
762 | + close(fd); |
763 | + return ret; |
764 | +} |
765 | + |
766 | +int sysfs_write(const char *path, const void *buf, int len) |
767 | +{ |
768 | + int fd; |
769 | + ssize_t ret; |
770 | + |
771 | + fd = open(path, O_WRONLY); |
772 | + if (fd == -1) |
773 | + return -errno; |
774 | + |
775 | + ret = write(fd, buf, len); |
776 | + if (ret == -1) |
777 | + ret = -errno; |
778 | + |
779 | + close(fd); |
780 | + return ret; |
781 | +} |
782 | |
783 | === added file 'libsuspend/sysfs.h' |
784 | --- libsuspend/sysfs.h 1970-01-01 00:00:00 +0000 |
785 | +++ libsuspend/sysfs.h 2013-05-21 14:54:26 +0000 |
786 | @@ -0,0 +1,26 @@ |
787 | +/* |
788 | + * Copyright 2013 Canonical Ltd. |
789 | + * |
790 | + * This file is part of powerd. |
791 | + * |
792 | + * powerd is free software; you can redistribute it and/or modify |
793 | + * it under the terms of the GNU General Public License as published by |
794 | + * the Free Software Foundation; version 3. |
795 | + * |
796 | + * powerd is distributed in the hope that it will be useful, |
797 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
798 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
799 | + * GNU General Public License for more details. |
800 | + * |
801 | + * You should have received a copy of the GNU General Public License |
802 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
803 | + */ |
804 | + |
805 | +#ifndef SYSFS_H |
806 | +#define SYSFS_H |
807 | + |
808 | +int sysfs_file_exists(const char *path); |
809 | +int sysfs_read(const char *path, void *buf, int len); |
810 | +int sysfs_write(const char *path, const void *buf, int len); |
811 | + |
812 | +#endif /* SYSFS_H */ |
813 | |
814 | === added file 'src/CMakeLists.txt' |
815 | --- src/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
816 | +++ src/CMakeLists.txt 2013-05-21 14:54:26 +0000 |
817 | @@ -0,0 +1,18 @@ |
818 | +include(UseGdbusCodegen) |
819 | +include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
820 | + |
821 | +set(GDBUS_NAME powerd-dbus) |
822 | + |
823 | +set(POWERD_GENERATED_SOURCES |
824 | + ${GDBUS_NAME}.c |
825 | +) |
826 | +set(POWERD_GENERATED_HEADERS |
827 | + ${GDBUS_NAME}.h |
828 | +) |
829 | + |
830 | +add_gdbus_codegen( |
831 | + OUTFILES POWERD_GENERATED_SOURCES |
832 | + NAME ${GDBUS_NAME} |
833 | + SERVICE_XML ${CMAKE_CURRENT_SOURCE_DIR}/../data/com.canonical.powerd.xml |
834 | +) |
835 | +ADD_CUSTOM_TARGET(dbus_bindings DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${POWERD_GENERATED_SOURCES}) |
836 | |
837 | === added file 'src/power-request.c' |
838 | --- src/power-request.c 1970-01-01 00:00:00 +0000 |
839 | +++ src/power-request.c 2013-05-21 14:54:26 +0000 |
840 | @@ -0,0 +1,446 @@ |
841 | +/* |
842 | + * Copyright 2013 Canonical Ltd. |
843 | + * |
844 | + * This file is part of powerd. |
845 | + * |
846 | + * powerd is free software; you can redistribute it and/or modify |
847 | + * it under the terms of the GNU General Public License as published by |
848 | + * the Free Software Foundation; version 3. |
849 | + * |
850 | + * powerd is distributed in the hope that it will be useful, |
851 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
852 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
853 | + * GNU General Public License for more details. |
854 | + * |
855 | + * You should have received a copy of the GNU General Public License |
856 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
857 | + */ |
858 | + |
859 | +#include <glib.h> |
860 | + |
861 | +#include <stddef.h> |
862 | +#include <stdio.h> |
863 | +#include <stdlib.h> |
864 | +#include <unistd.h> |
865 | +#include <fcntl.h> |
866 | +#include <errno.h> |
867 | +#include <string.h> |
868 | + |
869 | +#include <glib-object.h> |
870 | +#include <gio/gio.h> |
871 | +#include "powerd-internal.h" |
872 | +#include "powerd-dbus.h" |
873 | + |
874 | +#include "libsuspend.h" |
875 | + |
876 | +struct SysStateRequest { |
877 | + GString *owner; |
878 | + int pid; /* uint? left as int so we can use -1 for implying that |
879 | + the request comes from no app specifically */ |
880 | + enum SysPowerStates state; |
881 | + uint cookie; |
882 | +}; |
883 | + |
884 | +/* Current system power state */ |
885 | +static enum SysPowerStates current_system_state = POWERD_SYS_STATE_ACTIVE; |
886 | + |
887 | +/* |
888 | + * Lists for system power state requests, with one list for each power |
889 | + * level. Requests for the suspend state are not allowed, so the actual |
890 | + * number of lists is POWERD_NUM_POWER_STATES - 1. |
891 | + */ |
892 | +static GSList *sys_state_requests[POWERD_NUM_POWER_STATES - 1]; |
893 | + |
894 | +#define INVALID_STATE -1 |
895 | +static GQueue queued_state_changes; |
896 | +static enum SysPowerStates pending_system_state = INVALID_STATE; |
897 | + |
898 | +/* |
899 | + * Monotonically increasing value for use in generating unique cookies |
900 | + * for power state requests. |
901 | + * |
902 | + * XXX: Consider whether we might need something more random (i.e. not |
903 | + * guessable) for security purposes. |
904 | + */ |
905 | +static guint power_requeust_next_cookie; |
906 | + |
907 | +/* simple helper for debugging */ |
908 | +const gchar * |
909 | +state_to_string(int state) |
910 | +{ |
911 | + switch (state) { |
912 | + case POWERD_SYS_STATE_ACTIVE: return "ACTIVE"; |
913 | + case POWERD_SYS_STATE_SUSPEND: return "SUSPEND"; |
914 | + default: return "UNKNOWN"; |
915 | + } |
916 | +} |
917 | + |
918 | +/* Returns TRUE if the state request is valid, FALSE otherwise. |
919 | + * Nobody can request the SUSPEND state. */ |
920 | +static gboolean |
921 | +is_valid_state_request(int state) |
922 | +{ |
923 | + return state > POWERD_SYS_STATE_SUSPEND && state < POWERD_NUM_POWER_STATES; |
924 | +} |
925 | + |
926 | +static GSList ** |
927 | +sys_request_list(int state) |
928 | +{ |
929 | + if (!is_valid_state_request(state)) |
930 | + return NULL; |
931 | + return &sys_state_requests[state - 1]; |
932 | +} |
933 | + |
934 | +/* internal callers should pass in NULL for the builder, its only used |
935 | + * by dbus callers. Returns TRUE if there are any elements in any list, |
936 | + * FALSE otherwise. */ |
937 | +static gboolean |
938 | +list_sys_requests_internal(GVariantBuilder *builder) |
939 | +{ |
940 | + gboolean ret = FALSE; |
941 | + GSList **list, *iterator = NULL; |
942 | + int i; |
943 | + |
944 | + for (i = POWERD_SYS_STATE_SUSPEND + 1; i < POWERD_NUM_POWER_STATES; i++) { |
945 | + list = sys_request_list(i); |
946 | + |
947 | + g_message("Requests for %s state:", state_to_string(i)); |
948 | + if (*list == NULL) { |
949 | + g_message(" no requests active"); |
950 | + } |
951 | + else { |
952 | + for (iterator = *list; iterator; iterator = iterator->next) { |
953 | + struct SysStateRequest *sr = (struct SysStateRequest *)iterator->data; |
954 | + // XXX - we should probably not dump the cookie here, it's a |
955 | + // security risk |
956 | + g_message(" Owner: %s, Pid: %d, Cookie: %u", |
957 | + sr->owner->str, sr->pid, sr->cookie); |
958 | + ret = TRUE; |
959 | + if (builder) { |
960 | + g_variant_builder_add(builder, "(si)", sr->owner->str, sr->pid); |
961 | + } |
962 | + } |
963 | + } |
964 | + } |
965 | + return ret; |
966 | +} |
967 | + |
968 | +/* Dump the requests to stdout and return the list via dbus */ |
969 | +gboolean |
970 | +handle_list_sys_requests(PowerdSource *obj, GDBusMethodInvocation *invocation) |
971 | +{ |
972 | + GVariant *list, *tuple = NULL; |
973 | + GVariantBuilder *builder; |
974 | + gboolean ret; |
975 | + |
976 | + // XXX - fix me, we should be returning an empty list when there are |
977 | + // no elements |
978 | + builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); |
979 | + ret = list_sys_requests_internal(builder); |
980 | + if (ret) { |
981 | + list = g_variant_builder_end(builder); |
982 | + // XXX - is a tuple with the first element as a list correct here? seems odd |
983 | + tuple = g_variant_new_tuple(&list,1); |
984 | + g_dbus_method_invocation_return_value(invocation, tuple); |
985 | + } |
986 | + else { |
987 | + g_dbus_method_invocation_return_value(invocation, NULL); |
988 | + } |
989 | + return TRUE; |
990 | +} |
991 | + |
992 | +static gint |
993 | +find_request_by_cookie(gconstpointer a, gconstpointer b) { |
994 | + struct SysStateRequest *sr_a = (struct SysStateRequest *)a; |
995 | + struct SysStateRequest *sr_b = (struct SysStateRequest *)b; |
996 | + return (sr_a->cookie == sr_b->cookie) ? 0 : 1; |
997 | +} |
998 | + |
999 | +/* Note: invocation is NULL for internal usage */ |
1000 | +gboolean |
1001 | +request_sys_state_internal(GDBusMethodInvocation *invocation, int state, int pid, uint *cookie) |
1002 | +{ |
1003 | + GSList **list, *item = NULL; |
1004 | + struct SysStateRequest *sr = NULL; |
1005 | + |
1006 | + if (cookie == NULL) { |
1007 | + g_error("you need to pass in memory for a cookie"); |
1008 | + return FALSE; |
1009 | + } |
1010 | + |
1011 | + if (!is_valid_state_request(state)) |
1012 | + { |
1013 | + g_warning("invalid state requested: %d",state); |
1014 | + if (invocation) { |
1015 | + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, |
1016 | + G_DBUS_ERROR_INVALID_ARGS,"Invalid state requested %d",state); |
1017 | + } |
1018 | + return FALSE; |
1019 | + } |
1020 | + |
1021 | + list = sys_request_list(state); |
1022 | + if (!list) { |
1023 | + /* Should never hit this code since we've already verified that |
1024 | + * the state is valid */ |
1025 | + g_error("Could not get request list for state %d (%s)", state, |
1026 | + state_to_string(state)); |
1027 | + if (invocation) { |
1028 | + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, |
1029 | + G_DBUS_ERROR_INVALID_ARGS, "Invalid state requested %d",state); |
1030 | + } |
1031 | + return FALSE; |
1032 | + } |
1033 | + |
1034 | + sr = g_new(struct SysStateRequest, 1); |
1035 | + sr->state = (enum SysPowerStates)state; |
1036 | + sr->pid = pid; |
1037 | + if (invocation) { |
1038 | + sr->owner = g_string_new(g_dbus_method_invocation_get_sender(invocation)); |
1039 | + } |
1040 | + else { |
1041 | + sr->owner = g_string_new("internal"); |
1042 | + } |
1043 | + |
1044 | + // The request is valid at this point, create a cookie and insert into list |
1045 | + *cookie = g_atomic_int_add(&power_requeust_next_cookie, 1); |
1046 | + sr->cookie = *cookie; |
1047 | + *list = g_slist_append(*list, sr); |
1048 | + update_system_state(); |
1049 | + return TRUE; |
1050 | +} |
1051 | + |
1052 | +gboolean |
1053 | +handle_request_sys_state (PowerdSource *obj, GDBusMethodInvocation *invocation, int state, int pid) |
1054 | +{ |
1055 | + gboolean retval = FALSE; |
1056 | + GVariant *gvCookie, *ret = NULL; |
1057 | + guint cookie; |
1058 | + |
1059 | + g_debug("handle_requestSysState from %s: %d - %s (%d)", |
1060 | + g_dbus_method_invocation_get_sender(invocation), pid, |
1061 | + state_to_string(state), state); |
1062 | + |
1063 | + retval = request_sys_state_internal(invocation, state, pid, &cookie); |
1064 | + if (retval == TRUE) { |
1065 | + gvCookie = g_variant_new_uint32(cookie); |
1066 | + ret = g_variant_new_tuple(&gvCookie,1); |
1067 | + g_debug("handle_requestSysState - SUCCESS"); |
1068 | + g_dbus_method_invocation_return_value(invocation, ret); |
1069 | + } |
1070 | + return retval; |
1071 | +} |
1072 | + |
1073 | +gboolean |
1074 | +clear_sys_state_internal(GDBusMethodInvocation *invocation, uint cookie) |
1075 | +{ |
1076 | + struct SysStateRequest *tmpsr = NULL; |
1077 | + GSList **list, *matched_requests = NULL; |
1078 | + int i; |
1079 | + |
1080 | + tmpsr = g_new(struct SysStateRequest, 1); |
1081 | + tmpsr->cookie = cookie; |
1082 | + |
1083 | + for (i = POWERD_SYS_STATE_SUSPEND + 1; i < POWERD_NUM_POWER_STATES; i++) { |
1084 | + list = sys_request_list(i); |
1085 | + if (!list) |
1086 | + continue; |
1087 | + |
1088 | + matched_requests = g_slist_find_custom(*list, tmpsr, find_request_by_cookie); |
1089 | + |
1090 | + if (matched_requests) |
1091 | + break; |
1092 | + } |
1093 | + g_free(tmpsr); |
1094 | + |
1095 | + if (matched_requests == NULL) |
1096 | + { |
1097 | + g_warning("request (%u) not found", cookie); |
1098 | + if (invocation) |
1099 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, |
1100 | + "No request with cookie: %u", cookie); |
1101 | + return FALSE; |
1102 | + } |
1103 | + |
1104 | + for ( ; matched_requests; matched_requests = matched_requests->next) { |
1105 | + struct SysStateRequest *sr = (struct SysStateRequest *)matched_requests->data; |
1106 | + g_debug("removing an element: %u",sr->cookie); |
1107 | + *list = g_slist_remove_all(*list, sr); |
1108 | + } |
1109 | + |
1110 | + g_slist_free_full(matched_requests, sys_state_request_destroy); |
1111 | + update_system_state(); |
1112 | + return TRUE; |
1113 | +} |
1114 | + |
1115 | +gboolean |
1116 | +handle_clear_sys_state (PowerdSource *obj, GDBusMethodInvocation *invocation, uint cookie) |
1117 | +{ |
1118 | + gboolean retval = FALSE; |
1119 | + g_debug("handle_clearSysState from %s, cookie: %u", |
1120 | + g_dbus_method_invocation_get_sender(invocation), cookie); |
1121 | + |
1122 | + retval = clear_sys_state_internal(invocation, cookie); |
1123 | + if (retval == TRUE) { |
1124 | + g_dbus_method_invocation_return_value(invocation, NULL); |
1125 | + } |
1126 | + return retval; |
1127 | +} |
1128 | + |
1129 | +gboolean any_active_sys_state_requests(void) |
1130 | +{ |
1131 | + GSList **list = sys_request_list(POWERD_SYS_STATE_ACTIVE); |
1132 | + if (list && *list) |
1133 | + return TRUE; |
1134 | + return FALSE; |
1135 | +} |
1136 | + |
1137 | +static enum SysPowerStates max_requested_state(void) |
1138 | +{ |
1139 | + int i; |
1140 | + GSList **list; |
1141 | + |
1142 | + for (i = POWERD_NUM_POWER_STATES - 1; i > POWERD_SYS_STATE_SUSPEND; i--) { |
1143 | + list = sys_request_list(i); |
1144 | + if (list && *list) |
1145 | + return i; |
1146 | + }; |
1147 | + |
1148 | + return POWERD_SYS_STATE_SUSPEND; |
1149 | +} |
1150 | + |
1151 | +static void check_queued_state_changes(void) |
1152 | +{ |
1153 | + enum SysPowerStates new_state; |
1154 | + int ret; |
1155 | + |
1156 | + /* |
1157 | + * If state change in progress we'll process the next queued state |
1158 | + * change when finished. |
1159 | + */ |
1160 | + if (pending_system_state != INVALID_STATE) { |
1161 | + g_debug("state change in progress, delaying"); |
1162 | + return; |
1163 | + } |
1164 | + |
1165 | + if (g_queue_is_empty(&queued_state_changes)) { |
1166 | + g_debug("no pending state changes"); |
1167 | + return; |
1168 | + } |
1169 | + |
1170 | + pending_system_state = (enum SysPowerStates)g_queue_pop_head(&queued_state_changes); |
1171 | + if (pending_system_state == current_system_state) { |
1172 | + g_debug("pending state == current state, discarding"); |
1173 | + pending_system_state = INVALID_STATE; |
1174 | + return; |
1175 | + } |
1176 | + |
1177 | + /* |
1178 | + * XXX: This code needs to be split up. Here's what it needs to do: |
1179 | + * |
1180 | + * 1. If going to suspend, possibly delay a few seconds to see if |
1181 | + * any new active requests come in. If so, abort the suspend |
1182 | + * transition. |
1183 | + * 2. Send out the signal to prepare for the state change. |
1184 | + * 3. Wait for acks or the timeout period to elapse. |
1185 | + * 4. Complete the state transition. If going to suspend, check to |
1186 | + * be sure that there's not a queued request to transition to a |
1187 | + * higher state, and if not tell the kernel to suspend. |
1188 | + */ |
1189 | + if (current_system_state == POWERD_SYS_STATE_SUSPEND) { |
1190 | + g_debug("exiting suspend"); |
1191 | + ret = libsuspend_exit_suspend(); |
1192 | + if (ret) |
1193 | + g_warning("Failed to exit suspend: %d\n", ret); |
1194 | + } else if (pending_system_state == POWERD_SYS_STATE_SUSPEND && |
1195 | + g_queue_is_empty(&queued_state_changes)) { |
1196 | + g_debug("entering suspend"); |
1197 | + ret = libsuspend_prepare_suspend(); |
1198 | + if (ret) |
1199 | + g_warning("Failed to prepare for suspend: %d\n", ret); |
1200 | + /* XXX: Here is where notifications should be sent out */ |
1201 | + ret = libsuspend_enter_suspend(); |
1202 | + if (ret) |
1203 | + g_warning("Failed to enter suspend: %d\n", ret); |
1204 | + } |
1205 | + |
1206 | + current_system_state = pending_system_state; |
1207 | + pending_system_state = INVALID_STATE; |
1208 | +} |
1209 | + |
1210 | +/* |
1211 | + * XXX: Currently the coalescing is very simplistic and may need |
1212 | + * improvement. |
1213 | + */ |
1214 | +static void enqueue_state_change(enum SysPowerStates state) |
1215 | +{ |
1216 | + gboolean queue_empty; |
1217 | + |
1218 | + g_debug("Enqueue state change to %s", state_to_string(state)); |
1219 | + |
1220 | + /* |
1221 | + * If the new request is the same as the one we're currently |
1222 | + * processing we can drop all pending requests (including the |
1223 | + * new one). |
1224 | + */ |
1225 | + if (pending_system_state == state) { |
1226 | + g_debug("State == pending state, discarding"); |
1227 | + g_queue_clear(&queued_state_changes); |
1228 | + return; |
1229 | + } else if (pending_system_state == INVALID_STATE) { |
1230 | + queue_empty = g_queue_is_empty(&queued_state_changes); |
1231 | + |
1232 | + /* |
1233 | + * If no state changes are pending or in progress and the |
1234 | + * requested state is the same as the current state, do nothing. |
1235 | + */ |
1236 | + if (queue_empty && state == current_system_state) { |
1237 | + g_debug("queue empty && state == current, discarding"); |
1238 | + return; |
1239 | + } |
1240 | + |
1241 | + /* |
1242 | + * If we aren't processing a request and the current request is |
1243 | + * the same as the next reques in the queue, all intermediate |
1244 | + * requests can be dropped. We do this by clearing the queue and |
1245 | + * then adding in the new request. |
1246 | + * |
1247 | + * XXX: This situation is probably impossible currently. |
1248 | + */ |
1249 | + if (!queue_empty && |
1250 | + (enum SysPowerStates)g_queue_peek_tail(&queued_state_changes) == state) { |
1251 | + g_debug("new state == next queued state, discarding all intermediate requests"); |
1252 | + g_queue_clear(&queued_state_changes); |
1253 | + } |
1254 | + } |
1255 | + |
1256 | + g_queue_push_tail(&queued_state_changes, (gpointer)state); |
1257 | + check_queued_state_changes(); |
1258 | +} |
1259 | + |
1260 | +void update_system_state(void) |
1261 | +{ |
1262 | + enqueue_state_change(max_requested_state()); |
1263 | +} |
1264 | + |
1265 | +void power_request_init(void) |
1266 | +{ |
1267 | + g_queue_init(&queued_state_changes); |
1268 | +} |
1269 | + |
1270 | +// Destructor for the state request object |
1271 | +void sys_state_request_destroy(gpointer data) |
1272 | +{ |
1273 | + struct SysStateRequest *sr = (struct SysStateRequest *)data; |
1274 | + if (sr->owner) { |
1275 | + g_free(sr->owner); |
1276 | + sr->owner = NULL; |
1277 | + } |
1278 | +} |
1279 | + |
1280 | +void power_request_deinit(void) |
1281 | +{ |
1282 | + int i; |
1283 | + for (i = POWERD_SYS_STATE_SUSPEND + 1; i < POWERD_NUM_POWER_STATES; i++) |
1284 | + g_slist_free_full(sys_state_requests[i-1], sys_state_request_destroy); |
1285 | + g_queue_clear(&queued_state_changes); |
1286 | +} |
1287 | |
1288 | === added file 'src/powerd-internal.h' |
1289 | --- src/powerd-internal.h 1970-01-01 00:00:00 +0000 |
1290 | +++ src/powerd-internal.h 2013-05-21 14:54:26 +0000 |
1291 | @@ -0,0 +1,63 @@ |
1292 | +/* |
1293 | + * Copyright 2013 Canonical Ltd. |
1294 | + * |
1295 | + * This file is part of powerd. |
1296 | + * |
1297 | + * powerd is free software; you can redistribute it and/or modify |
1298 | + * it under the terms of the GNU General Public License as published by |
1299 | + * the Free Software Foundation; version 3. |
1300 | + * |
1301 | + * powerd is distributed in the hope that it will be useful, |
1302 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1303 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1304 | + * GNU General Public License for more details. |
1305 | + * |
1306 | + * You should have received a copy of the GNU General Public License |
1307 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1308 | + */ |
1309 | + |
1310 | +#ifndef __POWERD_INTERNAL_H__ |
1311 | +#define __POWERD_INTERNAL_H__ |
1312 | + |
1313 | +#include "powerd-object.h" |
1314 | +#include "powerd.h" |
1315 | + |
1316 | +#ifdef __cplusplus |
1317 | +extern "C" { |
1318 | +#endif |
1319 | + |
1320 | +void powerd_exit(void); |
1321 | + |
1322 | +/* System power state requests */ |
1323 | +gboolean handle_list_sys_requests(PowerdSource *obj, |
1324 | + GDBusMethodInvocation *invocation); |
1325 | +gboolean handle_request_sys_state(PowerdSource *obj, |
1326 | + GDBusMethodInvocation *invocation, |
1327 | + int state, int pid); |
1328 | +gboolean handle_clear_sys_state(PowerdSource *obj, |
1329 | + GDBusMethodInvocation *invocation, |
1330 | + uint cookie); |
1331 | +gboolean request_sys_state_internal(GDBusMethodInvocation *invocation, |
1332 | + int state, int pid, uint *cookie); |
1333 | +gboolean clear_sys_state_internal(GDBusMethodInvocation *invocation, |
1334 | + uint cookie); |
1335 | +gboolean any_active_sys_state_requests(void); |
1336 | +void update_system_state(void); |
1337 | +void power_request_init(void); |
1338 | +void power_request_deinit(void); |
1339 | +void sys_state_request_destroy(gpointer data); |
1340 | +const gchar * state_to_string(int state); |
1341 | + |
1342 | +/* dbus callbacks */ |
1343 | +void powerd_bus_acquired_cb(GDBusConnection *connection, const gchar *name, |
1344 | + gpointer user_data); |
1345 | +void powerd_name_acquired_cb(GDBusConnection *connection, const gchar *name, |
1346 | + gpointer user_data); |
1347 | +void powerd_name_lost_cb(GDBusConnection *connection, const gchar *name, |
1348 | + gpointer user_data); |
1349 | + |
1350 | +#ifdef __cplusplus |
1351 | +} |
1352 | +#endif |
1353 | + |
1354 | +#endif |
1355 | |
1356 | === added file 'src/powerd-object.c' |
1357 | --- src/powerd-object.c 1970-01-01 00:00:00 +0000 |
1358 | +++ src/powerd-object.c 2013-05-21 14:54:26 +0000 |
1359 | @@ -0,0 +1,125 @@ |
1360 | +/* |
1361 | + * Copyright 2013 Canonical Ltd. |
1362 | + * |
1363 | + * This file is part of powerd. |
1364 | + * |
1365 | + * powerd is free software; you can redistribute it and/or modify |
1366 | + * it under the terms of the GNU General Public License as published by |
1367 | + * the Free Software Foundation; version 3. |
1368 | + * |
1369 | + * powerd is distributed in the hope that it will be useful, |
1370 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1371 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1372 | + * GNU General Public License for more details. |
1373 | + * |
1374 | + * You should have received a copy of the GNU General Public License |
1375 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1376 | + */ |
1377 | + |
1378 | +#include <glib.h> |
1379 | +#include <glib-object.h> |
1380 | +#include <gio/gio.h> |
1381 | +#include "powerd-internal.h" |
1382 | +#include "powerd-dbus.h" |
1383 | + |
1384 | +struct _PowerdSourcePrivate { |
1385 | + GDBusConnection * system_bus; |
1386 | + const gchar * path; |
1387 | + ComCanonicalPowerd * skel; |
1388 | +}; |
1389 | + |
1390 | +static void powerd_source_class_init (PowerdSourceClass * klass); |
1391 | +static void powerd_source_init (PowerdSource * self); |
1392 | +static void powerd_source_dispose (GObject * object); |
1393 | +static void powerd_source_finalize (GObject * object); |
1394 | + |
1395 | +G_DEFINE_TYPE (PowerdSource, powerd_source, G_TYPE_OBJECT); |
1396 | + |
1397 | +#define POWERD_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POWERD_TYPE_SOURCE, PowerdSourcePrivate)) |
1398 | + |
1399 | +/* Instance */ |
1400 | +static void |
1401 | +powerd_source_init (PowerdSource *self) |
1402 | +{ |
1403 | + self->priv = POWERD_SOURCE_GET_PRIVATE(self); |
1404 | + self->priv->system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); |
1405 | + return; |
1406 | +} |
1407 | + |
1408 | +/* Class Init */ |
1409 | +static void |
1410 | +powerd_source_class_init (PowerdSourceClass *self) |
1411 | +{ |
1412 | + GObjectClass *object_class = G_OBJECT_CLASS (self); |
1413 | + g_type_class_add_private (self, sizeof (PowerdSourcePrivate)); |
1414 | + object_class->dispose = powerd_source_dispose; |
1415 | + object_class->finalize = powerd_source_finalize; |
1416 | + return; |
1417 | +} |
1418 | + |
1419 | +/* Clean up references */ |
1420 | +static void |
1421 | +powerd_source_dispose (GObject *object) |
1422 | +{ |
1423 | + PowerdSource * self = POWERD_SOURCE(object); |
1424 | + if (self->priv->skel != NULL) { |
1425 | + g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(self->priv->skel)); |
1426 | + g_clear_object(&self->priv->skel); |
1427 | + } |
1428 | + g_clear_object(&self->priv->system_bus); |
1429 | + return; |
1430 | +} |
1431 | + |
1432 | +/* Free memory */ |
1433 | +static void |
1434 | +powerd_source_finalize (GObject *object) |
1435 | +{ |
1436 | + return; |
1437 | +} |
1438 | + |
1439 | +void |
1440 | +powerd_bus_acquired_cb (GDBusConnection *connection, |
1441 | + const gchar *name, |
1442 | + gpointer user_data) |
1443 | +{ |
1444 | + GError *error = NULL; |
1445 | + PowerdSource *source = NULL; |
1446 | + |
1447 | + g_debug("Bus acquired (guid %s)", g_dbus_connection_get_guid (connection)); |
1448 | + source = (PowerdSource *)g_object_new(POWERD_TYPE_SOURCE, NULL); |
1449 | + source->priv->skel = com_canonical_powerd_skeleton_new(); |
1450 | + source->priv->path = "/com/canonical/powerd"; |
1451 | + |
1452 | + if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(source->priv->skel), |
1453 | + source->priv->system_bus, source->priv->path, &error)) { |
1454 | + g_error("Unable to export skeleton on path '%s': %s", source->priv->path, |
1455 | + error->message); |
1456 | + g_error_free(error); |
1457 | + error = NULL; |
1458 | + powerd_exit(); |
1459 | + } |
1460 | + |
1461 | + g_signal_connect(G_OBJECT(source->priv->skel), "handle-request-sys-state", |
1462 | + G_CALLBACK(handle_request_sys_state), source); |
1463 | + g_signal_connect(G_OBJECT(source->priv->skel), "handle-clear-sys-state", |
1464 | + G_CALLBACK(handle_clear_sys_state), source); |
1465 | + g_signal_connect(G_OBJECT(source->priv->skel), "handle-list-sys-requests", |
1466 | + G_CALLBACK(handle_list_sys_requests), source); |
1467 | +} |
1468 | + |
1469 | +void |
1470 | +powerd_name_acquired_cb (GDBusConnection *connection, |
1471 | + const gchar *name, |
1472 | + gpointer user_data) |
1473 | +{ |
1474 | + g_debug("name acquired (%s)", name); |
1475 | +} |
1476 | + |
1477 | +void |
1478 | +powerd_name_lost_cb (GDBusConnection *connection, |
1479 | + const gchar *name, |
1480 | + gpointer user_data) |
1481 | +{ |
1482 | + g_warning("name lost (%s)", name); |
1483 | + //XXX - quit here |
1484 | +} |
1485 | |
1486 | === added file 'src/powerd-object.h' |
1487 | --- src/powerd-object.h 1970-01-01 00:00:00 +0000 |
1488 | +++ src/powerd-object.h 2013-05-21 14:54:26 +0000 |
1489 | @@ -0,0 +1,60 @@ |
1490 | +/* |
1491 | + * Copyright 2013 Canonical Ltd. |
1492 | + * |
1493 | + * This file is part of powerd. |
1494 | + * |
1495 | + * powerd is free software; you can redistribute it and/or modify |
1496 | + * it under the terms of the GNU General Public License as published by |
1497 | + * the Free Software Foundation; version 3. |
1498 | + * |
1499 | + * powerd is distributed in the hope that it will be useful, |
1500 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1501 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1502 | + * GNU General Public License for more details. |
1503 | + * |
1504 | + * You should have received a copy of the GNU General Public License |
1505 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1506 | + */ |
1507 | + |
1508 | +#ifndef __POWERD_OBJECT_H__ |
1509 | +#define __POWERD_OBJECT_H__ |
1510 | + |
1511 | +#include <glib-object.h> |
1512 | + |
1513 | +#ifdef __cplusplus |
1514 | +extern "C" { |
1515 | +#endif |
1516 | + |
1517 | +G_BEGIN_DECLS |
1518 | + |
1519 | +#define POWERD_TYPE_SOURCE (powerd_source_get_type ()) |
1520 | +#define POWERD_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POWERD_TYPE_SOURCE, PowerdSource)) |
1521 | +#define POWERD_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POWERD_TYPE_SOURCE)) |
1522 | +#define POWERD_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), POWERD_TYPE_SOURCE, PowerdSourceClass)) |
1523 | +#define POWERD_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), POWERD_TYPE_SOURCE)) |
1524 | +#define POWERD_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), POWERD_TYPE_SOURCE, PowerdSourceClass)) |
1525 | + |
1526 | +struct _PowerdSourcePrivate; |
1527 | + |
1528 | +typedef struct _PowerdSource PowerdSource; |
1529 | +typedef struct _PowerdSourceClass PowerdSourceClass; |
1530 | +typedef struct _PowerdSourcePrivate PowerdSourcePrivate; |
1531 | + |
1532 | +struct _PowerdSourceClass { |
1533 | + GObjectClass parent_class; |
1534 | +}; |
1535 | + |
1536 | +struct _PowerdSource { |
1537 | + GObject parent; |
1538 | + PowerdSourcePrivate * priv; |
1539 | +}; |
1540 | + |
1541 | +GType powerd_source_get_type (void); |
1542 | + |
1543 | +G_END_DECLS |
1544 | + |
1545 | +#ifdef __cplusplus |
1546 | +} |
1547 | +#endif |
1548 | + |
1549 | +#endif |
1550 | |
1551 | === modified file 'src/powerd.cpp' |
1552 | --- src/powerd.cpp 2013-02-20 15:42:12 +0000 |
1553 | +++ src/powerd.cpp 2013-05-21 14:54:26 +0000 |
1554 | @@ -1,6 +1,11 @@ |
1555 | /* |
1556 | * Copyright 2013 Canonical Ltd. |
1557 | * |
1558 | + * Authors: |
1559 | + * Michael Frey: michael.frey@canonical.com |
1560 | + * Matthew Fischer: matthew.fischer@canonical.com |
1561 | + * Seth Forshee: seth.forshee@canonical.com |
1562 | + * |
1563 | * This file is part of powerd. |
1564 | * |
1565 | * powerd is free software; you can redistribute it and/or modify |
1566 | @@ -27,12 +32,21 @@ |
1567 | #include <fcntl.h> |
1568 | #include <errno.h> |
1569 | #include <string.h> |
1570 | +#include <sys/types.h> |
1571 | + |
1572 | +#include <glib-object.h> |
1573 | +#include <gio/gio.h> |
1574 | +#include "powerd-internal.h" |
1575 | +#include "powerd-object.h" |
1576 | +#include "powerd-dbus.h" |
1577 | |
1578 | #include <hybris/input/input_stack_compatibility_layer.h> |
1579 | #include <hybris/input/input_stack_compatibility_layer_codes_key.h> |
1580 | |
1581 | #include <hybris/surface_flinger/surface_flinger_compatibility_layer.h> |
1582 | |
1583 | +#include "libsuspend.h" |
1584 | + |
1585 | namespace |
1586 | { |
1587 | |
1588 | @@ -43,20 +57,6 @@ |
1589 | OUR_FD_COUNT |
1590 | }; |
1591 | |
1592 | -const char * const PATHS[] = { |
1593 | - "/sys/power/wake_lock", |
1594 | - "/sys/power/wake_unlock", |
1595 | - "/sys/power/state" |
1596 | -}; |
1597 | - |
1598 | -static const char *off_state = "mem"; |
1599 | -static const char *on_state = "on"; |
1600 | - |
1601 | -static bool in_suspend = false; |
1602 | -static int g_initialized = 0; |
1603 | -static int g_fds[OUR_FD_COUNT]; |
1604 | -static int g_error = 1; |
1605 | - |
1606 | static uint button_timer = 0; |
1607 | static uint activity_timer = 0; |
1608 | |
1609 | @@ -68,6 +68,8 @@ |
1610 | static gchar *brightness_path; |
1611 | |
1612 | static int ACTIVITY_TIMEOUT = 30; |
1613 | +static GMainLoop *main_loop = NULL; |
1614 | +static guint name_id; |
1615 | |
1616 | enum state { |
1617 | BUTTON_DOWN, |
1618 | @@ -77,6 +79,16 @@ |
1619 | |
1620 | static state button_state = BUTTON_UP; |
1621 | |
1622 | +enum screen_state { |
1623 | + SCREEN_OFF, |
1624 | + SCREEN_ON |
1625 | +}; |
1626 | + |
1627 | +static enum screen_state current_screen_state = SCREEN_ON; |
1628 | +static uint internal_request_cookie; |
1629 | +static bool internal_cookie_valid; |
1630 | + |
1631 | +gboolean activity_monitor(gpointer data); |
1632 | |
1633 | void get_brightness_path (void) |
1634 | { |
1635 | @@ -100,11 +112,9 @@ |
1636 | (g_strcmp0 (device_type, "platform") == 0) || |
1637 | (g_strcmp0 (device_type, "raw") == 0)) { |
1638 | brightness_path = g_strdup (g_udev_device_get_sysfs_path ((GUdevDevice *)device->data)); |
1639 | - g_print ("found: %s\n", brightness_path); |
1640 | break; |
1641 | } |
1642 | } |
1643 | - g_print ("found2: %s\n", brightness_path); |
1644 | |
1645 | g_list_foreach (devices, (GFunc) g_object_unref, NULL); |
1646 | g_list_free (devices); |
1647 | @@ -167,110 +177,103 @@ |
1648 | |
1649 | } |
1650 | |
1651 | -static int |
1652 | -open_file_descriptors(const char * const paths[]) |
1653 | -{ |
1654 | - int i; |
1655 | - for (i=0; i<OUR_FD_COUNT; i++) { |
1656 | - int fd = open(paths[i], O_RDWR); |
1657 | - if (fd < 0) { |
1658 | - fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]); |
1659 | - g_error = errno; |
1660 | - return -1; |
1661 | - } |
1662 | - g_fds[i] = fd; |
1663 | - } |
1664 | - |
1665 | - g_error = 0; |
1666 | - return 0; |
1667 | -} |
1668 | - |
1669 | -static inline void |
1670 | -initialize_fds(void) |
1671 | -{ |
1672 | - if (g_initialized == 0) { |
1673 | - if(open_file_descriptors(PATHS) < 0) { |
1674 | - on_state = "on"; |
1675 | - off_state = "mem"; |
1676 | - } |
1677 | - g_initialized = 1; |
1678 | - } |
1679 | -} |
1680 | - |
1681 | - |
1682 | gboolean call_shutdown(gpointer data) |
1683 | { |
1684 | - gchar *argv[] = {"poweroff", |
1685 | + static char poweroff_cmd[] = "poweroff"; |
1686 | + gchar *argv[] = {poweroff_cmd, |
1687 | NULL}; |
1688 | + |
1689 | if (button_state == BUTTON_DOWN) { |
1690 | button_state = SHUTDOWN; |
1691 | brightness_set_value(0); |
1692 | sf_blank(0); |
1693 | g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); |
1694 | } |
1695 | -} |
1696 | - |
1697 | -int set_screen_state(void) |
1698 | -{ |
1699 | - initialize_fds(); |
1700 | - |
1701 | - if (g_error) |
1702 | - goto failure; |
1703 | - |
1704 | - char buf[32]; |
1705 | - int len; |
1706 | - if(in_suspend) { |
1707 | - len = snprintf(buf, sizeof(buf), "%s", on_state); |
1708 | - in_suspend = false; |
1709 | - } else { |
1710 | - if (activity_timer > 0) { |
1711 | - g_source_remove(activity_timer); |
1712 | - activity_timer = 0; |
1713 | - } |
1714 | + |
1715 | +} |
1716 | + |
1717 | +void reset_activity_timer(int add) |
1718 | +{ |
1719 | + if (activity_timer > 0) { |
1720 | + g_source_remove(activity_timer); |
1721 | + activity_timer = 0; |
1722 | + } |
1723 | + if (add) |
1724 | + activity_timer = g_timeout_add_seconds(ACTIVITY_TIMEOUT, activity_monitor, NULL); |
1725 | +} |
1726 | + |
1727 | + |
1728 | +int set_screen_state(enum screen_state new_state) |
1729 | +{ |
1730 | + int ret; |
1731 | + |
1732 | + g_debug("set_screen_state: current %s (%d) new %s (%d)", |
1733 | + state_to_string(current_screen_state), current_screen_state, |
1734 | + state_to_string(new_state), new_state); |
1735 | + |
1736 | + if (current_screen_state == new_state) |
1737 | + return 0; |
1738 | + |
1739 | + switch (new_state) { |
1740 | + case SCREEN_OFF: |
1741 | + reset_activity_timer(0); |
1742 | saved_brightness = brightness_get_value(); |
1743 | brightness_set_value(0); |
1744 | sf_blank(0); |
1745 | - len = snprintf(buf, sizeof(buf), "%s", off_state); |
1746 | - in_suspend = true; |
1747 | - } |
1748 | - |
1749 | - buf[sizeof(buf) - 1] = '\0'; |
1750 | - len = write(g_fds[REQUEST_STATE], buf, len); |
1751 | - if(len < 0) { |
1752 | - failure: |
1753 | - printf("Failed setting last user activity: g_error=%d\n", g_error); |
1754 | - } |
1755 | - |
1756 | - //Need to wait for system wakeup otherwise we will get |
1757 | - //permission denied if we try to ake the screen up before that. |
1758 | - if (!in_suspend) { |
1759 | + |
1760 | + g_debug("Releasing internal active state request"); |
1761 | + ret = clear_sys_state_internal(NULL, internal_request_cookie); |
1762 | + if (!ret) |
1763 | + g_warning("Internal system state request cookie invalid: %d\n", |
1764 | + internal_request_cookie); |
1765 | + break; |
1766 | + case SCREEN_ON: |
1767 | + g_debug("Requesting active state internally"); |
1768 | + ret = request_sys_state_internal(NULL, POWERD_SYS_STATE_ACTIVE, |
1769 | + getpid(), &internal_request_cookie); |
1770 | + if (!ret) |
1771 | + g_warning("Request for active state failed"); |
1772 | + |
1773 | + /* Need to wait for system wakeup before waking screen */ |
1774 | sleep(1); |
1775 | sf_unblank(0); |
1776 | brightness_set_value(saved_brightness); |
1777 | + |
1778 | + activity_timer = g_timeout_add_seconds(ACTIVITY_TIMEOUT, activity_monitor, NULL); |
1779 | + break; |
1780 | + default: |
1781 | + g_warning("Invalid screen state %d", new_state); |
1782 | + return -1; |
1783 | } |
1784 | |
1785 | + current_screen_state = new_state; |
1786 | return 0; |
1787 | } |
1788 | |
1789 | +gboolean activity_monitor(gpointer data) |
1790 | +{ |
1791 | + set_screen_state(SCREEN_OFF); |
1792 | +} |
1793 | |
1794 | void on_new_event(Event* event, void* context) |
1795 | { |
1796 | - |
1797 | - if (activity_timer > 0) { |
1798 | - g_source_remove(activity_timer); |
1799 | - activity_timer = 0; |
1800 | - } |
1801 | - |
1802 | switch(event->type) |
1803 | { |
1804 | case KEY_EVENT_TYPE: |
1805 | if (event->details.key.key_code == ISCL_KEYCODE_POWER && button_state != SHUTDOWN) { |
1806 | if (event->action == 1) { |
1807 | + g_debug("power button pressed"); |
1808 | button_state = BUTTON_UP; |
1809 | curtime = time(0); |
1810 | tm = localtime (&curtime); |
1811 | - if (tm->tm_sec - lasttime < 2) |
1812 | - set_screen_state(); |
1813 | + if (tm->tm_sec - lasttime < 2) { |
1814 | + enum screen_state new_state; |
1815 | + if (current_screen_state == SCREEN_OFF) |
1816 | + new_state = SCREEN_ON; |
1817 | + else |
1818 | + new_state = SCREEN_OFF; |
1819 | + set_screen_state(new_state); |
1820 | + } |
1821 | } else if (event->action == 0) { |
1822 | button_state = BUTTON_DOWN; |
1823 | curtime = time(0); |
1824 | @@ -278,7 +281,7 @@ |
1825 | lasttime = tm->tm_sec; |
1826 | if (button_timer > 0) |
1827 | { |
1828 | - g_source_remove(button_timer); |
1829 | + g_source_remove(button_timer); |
1830 | button_timer = 0; |
1831 | } |
1832 | button_timer = g_timeout_add_seconds(2, call_shutdown, NULL); |
1833 | @@ -286,19 +289,49 @@ |
1834 | } |
1835 | break; |
1836 | default: |
1837 | + reset_activity_timer(1); |
1838 | break; |
1839 | } |
1840 | } |
1841 | |
1842 | -} |
1843 | - |
1844 | +void powerd_exit(void) |
1845 | +{ |
1846 | + g_main_loop_quit(main_loop); |
1847 | +} |
1848 | + |
1849 | +static void |
1850 | +sigterm_quit(int signal) |
1851 | +{ |
1852 | + g_warning("SIGTERM recieved, cleaning up"); |
1853 | + // XXX - strangely this call to unown name claims the id is invalid |
1854 | + // but I'm sure we're using it properly |
1855 | + g_bus_unown_name(name_id); |
1856 | + g_main_loop_quit(main_loop); |
1857 | +} |
1858 | + |
1859 | +} //namespace |
1860 | |
1861 | int main(int argc, char** argv) |
1862 | { |
1863 | - |
1864 | - GMainLoop* main_loop = NULL; |
1865 | + int i, ret; |
1866 | + |
1867 | + g_type_init(); |
1868 | + name_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, "com.canonical.powerd", |
1869 | + G_BUS_NAME_OWNER_FLAGS_REPLACE, powerd_bus_acquired_cb, |
1870 | + powerd_name_acquired_cb, powerd_name_lost_cb, NULL, NULL); |
1871 | + g_debug("owner id: %u", name_id); |
1872 | + |
1873 | + libsuspend_init(0); |
1874 | + power_request_init(); |
1875 | + |
1876 | + /* We start in the active state, so take a request */ |
1877 | + ret = request_sys_state_internal(NULL, POWERD_SYS_STATE_ACTIVE, |
1878 | + getpid(), &internal_request_cookie); |
1879 | + if (!ret) |
1880 | + g_warning("Initial request for active state failed"); |
1881 | |
1882 | main_loop = g_main_loop_new (NULL, FALSE); |
1883 | + signal(SIGTERM, sigterm_quit); |
1884 | |
1885 | AndroidEventListener listener; |
1886 | listener.on_new_event = on_new_event; |
1887 | @@ -312,11 +345,16 @@ |
1888 | android_input_stack_initialize(&listener, &config); |
1889 | android_input_stack_start(); |
1890 | |
1891 | - g_type_init(); |
1892 | get_brightness_path(); |
1893 | + activity_timer = g_timeout_add_seconds(ACTIVITY_TIMEOUT, activity_monitor, NULL); |
1894 | + |
1895 | g_main_loop_run(main_loop); |
1896 | + g_bus_unown_name(name_id); |
1897 | + g_main_loop_unref(main_loop); |
1898 | |
1899 | android_input_stack_stop(); |
1900 | android_input_stack_shutdown(); |
1901 | + |
1902 | + power_request_deinit(); |
1903 | + return 0; |
1904 | } |
1905 | - |
1906 | |
1907 | === added file 'src/powerd.h' |
1908 | --- src/powerd.h 1970-01-01 00:00:00 +0000 |
1909 | +++ src/powerd.h 2013-05-21 14:54:26 +0000 |
1910 | @@ -0,0 +1,41 @@ |
1911 | +/* |
1912 | + * Copyright 2013 Canonical Ltd. |
1913 | + * |
1914 | + * This file is part of powerd. |
1915 | + * |
1916 | + * powerd is free software; you can redistribute it and/or modify |
1917 | + * it under the terms of the GNU General Public License as published by |
1918 | + * the Free Software Foundation; version 3. |
1919 | + * |
1920 | + * powerd is distributed in the hope that it will be useful, |
1921 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1922 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1923 | + * GNU General Public License for more details. |
1924 | + * |
1925 | + * You should have received a copy of the GNU General Public License |
1926 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1927 | + */ |
1928 | + |
1929 | +#ifndef __POWERD_H__ |
1930 | +#define __POWERD_H__ |
1931 | + |
1932 | +#ifdef __cplusplus |
1933 | +extern "C" { |
1934 | +#endif |
1935 | + |
1936 | +enum SysPowerStates { |
1937 | + //Note that callers will be notified of suspend state changes |
1938 | + //but may not request this state. |
1939 | + POWERD_SYS_STATE_SUSPEND = 0, |
1940 | + |
1941 | + //The Active state will prevent system suspend |
1942 | + POWERD_SYS_STATE_ACTIVE, |
1943 | + |
1944 | + POWERD_NUM_POWER_STATES |
1945 | +}; |
1946 | + |
1947 | +#ifdef __cplusplus |
1948 | +} |
1949 | +#endif |
1950 | + |
1951 | +#endif |
1952 | |
1953 | === added directory 'testclient' |
1954 | === added file 'testclient/CMakeLists.txt' |
1955 | --- testclient/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1956 | +++ testclient/CMakeLists.txt 2013-05-21 14:54:26 +0000 |
1957 | @@ -0,0 +1,37 @@ |
1958 | +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb -g") |
1959 | + |
1960 | +set( |
1961 | + SRCS |
1962 | + |
1963 | + testclient.c |
1964 | +) |
1965 | + |
1966 | +link_directories( |
1967 | + ${GLIB_LIBRARY_DIRS} |
1968 | + ${GIO_LIBRARY_DIRS} |
1969 | + ${GIO-UNIX_LIBRARY_DIRS} |
1970 | + ${GUDEV_LIBRARY_DIRS} |
1971 | +) |
1972 | + |
1973 | +include_directories( |
1974 | + ${GLIB_INCLUDE_DIRS} |
1975 | + ${GIO_INCLUDE_DIRS} |
1976 | + ${GIO-UNIX_INCLUDE_DIRS} |
1977 | + ${GUDEV_INCLUDE_DIRS} |
1978 | + ../src |
1979 | +) |
1980 | + |
1981 | +add_executable( |
1982 | + powerd-testclient |
1983 | + |
1984 | + ${SRCS} |
1985 | +) |
1986 | + |
1987 | +target_link_libraries( |
1988 | + powerd-testclient |
1989 | + |
1990 | + ${GLIB_LIBRARIES} |
1991 | + ${GUDEV_LIBRARIES} |
1992 | + ${GIO_LIBRARIES} |
1993 | + ${GIO-UNIX_LIBRARIES} |
1994 | +) |
1995 | |
1996 | === added file 'testclient/testclient.c' |
1997 | --- testclient/testclient.c 1970-01-01 00:00:00 +0000 |
1998 | +++ testclient/testclient.c 2013-05-21 14:54:26 +0000 |
1999 | @@ -0,0 +1,120 @@ |
2000 | +/* |
2001 | + * Copyright 2013 Canonical Ltd. |
2002 | + * |
2003 | + * This file is part of powerd. |
2004 | + * |
2005 | + * powerd is free software; you can redistribute it and/or modify |
2006 | + * it under the terms of the GNU General Public License as published by |
2007 | + * the Free Software Foundation; version 3. |
2008 | + * |
2009 | + * powerd is distributed in the hope that it will be useful, |
2010 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2011 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2012 | + * GNU General Public License for more details. |
2013 | + * |
2014 | + * You should have received a copy of the GNU General Public License |
2015 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2016 | + */ |
2017 | + |
2018 | +#include <assert.h> |
2019 | +#include <stdlib.h> |
2020 | +#include <stdio.h> |
2021 | +#include <unistd.h> |
2022 | +#include <sys/types.h> |
2023 | +#include <glib-object.h> |
2024 | +#include <gio/gio.h> |
2025 | +#include <powerd.h> |
2026 | + |
2027 | +static void |
2028 | +on_signal (GDBusProxy *proxy, |
2029 | + gchar *sender_name, |
2030 | + gchar *signal_name, |
2031 | + GVariant *parameters, |
2032 | + gpointer user_data) |
2033 | +{ |
2034 | + g_warning("we get signal from %s: %s", sender_name, signal_name); |
2035 | +} |
2036 | + |
2037 | +static gboolean |
2038 | +requestSysState(GDBusProxy *proxy, int state, pid_t pid, uint *cookie) |
2039 | +{ |
2040 | + GVariant *ret = NULL; |
2041 | + GError *error = NULL; |
2042 | + |
2043 | + if (proxy == NULL) { |
2044 | + g_warning("requires a valid proxy object"); |
2045 | + return FALSE; |
2046 | + } |
2047 | + |
2048 | + if (cookie == NULL) { |
2049 | + g_warning("requires a valid pointer for cookie"); |
2050 | + return FALSE; |
2051 | + } |
2052 | + |
2053 | + ret = g_dbus_proxy_call_sync(proxy, |
2054 | + "requestSysState", |
2055 | + g_variant_new("(ii)", state, pid), |
2056 | + G_DBUS_CALL_FLAGS_NONE, |
2057 | + -1, |
2058 | + NULL, |
2059 | + &error); |
2060 | + if (ret == NULL) { |
2061 | + g_warning("Error when calling requestSysState: %s", error->message); |
2062 | + g_error_free(error); |
2063 | + return FALSE; |
2064 | + } |
2065 | + else { |
2066 | + g_variant_get(ret, "(u)", cookie); |
2067 | + g_message("Got cookie: %u", *cookie); |
2068 | + return TRUE; |
2069 | + } |
2070 | +} |
2071 | + |
2072 | +int main (int argc, char **argv) |
2073 | +{ |
2074 | + GDBusProxy *proxy = NULL; |
2075 | + GMainLoop *loop = NULL; |
2076 | + GError *error = NULL; |
2077 | + pid_t mypid; |
2078 | + uint cookie; |
2079 | + |
2080 | + g_type_init(); |
2081 | + loop = g_main_loop_new (NULL, FALSE); |
2082 | + |
2083 | + proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, |
2084 | + G_DBUS_PROXY_FLAGS_NONE, |
2085 | + NULL, |
2086 | + "com.canonical.powerd", |
2087 | + "/com/canonical/powerd", |
2088 | + "com.canonical.powerd", |
2089 | + NULL, |
2090 | + &error); |
2091 | + |
2092 | + if (error != NULL) { |
2093 | + g_error("error, could not acquire system bus: %s", error->message); |
2094 | + g_error_free(error); |
2095 | + return -1; |
2096 | + } |
2097 | + |
2098 | + // XXX - attach to real signal once we have one |
2099 | + g_signal_connect(proxy, |
2100 | + "g-signal", |
2101 | + G_CALLBACK (on_signal), |
2102 | + NULL); |
2103 | + |
2104 | + mypid = getpid(); |
2105 | + g_message("Running as pid %d\n", mypid); |
2106 | + |
2107 | + assert(requestSysState(proxy, POWERD_SYS_STATE_ACTIVE, mypid, &cookie) == TRUE); |
2108 | + //cannot request the suspend state, this will fail |
2109 | + assert(requestSysState(proxy, POWERD_SYS_STATE_SUSPEND, mypid, &cookie) == FALSE); |
2110 | + //invalid values |
2111 | + assert(requestSysState(proxy, -1, mypid, &cookie) == FALSE); |
2112 | + assert(requestSysState(proxy, POWERD_NUM_POWER_STATES, mypid,&cookie) == FALSE); |
2113 | + assert(requestSysState(proxy, POWERD_NUM_POWER_STATES+1, mypid,&cookie) == FALSE); |
2114 | + |
2115 | + g_message("Waiting for events"); |
2116 | + g_main_loop_run(loop); |
2117 | + g_main_loop_unref(loop); |
2118 | + return 0; |
2119 | +} |
2120 | |
2121 | === added file 'tester.sh' |
2122 | --- tester.sh 1970-01-01 00:00:00 +0000 |
2123 | +++ tester.sh 2013-05-21 14:54:26 +0000 |
2124 | @@ -0,0 +1,51 @@ |
2125 | +#!/bin/sh |
2126 | + |
2127 | +RET=`sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2128 | + /com/canonical/powerd --method com.canonical.powerd.requestSysState 1 99` |
2129 | +COOKIEA=`echo ${RET%,*} | sed 's/.* //'` |
2130 | +echo "Cookie: $COOKIEA" |
2131 | +RET=`sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2132 | + /com/canonical/powerd --method com.canonical.powerd.requestSysState 1 99` |
2133 | +COOKIEB=`echo ${RET%,*} | sed 's/.* //'` |
2134 | +echo "Cookie: $COOKIEB" |
2135 | + |
2136 | +# should have 2 |
2137 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2138 | + /com/canonical/powerd --method com.canonical.powerd.listSysRequests |
2139 | + |
2140 | +# clear our requests |
2141 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2142 | + /com/canonical/powerd --method com.canonical.powerd.clearSysState $COOKIEA |
2143 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2144 | + /com/canonical/powerd --method com.canonical.powerd.clearSysState $COOKIEB |
2145 | + |
2146 | +# should have 0 |
2147 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2148 | + /com/canonical/powerd --method com.canonical.powerd.listSysRequests |
2149 | + |
2150 | +# these should fail |
2151 | +echo "These should all fail" |
2152 | +# invalid state 99 |
2153 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2154 | + /com/canonical/powerd --method com.canonical.powerd.requestSysState 99 99 |
2155 | +# illegal to request the suspend state |
2156 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2157 | + /com/canonical/powerd --method com.canonical.powerd.requestSysState 0 99 |
2158 | +# gdbus does not like passing -1 |
2159 | +#sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2160 | +# /com/canonical/powerd --method com.canonical.powerd.requestSysState \-1 99 |
2161 | +# bad arg |
2162 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2163 | + /com/canonical/powerd --method com.canonical.powerd.requestSysState fred |
2164 | +# bad arg |
2165 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2166 | + /com/canonical/powerd --method com.canonical.powerd.listStateRequests fred |
2167 | +# bad cookie |
2168 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2169 | + /com/canonical/powerd --method com.canonical.powerd.clearSysState 18181 |
2170 | +# bad arg |
2171 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2172 | + /com/canonical/powerd --method com.canonical.powerd.clearSysState fred |
2173 | +# invalid call to non-existant method |
2174 | +sudo gdbus call --system --dest com.canonical.powerd --object-path\ |
2175 | + /com/canonical/powerd --method com.canonical.powerd.chickenCutlass |
FAILED: Continuous integration, rev:32 /code.launchpad .net/~phablet- team/powerd/ dbus-stuff/ +merge/ 164811/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ powerd- ci/4/ jenkins. qa.ubuntu. com/job/ powerd- raring- armhf-ci/ 4
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ powerd- ci/4/rebuild
http://