Merge lp:~awe/phablet-extras/ofono-nettime-plugin into lp:phablet-extras/ofono

Proposed by Tony Espy on 2013-06-25
Status: Merged
Approved by: Ricardo Salveti on 2013-06-26
Approved revision: 46
Merged at revision: 45
Proposed branch: lp:~awe/phablet-extras/ofono-nettime-plugin
Merge into: lp:phablet-extras/ofono
Diff against target: 442 lines (+371/-1)
7 files modified
Makefile.am (+5/-0)
configure.ac (+5/-0)
debian/changelog (+5/-1)
include/dbus.h (+1/-0)
plugins/nettime.c (+274/-0)
test/get-network-time (+69/-0)
test/monitor-ofono (+12/-0)
To merge this branch: bzr merge lp:~awe/phablet-extras/ofono-nettime-plugin
Reviewer Review Type Date Requested Status
Ricardo Salveti 2013-06-25 Approve on 2013-06-26
PS Jenkins bot continuous-integration Approve on 2013-06-26
Review via email: mp+171344@code.launchpad.net

Commit message

Added network time plugin which exposes RILD NITZ messages over DBus.

Description of the change

Add network time plugin.

This can be tested using a new test script get-network-time and modification to monitor-ofono.

To post a comment you must log in.
Tony Espy (awe) wrote :

Note, as I'm going to have to re-merge once the IMEI MR lands, I'll deal with the changelog at the same time...

44. By Tony Espy on 2013-06-25

Re-merge from trunk.

Ricardo Salveti (rsalveti) wrote :

476 + for member in ["NetworkTimeReceived"]:

This should be NetworkTimeChanged instead.

Other than that, code looks good.

review: Needs Fixing
45. By Tony Espy on 2013-06-26

[nettime] Fix NetworkTimeChanged signal in test/monitor-ofono.

Tony Espy (awe) wrote :

Nice catch... fixed.

46. By Tony Espy on 2013-06-26

Re-merge from trunk.

Ricardo Salveti (rsalveti) wrote :

Good.

