Remove debian files
[platform/core/telephony/tel-plugin-indicator.git] / src / desc-indicator.c
1 /*
2  * tel-plugin-indicator
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <glib.h>
27
28 #include <tcore.h>
29 #include <server.h>
30 #include <plugin.h>
31 #include <storage.h>
32 #include <co_ps.h>
33 #include <co_context.h>
34
35 #define INDICATOR_UPDATE_INTERVAL       1
36 #define INDICATOR_PROCFILE              "/proc/net/dev"
37 #define INDICATOR_BUFF_SIZE             4096
38 #define DATABASE_PATH           "/opt/dbspace/.dnet.db"
39 #define NO_RX_PKT_TIMEOUT       30
40 //enum
41
42 typedef enum _cellular_state {
43         CELLULAR_OFF = 0x00,
44         CELLULAR_NORMAL_CONNECTED = 0x01,
45         CELLULAR_SECURE_CONNECTED = 0x02,
46         CELLULAR_USING = 0x03,
47 } cellular_state;
48
49 typedef enum _indicator_state {
50         INDICATOR_NORMAL = 0x00,
51         INDICATOR_RX = 0x01,
52         INDICATOR_TX = 0x02,
53         INDICATOR_RXTX = 0x03,
54 } indicator_state;
55
56 struct indicator_device_state {
57         gchar *devname;
58         gboolean active;
59         guint64 prev_rx;
60         guint64 prev_tx;
61         guint64 curr_rx;
62         guint64 curr_tx;
63 };
64
65 //global variable
66 static struct  indicator_device_state indicator_info = {
67         NULL,FALSE,0,0,0,0
68 };
69
70 static GSource* src;
71 static gboolean _indicator_update_callback(gpointer user_data);
72
73 static void _indicator_initialize(Server *s)
74 {
75         indicator_info.prev_rx = 0;
76         indicator_info.prev_tx = 0;
77         indicator_info.curr_rx = 0;
78         indicator_info.curr_tx = 0;
79 }
80
81 static gboolean _indicator_start_updater(Server *s)
82 {
83         Storage *strg_vconf;
84         gpointer vconf_handle;
85
86         dbg("indicator is started");
87
88         strg_vconf = tcore_server_find_storage(s, "vconf");
89         vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
90         if (!vconf_handle)
91                 err("fail to create vconf db_handle");
92
93         tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
94         tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
95
96         if(src != 0)
97                 return FALSE;
98
99         _indicator_initialize(s);
100
101         src = g_timeout_source_new_seconds(INDICATOR_UPDATE_INTERVAL);
102         g_source_set_callback(src, _indicator_update_callback, s, NULL);
103         g_source_set_priority(src, G_PRIORITY_HIGH);
104         g_source_attach(src, NULL);
105         g_source_unref(src);
106
107         return TRUE;
108 }
109
110 static gboolean _indicator_stop_updater(Server *s)
111 {
112         Storage *strg_vconf;
113         gpointer vconf_handle;
114         int t_rx = 0, t_tx = 0;
115
116         dbg("indicator is stopped");
117         strg_vconf = tcore_server_find_storage(s, "vconf");
118         vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
119         if (!vconf_handle)
120                 err("fail to create vconf db_handle");
121
122         tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_OFF);
123         tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
124
125         t_rx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV);
126         t_tx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT);
127         t_rx += (int)indicator_info.curr_rx;
128         t_tx += (int)indicator_info.curr_tx;
129
130         tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV, t_rx);
131         tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT, t_tx);
132         tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_RCV, (int)indicator_info.curr_rx);
133         tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_SNT, (int)indicator_info.curr_tx);
134
135         if(src == 0)
136                 return TRUE;
137
138         g_source_destroy(src);
139         src = 0;
140
141         return TRUE;
142 }
143
144 static gint _indicator_get_proc_ver(gchar *buff)
145 {
146         if (strstr(buff, "compressed")) return 3;
147         if (strstr(buff, "bytes")) return 2;
148         return 1;
149 }
150
151 static gint _indicator_get_pkt(gchar *buff, gint proc_ver, guint64 *rx_pkt, guint64 *tx_pkt)
152 {
153         gint result = -1;
154         gchar s_rx[100];
155         gchar s_tx[100];
156
157         memset(s_rx, 0 , 100);
158         memset(s_tx, 0 , 100);
159
160         if (buff == NULL)
161                 return result;
162
163         switch (proc_ver) {
164         case 3:
165                 result = sscanf(buff,
166                                 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
167                                 s_rx, s_tx);
168                 break;
169         case 2:
170                 result = sscanf(buff,
171                                 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
172                                 s_rx, s_tx);
173                 break;
174         case 1:
175                 result = sscanf(buff,
176                                 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
177                                 s_rx, s_tx);
178                 break;
179         default:
180                 dbg("stats unknown version");
181                 break;
182         }
183
184         *rx_pkt = g_ascii_strtoull(s_rx, NULL, 10);
185         *tx_pkt = g_ascii_strtoull(s_tx, NULL, 10);
186
187         return result;
188 }
189
190 static gboolean _indicator_get_pktcnt(gpointer user_data)
191 {
192         FILE *pf = NULL;
193         gint proc_ver = 0;
194         char *res;
195         gchar buff[INDICATOR_BUFF_SIZE];
196
197         pf = fopen(INDICATOR_PROCFILE, "r");
198         if (pf == NULL) {
199                 err("indicator fail to open file(%s), errno(%d)", INDICATOR_PROCFILE, errno);
200                 return FALSE;
201         }
202
203         res = fgets(buff, sizeof(buff), pf);
204         if (res == NULL)
205                 err("fegts fails");
206         res = fgets(buff, sizeof(buff), pf);
207         if (res == NULL)
208                 err("fegts fails");
209         proc_ver = _indicator_get_proc_ver(buff);
210
211         while (fgets(buff, sizeof(buff), pf)) {
212                 gint result = 0;
213                 guint64 rx_pkt = 0;
214                 guint64 tx_pkt = 0;
215                 gchar *ifname, *entry;
216
217                 ifname = buff;
218                 while (*ifname == ' ')
219                         ifname++;
220                 entry = strrchr(ifname, ':');
221                 *entry++ = 0;
222
223                 result = _indicator_get_pkt(entry, proc_ver, &rx_pkt, &tx_pkt);
224                 if (result <= 0) {
225                         err("stats fail to get proc field");
226                         fclose(pf);
227                         return FALSE;
228                 }
229
230                 if ( g_strcmp0(ifname, indicator_info.devname) == 0 ){
231                         indicator_info.prev_rx = indicator_info.curr_rx;
232                         indicator_info.prev_tx = indicator_info.curr_tx;
233                         indicator_info.curr_rx = rx_pkt;
234                         indicator_info.curr_tx = tx_pkt;
235                         break;
236                 }
237         }
238
239         fclose(pf);
240         return TRUE;
241 }
242
243 static gboolean _indicator_update(Server *s)
244 {
245         guint64 rx_changes = 0;
246         guint64 tx_changes = 0;
247         Storage *strg_vconf;
248         gpointer vconf_handle;
249
250         strg_vconf = tcore_server_find_storage(s, "vconf");
251         vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
252         if (!vconf_handle)
253                 err("fail to create vconf db_handle");
254
255         if(!indicator_info.active) return FALSE;
256
257         rx_changes = indicator_info.curr_rx - indicator_info.prev_rx;
258         tx_changes = indicator_info.curr_tx - indicator_info.prev_tx;
259
260         if (rx_changes != 0 || tx_changes != 0)
261                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_USING);
262         else
263                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
264
265         if (rx_changes > 0 && tx_changes > 0)
266                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RXTX);
267         else if (rx_changes > 0 && tx_changes == 0)
268                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RX);
269         else if (rx_changes == 0 && tx_changes > 0)
270                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_TX);
271         else
272                 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
273
274         return TRUE;
275 }
276
277 static gboolean _indicator_update_callback(gpointer user_data)
278 {
279         gboolean rv = FALSE;
280         Server *s = NULL;
281
282         s = (Server *)user_data;
283
284         rv = _indicator_get_pktcnt(NULL);
285         if(!rv){
286                 src = 0;
287                 return FALSE;
288         }
289
290         rv = _indicator_update(s);
291         if(!rv){
292                 src = 0;
293                 return FALSE;
294         }
295
296         return TRUE;
297 }
298
299 static enum tcore_hook_return __on_hook_powered(Server *s, CoreObject *source,
300                 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
301 {
302         struct tnoti_modem_power *modem_power = NULL;
303
304         dbg("powered event called");
305         g_return_val_if_fail(data != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
306
307         modem_power = (struct tnoti_modem_power *)data;
308         if ( modem_power->state == MODEM_STATE_ERROR ){
309                 indicator_info.active = FALSE;
310                 g_free(indicator_info.devname);
311                 indicator_info.devname = NULL;
312                 _indicator_stop_updater(s);
313         }
314
315         return TCORE_HOOK_RETURN_CONTINUE;
316 }
317
318 static enum tcore_hook_return __on_hook_callstatus(Server *s, CoreObject *source,
319                 enum tcore_notification_command command, unsigned int data_len, void *data,
320                 void *user_data)
321 {
322         unsigned int con_id = 0;
323         CoreObject *co_ps = NULL, *co_context = NULL;
324         struct tnoti_ps_call_status *cstatus = NULL;
325
326         dbg("call status event");
327         g_return_val_if_fail(data != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
328
329         co_ps = source;
330         dbg("ps object(%p)", co_ps);
331         co_context = tcore_ps_ref_context_by_role(co_ps, CONTEXT_ROLE_INTERNET);
332         con_id = tcore_context_get_id(co_context);
333         dbg("context(%p) con_id(%d)", co_context, con_id);
334
335         cstatus = (struct tnoti_ps_call_status *) data;
336         dbg("call status event cid(%d) state(%d)", cstatus->context_id, cstatus->state);
337
338         if(con_id != cstatus->context_id)
339                 return TCORE_HOOK_RETURN_CONTINUE;
340
341         if (cstatus->state == PS_DATA_CALL_CTX_DEFINED) {
342                 /* do nothing. */
343                 dbg("Just noti for PDP define complete, do nothing.");
344                 return TCORE_HOOK_RETURN_CONTINUE;
345         }
346         else if (cstatus->state == PS_DATA_CALL_CONNECTED) {
347                 indicator_info.active = TRUE;
348                 indicator_info.devname = tcore_context_get_ipv4_devname(co_context);
349                 _indicator_start_updater(s);
350                 return TCORE_HOOK_RETURN_CONTINUE;
351         }
352
353         indicator_info.active = FALSE;
354         g_free(indicator_info.devname);
355         indicator_info.devname = NULL;
356         _indicator_stop_updater(s);
357
358         return TCORE_HOOK_RETURN_CONTINUE;
359 }
360
361 static gboolean on_load()
362 {
363         dbg("Indicator plugin load!");
364         return TRUE;
365 }
366
367 static gboolean on_init(TcorePlugin *p)
368 {
369         Server *s = NULL;
370         s = tcore_plugin_ref_server(p);
371         tcore_server_add_notification_hook(s, TNOTI_MODEM_POWER, __on_hook_powered, NULL);
372         tcore_server_add_notification_hook(s, TNOTI_PS_CALL_STATUS, __on_hook_callstatus, NULL);
373         dbg("initialized Indicator plugin!");
374         return TRUE;
375 }
376
377 static void on_unload(TcorePlugin *p)
378 {
379         dbg("i'm unload!");
380         return;
381 }
382
383 struct tcore_plugin_define_desc plugin_define_desc =
384 {
385         .name = "INDICATOR",
386         .priority = TCORE_PLUGIN_PRIORITY_MID + 2,
387         .version = 1,
388         .load = on_load,
389         .init = on_init,
390         .unload = on_unload
391 };