Merge lp:~morphis/ofono/ota9-suspend-fix into lp:~phablet-team/ofono/ubuntu

Proposed by Simon Fels on 2016-01-15
Status: Merged
Approved by: Tony Espy on 2016-01-15
Approved revision: 6910
Merged at revision: 6910
Proposed branch: lp:~morphis/ofono/ota9-suspend-fix
Merge into: lp:~phablet-team/ofono/ubuntu
Diff against target: 618 lines (+505/-2)
10 files modified
Makefile.am (+7/-2)
configure.ac (+5/-0)
debian/changelog (+11/-0)
debian/rules (+6/-0)
include/wakelock.h (+100/-0)
plugins/android-wakelock.c (+212/-0)
src/main.c (+4/-0)
src/ofono.h (+3/-0)
src/voicecall.c (+6/-0)
src/wakelock.c (+151/-0)
To merge this branch: bzr merge lp:~morphis/ofono/ota9-suspend-fix
Reviewer Review Type Date Requested Status
Tony Espy 2016-01-15 Approve on 2016-01-15
PS Jenkins bot continuous-integration Approve on 2016-01-15
Review via email: mp+282777@code.launchpad.net

Commit Message

[ Simon Fels]
* voicecall: acquire wakelock when starting a HFP initated voicecall
  (LP: #1533716)
* plugins: add android wakelock implementation
* src: add wakelock abstraction

Description of the Change

Correctly keep the system awake when we need to processing incoming HFP commands and the system might have slept and will otherwise fell asleep quickly again.

To post a comment you must log in.
Tony Espy (awe) :
review: Approve
lp:~morphis/ofono/ota9-suspend-fix updated on 2016-01-15
6911. By Simon Fels on 2016-01-15

Note the bug we've fixed in the changelog

Mathieu Trudel-Lapierre (cyphermox) wrote :

Commented inline.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2015-11-27 16:53:45 +0000
3+++ Makefile.am 2016-01-15 17:35:26 +0000
4@@ -23,7 +23,7 @@
5 include/cdma-provision.h include/handsfree.h \
6 include/handsfree-audio.h include/siri.h \
7 include/sim-mnclength.h include/spn-table.h \
8- include/dns-client.h
9+ include/dns-client.h include/wakelock.h
10
11 nodist_pkginclude_HEADERS = include/version.h
12
13@@ -616,6 +616,11 @@
14 builtin_modules += smshistory
15 builtin_sources += plugins/smshistory.c
16
17+if ANDROID_WAKELOCK
18+builtin_modules += android_wakelock
19+builtin_sources += plugins/android-wakelock.c
20+endif
21+
22 sbin_PROGRAMS = src/ofonod
23
24 src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
25@@ -645,7 +650,7 @@
26 src/handsfree-audio.c src/bluetooth.h \
27 src/hfp.h src/siri.c \
28 src/sim-mnclength.c src/spn-table.c \
29- src/dns-client.c
30+ src/dns-client.c src/wakelock.c
31
32 src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
33 @GLIB_LIBS@ @DBUS_LIBS@ -ldl
34
35=== modified file 'configure.ac'
36--- configure.ac 2015-10-23 07:09:51 +0000
37+++ configure.ac 2016-01-15 17:35:26 +0000
38@@ -234,6 +234,11 @@
39 [enable_upower=${enableval}])
40 AM_CONDITIONAL(UPOWER, test "${enable_power}" != "no")
41
42+AC_ARG_ENABLE(android_wakelock, AC_HELP_STRING([--enable-android-wakelock],
43+ [enable Enable support for Android wakelocks]),
44+ [enable_android_wakelock=${enableval}])
45+AM_CONDITIONAL(ANDROID_WAKELOCK, test "${enable_android_wakelock}" = "yes")
46+
47 AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
48 [do not install configuration and data files]),
49 [enable_datafiles=${enableval}])
50
51=== modified file 'debian/changelog'
52--- debian/changelog 2015-12-03 08:32:21 +0000
53+++ debian/changelog 2016-01-15 17:35:26 +0000
54@@ -1,3 +1,14 @@
55+ofono (1.17.bzr6910+16.04.20151203-0ubuntu1) UNRELEASED; urgency=medium
56+
57+ [ Simon Fels]
58+
59+ * voicecall: acquire wakelock when starting a HFP initated voicecall
60+ (LP: #1533716)
61+ * plugins: add android wakelock implementation
62+ * src: add wakelock abstraction
63+
64+ -- Simon Fels <simon.fels@canonical.com> Fri, 15 Jan 2016 17:00:56 +0100
65+
66 ofono (1.17.bzr6908+16.04.20151203-0ubuntu1) xenial; urgency=medium
67
68 [ Tony Espy ]
69
70=== modified file 'debian/rules'
71--- debian/rules 2015-09-10 17:15:10 +0000
72+++ debian/rules 2016-01-15 17:35:26 +0000
73@@ -9,9 +9,15 @@
74 -Wcast-align \
75 -DG_DISABLE_DEPRECATED
76
77+CONFIGURE_FLAGS := \
78+ --enable-android-wakelock
79+
80 %:
81 dh $@ --parallel --with=autoreconf,systemd
82
83+override_dh_auto_configure:
84+ dh_auto_configure -- $(CONFIGURE_FLAGS)
85+
86 override_dh_installinit:
87 dh_installinit --no-restart-on-upgrade
88
89
90=== added file 'include/wakelock.h'
91--- include/wakelock.h 1970-01-01 00:00:00 +0000
92+++ include/wakelock.h 2016-01-15 17:35:26 +0000
93@@ -0,0 +1,100 @@
94+/*
95+ *
96+ * oFono - Open Source Telephony
97+ *
98+ * Copyright (C) 2015 Jolla Ltd. All rights reserved.
99+ * Contact: Hannu Mallat <hannu.mallat@jollamobile.com>
100+ *
101+ * This program is free software; you can redistribute it and/or modify
102+ * it under the terms of the GNU General Public License as published by
103+ * the Free Software Foundation; either version 2 of the License, or
104+ * (at your option) any later version.
105+ *
106+ * This program is distributed in the hope that it will be useful,
107+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
108+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109+ * GNU General Public License for more details.
110+ *
111+ * You should have received a copy of the GNU General Public License
112+ * along with this program; if not, write to the Free Software
113+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
114+ *
115+ */
116+
117+#ifndef __OFONO_WAKELOCK_H_
118+#define __OFONO_WAKELOCK_H_
119+
120+#include <ofono/types.h>
121+
122+/* Wakelock interface
123+ *
124+ * Wakelocks ensure system does not suspend/enter power save mode
125+ * before an ongoing operation completes. This header declares a
126+ * wakelock API that can be implemented by a OS-specific plugin.
127+ */
128+
129+struct wakelock; /* Opaque */
130+
131+struct wakelock_table {
132+ int (*create)(const char *name, struct wakelock **);
133+ int (*free)(struct wakelock *);
134+ int (*acquire)(struct wakelock *);
135+ int (*release)(struct wakelock *);
136+ ofono_bool_t (*is_locked)(struct wakelock *);
137+};
138+
139+
140+/*** Functions for wakelock users ***/
141+
142+/*
143+ * This will create a wakelock which will be held for a short duration
144+ * and then automatically freed. If this is called multiple times the
145+ * timeout will be restarted on every call.
146+ */
147+void wakelock_system_lock(void);
148+
149+/*
150+ * Create a wakelock. Multiple wakelocks can be created; if any one of
151+ * them is activated, system will be prevented from going to suspend.
152+ * This makes it possible to overlap locks to hand over from subsystem
153+ * to subsystem, each with their own wakelock-guarded sections,
154+ * without falling to suspend in between.
155+ */
156+int wakelock_create(const char *name, struct wakelock **wakelock);
157+
158+/*
159+ * Free a wakelock, releasing all acquisitions at the same time
160+ * and deallocating the lock.
161+ */
162+int wakelock_free(struct wakelock *wakelock);
163+
164+/*
165+ * Acquire a wakelock. Multiple acquisitions are possible, meaning
166+ * that the wakelock needs to be released the same number of times
167+ * until it is actually deactivated.
168+ */
169+int wakelock_acquire(struct wakelock *wakelock);
170+
171+/*
172+ * Release a wakelock, deactivating it if all acquisitions are
173+ * released, letting system suspend.
174+ */
175+int wakelock_release(struct wakelock *wakelock);
176+
177+/*
178+ * Check if a wakelock is currently locked or not.
179+ */
180+ofono_bool_t wakelock_is_locked(struct wakelock *wakelock);
181+
182+/*** Functions for wakelock implementors ***/
183+
184+/*
185+ * Register a wakelock implementation. Only one implementation may be
186+ * registered at a time. In the absence of an implementation, all
187+ * wakelock functions are no-ops.
188+ */
189+int wakelock_plugin_register(const char *name, struct wakelock_table *fns);
190+
191+int wakelock_plugin_unregister(void);
192+
193+#endif
194
195=== added file 'plugins/android-wakelock.c'
196--- plugins/android-wakelock.c 1970-01-01 00:00:00 +0000
197+++ plugins/android-wakelock.c 2016-01-15 17:35:26 +0000
198@@ -0,0 +1,212 @@
199+/*
200+ *
201+ * oFono - Open Source Telephony - Android based wakelocks
202+ *
203+ * Copyright (C) 2016 Canonical Ltd.
204+ *
205+ * This program is free software; you can redistribute it and/or modify
206+ * it under the terms of the GNU General Public License as published by
207+ * the Free Software Foundation; either version 2 of the License, or
208+ * (at your option) any later version.
209+ *
210+ * This program is distributed in the hope that it will be useful,
211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213+ * GNU General Public License for more details.
214+ *
215+ * You should have received a copy of the GNU General Public License
216+ * along with this program; if not, write to the Free Software
217+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
218+ *
219+ */
220+
221+#ifdef HAVE_CONFIG_H
222+#include <config.h>
223+#endif
224+
225+#include <sys/types.h>
226+#include <sys/stat.h>
227+#include <fcntl.h>
228+#include <unistd.h>
229+#include <string.h>
230+#include <errno.h>
231+#include <glib.h>
232+#include <dlfcn.h>
233+
234+#include <glib.h>
235+
236+#define OFONO_API_SUBJECT_TO_CHANGE
237+
238+#include "plugin.h"
239+#include "log.h"
240+#include "wakelock.h"
241+
242+#define ANDROID_WAKELOCK_LOCK_PATH "/sys/power/wake_lock"
243+#define ANDROID_WAKELOCK_UNLOCK_PATH "/sys/power/wake_unlock"
244+
245+struct wakelock {
246+ char *name;
247+ unsigned int acquisitions;
248+};
249+
250+GSList *locks = NULL;
251+
252+static int file_exists(char const *filename)
253+{
254+ struct stat st;
255+
256+ return stat(filename, &st) == 0;
257+}
258+
259+static int write_file(const char *file, const char *content)
260+{
261+ int fd;
262+ unsigned int r = 0;
263+
264+ fd = open(file, O_WRONLY);
265+
266+ if (fd == -1)
267+ return -EIO;
268+
269+ r = write(fd, content, strlen(content));
270+
271+ close(fd);
272+
273+ if (r != strlen(content))
274+ return -EIO;
275+
276+ return 0;
277+}
278+
279+static int wakelock_lock(const char *name)
280+{
281+ return write_file(ANDROID_WAKELOCK_LOCK_PATH, name);
282+}
283+
284+static int wakelock_unlock(const char *name)
285+{
286+ return write_file(ANDROID_WAKELOCK_UNLOCK_PATH, name);
287+}
288+
289+static int android_wakelock_acquire(struct wakelock *lock)
290+{
291+ if (!lock)
292+ return -EINVAL;
293+
294+ if (lock->acquisitions > 0) {
295+ lock->acquisitions++;
296+ return 0;
297+ }
298+
299+ if (wakelock_lock(lock->name) < 0)
300+ return -EIO;
301+
302+ lock->acquisitions++;
303+
304+ return 0;
305+}
306+
307+static int android_wakelock_release(struct wakelock *lock)
308+{
309+ if (!lock)
310+ return -EINVAL;
311+
312+ DBG("lock %p name %s acquisitions %d",
313+ lock, lock->name, lock->acquisitions);
314+
315+ if (!lock->acquisitions) {
316+ ofono_warn("Attempted to release already released lock %s", lock->name);
317+ return -EINVAL;
318+ }
319+
320+ if (lock->acquisitions > 1) {
321+ lock->acquisitions--;
322+ DBG("lock %s released acquisitions %d", lock->name, lock->acquisitions);
323+ return 0;
324+ }
325+
326+ if (wakelock_unlock(lock->name) < 0)
327+ return -EIO;
328+
329+ lock->acquisitions = 0;
330+
331+ DBG("lock %s was released", lock->name);
332+
333+ return 0;
334+}
335+
336+static int android_wakelock_create(const char *name, struct wakelock **lock)
337+{
338+ if (!lock)
339+ return -EINVAL;
340+
341+ *lock = g_new0(struct wakelock, 1);
342+ (*lock)->name = g_strdup(name);
343+ (*lock)->acquisitions = 0;
344+
345+ locks = g_slist_prepend(locks, *lock);
346+
347+ DBG("wakelock %s create", name);
348+
349+ return 0;
350+}
351+
352+static int android_wakelock_free(struct wakelock *lock)
353+{
354+ if (!lock)
355+ return -EINVAL;
356+
357+ if (lock->acquisitions) {
358+ /* Need to force releasing the lock here */
359+ lock->acquisitions = 1;
360+ android_wakelock_release(lock);
361+ }
362+
363+ locks = g_slist_remove(locks, lock);
364+
365+ DBG("Freeing lock %s", lock->name);
366+
367+ g_free(lock->name);
368+ g_free(lock);
369+
370+ return 0;
371+}
372+
373+static ofono_bool_t android_wakelock_is_locked(struct wakelock *lock)
374+{
375+ if (!lock)
376+ return FALSE;
377+
378+ return lock->acquisitions > 0;
379+}
380+
381+struct wakelock_table driver = {
382+ .create = android_wakelock_create,
383+ .free = android_wakelock_free,
384+ .acquire = android_wakelock_acquire,
385+ .release = android_wakelock_release,
386+ .is_locked = android_wakelock_is_locked
387+};
388+
389+static int android_wakelock_init(void)
390+{
391+ if (!file_exists(ANDROID_WAKELOCK_LOCK_PATH)) {
392+ ofono_warn("System does not support Android wakelocks.");
393+ return 0;
394+ }
395+
396+ if (wakelock_plugin_register("android-wakelock", &driver) < 0) {
397+ ofono_error("Failed to register wakelock driver");
398+ return -EIO;
399+ }
400+
401+ return 0;
402+}
403+
404+static void android_wakelock_exit(void)
405+{
406+ wakelock_plugin_unregister();
407+}
408+
409+OFONO_PLUGIN_DEFINE(android_wakelock, "Android Wakelock driver", VERSION,
410+ OFONO_PLUGIN_PRIORITY_DEFAULT, android_wakelock_init, android_wakelock_exit)
411
412=== modified file 'src/main.c'
413--- src/main.c 2015-09-28 08:10:59 +0000
414+++ src/main.c 2016-01-15 17:35:26 +0000
415@@ -244,8 +244,12 @@
416 g_free(option_plugin);
417 g_free(option_noplugin);
418
419+ __ofono_wakelock_init();
420+
421 g_main_loop_run(event_loop);
422
423+ __ofono_wakelock_cleanup();
424+
425 __ofono_plugin_cleanup();
426
427 __ofono_manager_cleanup();
428
429=== modified file 'src/ofono.h'
430--- src/ofono.h 2015-11-02 09:18:14 +0000
431+++ src/ofono.h 2016-01-15 17:35:26 +0000
432@@ -534,3 +534,6 @@
433 #include <ofono/sim-mnclength.h>
434
435 int __ofono_sim_mnclength_get_mnclength(const char *imsi);
436+
437+int __ofono_wakelock_init(void);
438+void __ofono_wakelock_cleanup(void);
439
440=== modified file 'src/voicecall.c'
441--- src/voicecall.c 2015-11-27 16:53:45 +0000
442+++ src/voicecall.c 2016-01-15 17:35:26 +0000
443@@ -38,6 +38,7 @@
444 #include "simutil.h"
445 #include "smsutil.h"
446 #include "storage.h"
447+#include "wakelock.h"
448
449 #define MAX_VOICE_CALLS 16
450
451@@ -3462,6 +3463,11 @@
452 char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 1];
453 struct ofono_error result;
454
455+ /* Make sure we keep the system awake if we get woken up
456+ * shortly for processing the incoming request from the
457+ * HFP HF. */
458+ wakelock_system_lock();
459+
460 switch (ofono_emulator_request_get_type(req)) {
461 case OFONO_EMULATOR_REQUEST_TYPE_SET:
462 str = ofono_emulator_request_get_raw(req);
463
464=== added file 'src/wakelock.c'
465--- src/wakelock.c 1970-01-01 00:00:00 +0000
466+++ src/wakelock.c 2016-01-15 17:35:26 +0000
467@@ -0,0 +1,151 @@
468+/*
469+ *
470+ * oFono - Open Source Telephony
471+ *
472+ * Copyright (C) 2015 Jolla Ltd. All rights reserved.
473+ * Contact: Hannu Mallat <hannu.mallat@jollamobile.com>
474+ *
475+ * This program is free software; you can redistribute it and/or modify
476+ * it under the terms of the GNU General Public License as published by
477+ * the Free Software Foundation; either version 2 of the License, or
478+ * (at your option) any later version.
479+ *
480+ * This program is distributed in the hope that it will be useful,
481+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
482+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
483+ * GNU General Public License for more details.
484+ *
485+ * You should have received a copy of the GNU General Public License
486+ * along with this program; if not, write to the Free Software
487+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
488+ *
489+ */
490+
491+#ifdef HAVE_CONFIG_H
492+#include <config.h>
493+#endif
494+
495+#include <errno.h>
496+#include <string.h>
497+#include <glib.h>
498+
499+#include "log.h"
500+#include "wakelock.h"
501+#include "ofono.h"
502+
503+#define SYSTEM_WAKELOCK_NAME "ofono-system"
504+#define SYSTEM_WAKELOCK_DURATION 30
505+
506+static char *impl = NULL;
507+static struct wakelock_table table;
508+
509+static struct wakelock *system_wakelock = NULL;
510+static guint system_wakelock_source = 0;
511+
512+static gboolean system_wakelock_put(gpointer user_data)
513+{
514+ DBG("Releasing system wakelock");
515+ wakelock_release(system_wakelock);
516+ system_wakelock_source = 0;
517+ return FALSE;
518+}
519+
520+void wakelock_system_lock(void)
521+{
522+ guint old_source;
523+
524+ if (!impl)
525+ return;
526+
527+ DBG("Acquiring system wakelock");
528+
529+ old_source = system_wakelock_source;
530+
531+ system_wakelock_source = g_timeout_add_seconds(SYSTEM_WAKELOCK_DURATION,
532+ system_wakelock_put,
533+ NULL);
534+ if (system_wakelock_source)
535+ wakelock_acquire(system_wakelock);
536+
537+ if (old_source) {
538+ g_source_remove(old_source);
539+ wakelock_release(system_wakelock);
540+ }
541+}
542+
543+int wakelock_create(const char *name, struct wakelock **wakelock)
544+{
545+ if (!impl) {
546+ *wakelock = NULL;
547+ return -EINVAL;
548+ }
549+
550+ return (table.create)(name, wakelock);
551+}
552+
553+int wakelock_free(struct wakelock *wakelock)
554+{
555+ if (!impl)
556+ return -EINVAL;
557+
558+ return table.free(wakelock);
559+}
560+
561+int wakelock_acquire(struct wakelock *wakelock)
562+{
563+ if (!impl)
564+ return -EINVAL;
565+
566+ return table.acquire(wakelock);
567+}
568+
569+int wakelock_release(struct wakelock *wakelock)
570+{
571+ if (!impl)
572+ return -EINVAL;
573+
574+ return table.release(wakelock);
575+}
576+
577+ofono_bool_t wakelock_is_locked(struct wakelock *wakelock) {
578+ if (!impl)
579+ return -EINVAL;
580+
581+ return table.is_locked(wakelock);
582+}
583+
584+int wakelock_plugin_register(const char *name, struct wakelock_table *fns)
585+{
586+ if (impl)
587+ return -EALREADY;
588+
589+ impl = g_strdup(name);
590+ memcpy(&table, fns, sizeof(struct wakelock_table));
591+ return 0;
592+}
593+
594+int wakelock_plugin_unregister(void)
595+{
596+ if (!impl)
597+ return -ENOENT;
598+
599+ memset(&table, 0, sizeof(struct wakelock_table));
600+ g_free(impl);
601+ impl = NULL;
602+
603+ return 0;
604+}
605+
606+int __ofono_wakelock_init(void)
607+{
608+ if (wakelock_create(SYSTEM_WAKELOCK_NAME, &system_wakelock) < 0)
609+ ofono_warn("Failed to create system keep alive wakelock");
610+
611+ return 0;
612+}
613+
614+void __ofono_wakelock_cleanup(void)
615+{
616+ if (system_wakelock)
617+ wakelock_free(system_wakelock);
618+}

Subscribers

People subscribed via source and target branches