Merge lp:~sforshee/powerd/low-battery-shutdown into lp:powerd

Proposed by Seth Forshee
Status: Merged
Approved by: Matt Fischer
Approved revision: 71
Merged at revision: 70
Proposed branch: lp:~sforshee/powerd/low-battery-shutdown
Merge into: lp:powerd
Diff against target: 234 lines (+113/-6)
5 files modified
CMakeLists.txt (+5/-0)
debian/control (+2/-1)
src/power-source.c (+91/-0)
src/powerd-internal.h (+5/-0)
src/powerd.cpp (+10/-5)
To merge this branch: bzr merge lp:~sforshee/powerd/low-battery-shutdown
Reviewer Review Type Date Requested Status
Matt Fischer (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+174861@code.launchpad.net

Commit message

Add shutdown on critically low battery, using upower for battery information (LP: 1123387)

Description of the change

Add shutdown on critically low battery, using upower for battery information (LP: 1123387)

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
Matt Fischer (mfisch) wrote :

124 + /*
125 + * Android shuts down when percentage reaches 0. We
126 + * use 1% to leave a little more headroom.
127 + */

Do we know how much less life this gives us?

134 + if (shutdown) {
135 + powerd_warn("Initiating emergency shutdown");
136 + powerd_shutdown();
137 + }

Can we or someone pop-up a GUI warning?

Can we add this to the test plan?

148 + ret = up_client_enumerate_devices_sync(up_client, NULL, NULL);
Does this delay initialization? Should we use async instead or do we need to delay other stuff on this finishing. My guess is we could use async but I don't know how much it gains us.

How often is the device changed CB Called? every percent, every 0.1 percent?

Revision history for this message
Seth Forshee (sforshee) wrote :

> 124 + /*
> 125 + * Android shuts down when percentage reaches 0. We
> 126 + * use 1% to leave a little more headroom.
> 127 + */
>
> Do we know how much less life this gives us?

No. It depends on too many factors, namely the size of the battery and what the system seems to be doing at the time you ask the question. upower tries to estimate time-to-empty, but I collected a lot of data and found that the estimate jumps around too much to really be all that useful for deciding when to shut down. The only thing that appeared to be even somewhat reliable was percent capacity remaining.

> 134 + if (shutdown) {
> 135 + powerd_warn("Initiating emergency shutdown");
> 136 + powerd_shutdown();
> 137 + }
>
> Can we or someone pop-up a GUI warning?

Well, powerd can't. What I expect this to be is the "oh crap" option. I.e., something higher level should do the nicey-nice, prompt the user shutdown before it gets this far. When this shutdown is triggered we just need to get it done.

> Can we add this to the test plan?

Sure.

> 148 + ret = up_client_enumerate_devices_sync(up_client, NULL, NULL);
> Does this delay initialization? Should we use async instead or do we need to
> delay other stuff on this finishing. My guess is we could use async but I
> don't know how much it gains us.

There is no async option, afaict. Unless the library is going to take care of it for us if we don't call this function. I couldn't tell because the documentation really isn't very informative.

> How often is the device changed CB Called? every percent, every 0.1 percent?

I suspect this mostly depends on how often the data from the drivers change. Empirically I can say that it varies from device to device. One device had big batches of changes at high frequency, but on an on-going basis I never saw updates happening more frequently than once every few seconds.

Revision history for this message
Matt Fischer (mfisch) wrote :

My only thought is that in the future we may want to adjust the threshold. Is it worth making a gsetting for now? Can you do half percentages?

But per discussion on IRC, we can skip this for now, until it is needed.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2013-07-02 16:43:23 +0000
3+++ CMakeLists.txt 2013-07-15 20:52:30 +0000
4@@ -22,6 +22,7 @@
5 pkg_check_modules(GIO gio-2.0)
6 pkg_check_modules(GIO-UNIX gio-unix-2.0)
7 pkg_check_modules(LIBUDEV libudev)
8+pkg_check_modules(UPOWER_GLIB upower-glib)
9 pkg_check_modules(UUID uuid)
10
11 set(POWERD_GENERATED_SOURCES
12@@ -42,6 +43,7 @@
13 src/log.c
14 src/powerd-object.c
15 src/power-request.c
16+ src/power-source.c
17 src/powerd-sensors.cpp
18 src/util.c
19 src/${GDBUS_NAME}.c
20@@ -52,6 +54,7 @@
21 ${GIO_LIBRARY_DIRS}
22 ${GIO-UNIX_LIBRARY_DIRS}
23 ${LIBUDEV_LIBRARY_DIRS}
24+ ${UPOWER_GLIB_LIBRARY_DIRS}
25 ${UUID_LIBRARY_DIRS}
26 )
27
28@@ -60,6 +63,7 @@
29 ${GIO_INCLUDE_DIRS}
30 ${GIO-UNIX_INCLUDE_DIRS}
31 ${LIBUDEV_INCLUDE_DIRS}
32+ ${UPOWER_GLIB_INCLUDE_DIRS}
33 ${UUID_INCLUDE_DIRS}
34 ${PROJECT_SOURCE_DIR}/libsuspend
35 ${CMAKE_CURRENT_BINARY_DIR}/src
36@@ -99,6 +103,7 @@
37 ${PHABLET_LIBRARIES}
38 "-lubuntu_application_api"
39 ${LIBUDEV_LIBRARIES}
40+ ${UPOWER_GLIB_LIBRARIES}
41 ${UUID_LIBRARIES}
42 )
43
44
45=== modified file 'debian/control'
46--- debian/control 2013-07-02 13:07:44 +0000
47+++ debian/control 2013-07-15 20:52:30 +0000
48@@ -10,6 +10,7 @@
49 libudev-dev,
50 python,
51 libplatform-api1-dev,
52+ libupower-glib-dev,
53 uuid-dev,
54 Standards-Version: 3.9.4
55 Homepage: https://launchpad.net/powerd
56@@ -19,7 +20,7 @@
57
58 Package: powerd
59 Architecture: any
60-Depends: ${misc:Depends}, ${shlibs:Depends}
61+Depends: ${misc:Depends}, ${shlibs:Depends}, upower
62 Recommends: ofono
63 Description: Power daemon to monitor and control system and display power state
64 This daemon monitors and controls system and display power states for Ubuntu
65
66=== added file 'src/power-source.c'
67--- src/power-source.c 1970-01-01 00:00:00 +0000
68+++ src/power-source.c 2013-07-15 20:52:30 +0000
69@@ -0,0 +1,91 @@
70+/*
71+ * Copyright 2013 Canonical Ltd.
72+ *
73+ * This file is part of powerd.
74+ *
75+ * powerd is free software; you can redistribute it and/or modify
76+ * it under the terms of the GNU General Public License as published by
77+ * the Free Software Foundation; version 3.
78+ *
79+ * powerd is distributed in the hope that it will be useful,
80+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
81+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82+ * GNU General Public License for more details.
83+ *
84+ * You should have received a copy of the GNU General Public License
85+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
86+ */
87+
88+#include <errno.h>
89+#include <glib.h>
90+#include <libupower-glib/upower.h>
91+
92+#include "powerd-internal.h"
93+#include "log.h"
94+
95+static UpClient *up_client;
96+
97+static void up_device_changed_cb(UpClient *client, UpDevice *device,
98+ gpointer unused)
99+{
100+ gboolean on_battery;
101+ GPtrArray *devices;
102+ int i;
103+ gboolean shutdown = TRUE;
104+
105+ g_object_get(up_client,
106+ "on_battery", &on_battery,
107+ NULL);
108+ if (!on_battery)
109+ return;
110+ devices = up_client_get_devices(up_client);
111+ for (i = 0; i < devices->len; i++) {
112+ UpDevice *device = g_ptr_array_index(devices, i);
113+ UpDeviceKind kind;
114+ gboolean is_present;
115+ g_object_get(device,
116+ "kind", &kind,
117+ "is-present", &is_present,
118+ NULL);
119+ if (kind == UP_DEVICE_KIND_BATTERY && is_present) {
120+ double percentage;
121+ g_object_get(device,
122+ "percentage", &percentage,
123+ NULL);
124+ /*
125+ * Android shuts down when percentage reaches 0. We
126+ * use 1% to leave a little more headroom.
127+ */
128+ if (percentage > 1.0) {
129+ shutdown = FALSE;
130+ break;
131+ }
132+ }
133+ }
134+ if (shutdown) {
135+ powerd_warn("Initiating emergency shutdown");
136+ powerd_shutdown();
137+ }
138+}
139+
140+int powerd_ps_init(void)
141+{
142+ gboolean ret;
143+ up_client = up_client_new();
144+ if (!up_client) {
145+ powerd_warn("Could not allocate upower client");
146+ return -ENODEV;
147+ }
148+ ret = up_client_enumerate_devices_sync(up_client, NULL, NULL);
149+ if (!ret)
150+ powerd_warn("Could not enumerate upower devices");
151+ g_signal_connect(up_client, "device-changed",
152+ G_CALLBACK(up_device_changed_cb), NULL);
153+ return 0;
154+}
155+
156+void powerd_ps_deinit(void)
157+{
158+ if (up_client)
159+ g_object_unref(up_client);
160+}
161
162=== modified file 'src/powerd-internal.h'
163--- src/powerd-internal.h 2013-07-10 19:12:51 +0000
164+++ src/powerd-internal.h 2013-07-15 20:52:30 +0000
165@@ -57,6 +57,7 @@
166 GSList *uuids;
167 };
168
169+void powerd_shutdown(void);
170 void powerd_exit(int exit_code);
171 void powerd_reset_activity_timer(int add);
172 void powerd_dbus_init_complete(void);
173@@ -150,6 +151,10 @@
174 void powerd_sensors_proximity_enable(void);
175 void powerd_sensors_proximity_disable(void);
176
177+/* Power source functions */
178+int powerd_ps_init(void);
179+void powerd_ps_deinit(void);
180+
181 /* Utility functions */
182 int powerd_run_mainloop_sync(int (*func)(gpointer), gpointer data);
183 guint powerd_uuid_hash(gconstpointer key);
184
185=== modified file 'src/powerd.cpp'
186--- src/powerd.cpp 2013-07-10 23:27:14 +0000
187+++ src/powerd.cpp 2013-07-15 20:52:30 +0000
188@@ -123,15 +123,11 @@
189
190 gboolean call_shutdown(gpointer data)
191 {
192- static char poweroff_cmd[] = "poweroff";
193- gchar *argv[] = {poweroff_cmd,
194- NULL};
195-
196 if (button_state == BUTTON_DOWN) {
197 button_state = SHUTDOWN;
198 powerd_set_brightness(0);
199 sf_blank(0);
200- g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
201+ powerd_shutdown();
202 }
203
204 return FALSE;
205@@ -416,6 +412,13 @@
206 return (g_thread_self() == powerd_mainloop_thread);
207 }
208
209+void powerd_shutdown(void)
210+{
211+ static char poweroff_cmd[] = "poweroff";
212+ char *argv[] = {poweroff_cmd, NULL};
213+ g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
214+}
215+
216 void powerd_exit(int exit_code)
217 {
218 g_exit_code = exit_code;
219@@ -476,6 +479,7 @@
220 powerd_backlight_init();
221 powerd_display_init();
222 powerd_sensors_init();
223+ powerd_ps_init();
224
225 main_loop = g_main_loop_new (NULL, FALSE);
226 signal(SIGTERM, sigterm_quit);
227@@ -502,6 +506,7 @@
228 android_input_stack_stop();
229 android_input_stack_shutdown();
230
231+ powerd_ps_deinit();
232 dbus_name_watch_deinit();
233 powerd_backlight_deinit();
234 display_request_deinit();

Subscribers

People subscribed via source and target branches