review: Approve

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 2013-04-12 20:04:45 +0000
3+++ Makefile.am 2013-06-26 17:26:23 +0000
4@@ -466,6 +466,11 @@
5 endif
6 endif
7
8+if NETTIME
9+builtin_modules += nettime
10+builtin_sources += plugins/nettime.c
11+endif
12+
13 if PROVISION
14 builtin_sources += plugins/mbpi.h plugins/mbpi.c
15
16
17=== modified file 'configure.ac'
18--- configure.ac 2013-03-28 12:50:26 +0000
19+++ configure.ac 2013-06-26 17:26:23 +0000
20@@ -188,6 +188,11 @@
21 AC_SUBST(BLUEZ_LIBS)
22 AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
23
24+AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
25+ [disable Nettime plugin]),
26+ [enable_nettime=${enableval}])
27+AM_CONDITIONAL(NETTIME, test "${enable_netttime}" != "no")
28+
29 AC_ARG_WITH([provisiondb], AC_HELP_STRING([--with-provisiondb=FILE],
30 [location of provision database]), [path_provisiondb=${withval}])
31
32
33=== modified file 'debian/changelog'
34--- debian/changelog 2013-06-26 15:49:07 +0000
35+++ debian/changelog 2013-06-26 17:26:23 +0000
36@@ -1,7 +1,11 @@
37-ofono (1.12phablet7) UNRELEASED; urgency=low
38+ofono (1.12phablet7) saucy; urgency=low
39
40+ [ Tony Espy ]
41 * gril/gril.c: Exit on RILD socket failures.
42
43+ [ Petri M. Gerdt <petri.gerdt@jollamobile.com> ]
44+ * plugins/nettime.c: Added nettime plugin.
45+
46 -- Tony Espy <espy@canonical.com> Tue, 25 Jun 2013 15:14:13 -0400
47
48 ofono (1.12phablet6) saucy; urgency=low
49
50=== modified file 'include/dbus.h'
51--- include/dbus.h 2012-08-22 19:59:08 +0000
52+++ include/dbus.h 2013-06-26 17:26:23 +0000
53@@ -59,6 +59,7 @@
54 #define OFONO_GNSS_INTERFACE "org.ofono.AssistedSatelliteNavigation"
55 #define OFONO_GNSS_POSR_AGENT_INTERFACE "org.ofono.PositioningRequestAgent"
56 #define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
57+#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
58
59 /* CDMA Interfaces */
60 #define OFONO_CDMA_VOICECALL_MANAGER_INTERFACE "org.ofono.cdma.VoiceCallManager"
61
62=== added file 'plugins/nettime.c'
63--- plugins/nettime.c 1970-01-01 00:00:00 +0000
64+++ plugins/nettime.c 2013-06-26 17:26:23 +0000
65@@ -0,0 +1,274 @@
66+/*
67+ *
68+ * oFono - Open Source Telephony
69+ *
70+ * Copyright (C) 2012-2013 Jolla Ltd.
71+ *
72+ * This program is free software; you can redistribute it and/or modify
73+ * it under the terms of the GNU General Public License version 2 as
74+ * published by the Free Software Foundation.
75+ *
76+ * This program is distributed in the hope that it will be useful,
77+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
78+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79+ * GNU General Public License for more details.
80+ *
81+ * You should have received a copy of the GNU General Public License
82+ * along with this program; if not, write to the Free Software
83+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
84+ *
85+ */
86+
87+#ifdef HAVE_CONFIG_H
88+#include <config.h>
89+#endif
90+
91+#include <string.h>
92+#include <glib.h>
93+#include <gdbus.h>
94+
95+#define OFONO_API_SUBJECT_TO_CHANGE
96+#include <ofono/plugin.h>
97+#include <ofono/log.h>
98+#include <ofono/nettime.h>
99+#include <ofono/types.h>
100+
101+#include "ofono.h"
102+
103+#include "common.h"
104+
105+struct nt_data {
106+ gboolean time_available;
107+ gboolean time_pending;
108+
109+ time_t nw_time_utc;
110+ time_t received;
111+
112+ int dst;
113+ int time_zone;
114+
115+ const char *mcc;
116+ const char *mnc;
117+ const char *path;
118+};
119+
120+static struct nt_data *ntd = NULL;
121+
122+
123+static void init_time(void)
124+{
125+ ntd = g_new0(struct nt_data, 1);
126+
127+ ntd->time_available = FALSE;
128+ ntd->time_pending = FALSE;
129+ ntd->dst = 0;
130+ ntd->time_zone = 0;
131+}
132+
133+static gboolean encode_time_format(const struct ofono_network_time *time,
134+ struct tm *tm)
135+{
136+ if (time->year < 0)
137+ return FALSE;
138+
139+ memset(tm, 0, sizeof(struct tm));
140+ tm->tm_year = time->year - 1900;
141+ tm->tm_mon = time->mon - 1;
142+ tm->tm_mday = time->mday;
143+ tm->tm_hour = time->hour;
144+ tm->tm_min = time->min;
145+ tm->tm_sec = time->sec;
146+ tm->tm_gmtoff = time->utcoff;
147+ tm->tm_isdst = time->dst;
148+
149+ return TRUE;
150+}
151+
152+static time_t get_monotonic_time()
153+{
154+ struct timespec ts;
155+ clock_gettime(CLOCK_MONOTONIC, &ts);
156+ return ts.tv_sec;
157+}
158+
159+static int fill_time_notification(DBusMessage *msg,
160+ struct nt_data *ntd)
161+{
162+ DBusMessageIter iter, iter_array;
163+ dbus_int64_t utc_long, received;
164+ dbus_int32_t dst, timezone;
165+ dbus_message_iter_init_append(msg, &iter);
166+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
167+ "{sv}",
168+ &iter_array);
169+ if (ntd->time_pending) {
170+ if (ntd->time_available) {
171+ utc_long = (dbus_int64_t) ntd->nw_time_utc;
172+ ofono_dbus_dict_append(&iter_array,
173+ "UTC",
174+ DBUS_TYPE_INT64,
175+ &utc_long);
176+ dst = (dbus_int32_t) ntd->dst;
177+ ofono_dbus_dict_append(&iter_array,
178+ "DST",
179+ DBUS_TYPE_UINT32,
180+ &dst);
181+ received = (dbus_int64_t) ntd->received;
182+ ofono_dbus_dict_append(&iter_array,
183+ "Received",
184+ DBUS_TYPE_INT64,
185+ &received);
186+ }
187+
188+ timezone = (dbus_int32_t) ntd->time_zone;
189+ ofono_dbus_dict_append(&iter_array,
190+ "Timezone",
191+ DBUS_TYPE_INT32,
192+ &timezone);
193+
194+ ofono_dbus_dict_append(&iter_array,
195+ "MobileCountryCode",
196+ DBUS_TYPE_STRING,
197+ &ntd->mcc);
198+
199+ ofono_dbus_dict_append(&iter_array,
200+ "MobileNetworkCode",
201+ DBUS_TYPE_STRING,
202+ &ntd->mnc);
203+ } else {
204+ DBG("fill_time_notification: time not available");
205+ }
206+
207+ dbus_message_iter_close_container(&iter, &iter_array);
208+ return 0;
209+}
210+
211+static DBusMessage *get_network_time(DBusConnection *conn,
212+ DBusMessage *msg, void *data)
213+{
214+ DBusMessage *reply;
215+
216+ reply = dbus_message_new_method_return(msg);
217+ if (reply == NULL)
218+ return NULL;
219+ fill_time_notification(reply, ntd);
220+ return reply;
221+}
222+
223+static const GDBusMethodTable nettime_methods[] = {
224+ { GDBUS_METHOD("GetNetworkTime",
225+ NULL, GDBUS_ARGS({ "time", "a{sv}" }),
226+ get_network_time) },
227+ { }
228+};
229+
230+static const GDBusSignalTable nettime_signals[] = {
231+ { GDBUS_SIGNAL("NetworkTimeChanged",
232+ GDBUS_ARGS({ "time", "a{sv}" })) },
233+ { }
234+};
235+
236+static int nettime_probe(struct ofono_nettime_context *context)
237+{
238+ DBusConnection *conn = ofono_dbus_get_connection();
239+ const char *path = ofono_modem_get_path(context->modem);
240+ DBG("Network time probe for modem: %p (%s)", context->modem, path);
241+ init_time();
242+ if (!g_dbus_register_interface(conn, path,
243+ OFONO_NETWORK_TIME_INTERFACE, // name
244+ nettime_methods, // methods
245+ nettime_signals, // signals
246+ NULL, // GDBusPropertyTable *properties
247+ NULL, // user data
248+ NULL)) { // GDBusDestroyFunction destroy
249+ ofono_error("Networkt time: Could not register interface %s, path %s",
250+ OFONO_NETWORK_TIME_INTERFACE, path);
251+ return 1;
252+ } else {
253+ ofono_info("Network time: Registered inteface %s, path %s",
254+ OFONO_NETWORK_TIME_INTERFACE, path);
255+ }
256+
257+ ofono_modem_add_interface(context->modem, OFONO_NETWORK_TIME_INTERFACE);
258+ return 0;
259+}
260+
261+static void nettime_remove(struct ofono_nettime_context *context)
262+{
263+ DBusConnection *conn = ofono_dbus_get_connection();
264+ const char *path = ofono_modem_get_path(context->modem);
265+ DBG("Network time remove for modem: %p (%s)", context->modem, path);
266+ if (!g_dbus_unregister_interface(conn, path, OFONO_NETWORK_TIME_INTERFACE)) {
267+ ofono_error("Network time: could not unregister interface %s, path %s",
268+ OFONO_NETWORK_TIME_INTERFACE, path);
269+ }
270+
271+ ofono_modem_remove_interface(context->modem, OFONO_NETWORK_TIME_INTERFACE);
272+ g_free(ntd);
273+}
274+
275+static void send_signal(struct nt_data *ntd)
276+{
277+ DBusConnection *conn = ofono_dbus_get_connection();
278+ DBusMessage *signal = dbus_message_new_signal(ntd->path,
279+ OFONO_NETWORK_TIME_INTERFACE,
280+ "NetworkTimeChanged");
281+ fill_time_notification(signal, ntd);
282+ g_dbus_send_message(conn, signal);
283+}
284+
285+static void nettime_info_received(struct ofono_nettime_context *context,
286+ struct ofono_network_time *info)
287+{
288+ struct ofono_netreg *netreg;
289+ struct tm t;
290+
291+ if (info == NULL)
292+ return;
293+
294+ netreg = __ofono_atom_get_data(__ofono_modem_find_atom(
295+ context->modem, OFONO_ATOM_TYPE_NETREG));
296+ ntd->path = ofono_modem_get_path(context->modem);
297+ ntd->mcc = ofono_netreg_get_mcc(netreg);
298+ ntd->mnc = ofono_netreg_get_mnc(netreg);
299+ ntd->received = get_monotonic_time();
300+ ntd->time_pending = TRUE;
301+ ntd->dst = info->dst;
302+ ntd->time_zone = info->utcoff;
303+
304+ ntd->time_available = encode_time_format(info, &t);
305+ if (ntd->time_available == TRUE)
306+ ntd->nw_time_utc = timegm(&t);
307+
308+ send_signal(ntd);
309+ DBG("modem: %p (%s)", context->modem, ofono_modem_get_path(context->modem));
310+ DBG("time: %04d-%02d-%02d %02d:%02d:%02d%c%02d:%02d (DST=%d)",
311+ info->year, info->mon, info->mday, info->hour,
312+ info->min, info->sec, info->utcoff > 0 ? '+' : '-',
313+ abs(info->utcoff) / 3600, (abs(info->utcoff) % 3600) / 60,
314+ info->dst);
315+ DBG("UTC timestamp: %li, Received (monotonic time): %li",
316+ ntd->nw_time_utc, ntd->received);
317+ DBG("MCC: %s, MNC: %s", ntd->mcc, ntd->mnc);
318+}
319+
320+static struct ofono_nettime_driver driver = {
321+ .name = "Network Time",
322+ .probe = nettime_probe,
323+ .remove = nettime_remove,
324+ .info_received = nettime_info_received,
325+};
326+
327+static int nettime_init(void)
328+{
329+ return ofono_nettime_driver_register(&driver);
330+}
331+
332+static void nettime_exit(void)
333+{
334+ ofono_nettime_driver_unregister(&driver);
335+}
336+
337+OFONO_PLUGIN_DEFINE(nettime, "Network Time Plugin",
338+ VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
339+ nettime_init, nettime_exit)
340
341=== added file 'test/get-network-time'
342--- test/get-network-time 1970-01-01 00:00:00 +0000
343+++ test/get-network-time 2013-06-26 17:26:23 +0000
344@@ -0,0 +1,69 @@
345+#!/usr/bin/python
346+
347+import dbus
348+import sys
349+_dbus2py = {
350+ dbus.String : unicode,
351+ dbus.UInt32 : int,
352+ dbus.Int32 : int,
353+ dbus.Int16 : int,
354+ dbus.UInt16 : int,
355+ dbus.UInt64 : int,
356+ dbus.Int64 : int,
357+ dbus.Byte : int,
358+ dbus.Boolean : bool,
359+ dbus.ByteArray : str,
360+ dbus.ObjectPath : str
361+ }
362+
363+def dbus2py(d):
364+ t = type(d)
365+ if t in _dbus2py:
366+ return _dbus2py[t](d)
367+ if t is dbus.Dictionary:
368+ return dict([(dbus2py(k), dbus2py(v)) for k, v in d.items()])
369+ if t is dbus.Array and d.signature == "y":
370+ return "".join([chr(b) for b in d])
371+ if t is dbus.Array or t is list:
372+ return [dbus2py(v) for v in d]
373+ if t is dbus.Struct or t is tuple:
374+ return tuple([dbus2py(v) for v in d])
375+ return d
376+
377+def pretty(d):
378+ d = dbus2py(d)
379+ t = type(d)
380+
381+ if t in (dict, tuple, list) and len(d) > 0:
382+ if t is dict:
383+ d = ", ".join(["%s = %s" % (k, pretty(v))
384+ for k, v in d.items()])
385+ return "{ %s }" % d
386+
387+ d = " ".join([pretty(e) for e in d])
388+
389+ if t is tuple:
390+ return "( %s )" % d
391+
392+ if t is str:
393+ return "%s" % d
394+
395+ return str(d)
396+
397+bus = dbus.SystemBus()
398+
399+manager = dbus.Interface(bus.get_object("org.ofono", "/"),
400+ "org.ofono.Manager")
401+
402+modems = manager.GetModems()
403+
404+for path, properties in modems:
405+ if "org.ofono.NetworkTime" in properties["Interfaces"]:
406+ break
407+
408+net_time = dbus.Interface(bus.get_object('org.ofono', path),
409+ 'org.ofono.NetworkTime')
410+
411+time = net_time.GetNetworkTime()
412+
413+print pretty(time)
414
415=== modified file 'test/monitor-ofono'
416--- test/monitor-ofono 2013-01-28 16:25:32 +0000
417+++ test/monitor-ofono 2013-06-26 17:26:23 +0000
418@@ -74,6 +74,10 @@
419 print "{%s} [%s] %s %s (%s)" % (iface, path, member,
420 msg, pretty(args))
421
422+def network_time_changed(time, member, path, interface):
423+ iface = interface[interface.rfind(".") + 1:]
424+ print "{%s} [%s] %s %s" % (iface, path, member, pretty(time))
425+
426 def ussd(msg, member, path, interface):
427 iface = interface[interface.rfind(".") + 1:]
428 print "{%s} [%s] %s %s" % (iface, path, member, msg)
429@@ -150,5 +154,13 @@
430 path_keyword="path",
431 interface_keyword="interface")
432
433+ for member in ["NetworkTimeChanged"]:
434+ bus.add_signal_receiver(network_time_changed,
435+ bus_name="org.ofono",
436+ signal_name = member,
437+ member_keyword="member",
438+ path_keyword="path",
439+ interface_keyword="interface")
440+
441 mainloop = gobject.MainLoop()
442 mainloop.run()

Subscribers

People subscribed via source and target branches