1c99a183eb1a5ddb0cbd94c6acc7dfc72ec9e9e5
[platform/core/connectivity/net-config.git] / src / wifi-indicator.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/ioctl.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27 #include <linux/wireless.h>
28 #include <vconf.h>
29 #include <vconf-keys.h>
30
31 #include "log.h"
32 #include "util.h"
33 #include "netdbus.h"
34 #include "wifi-state.h"
35 #include "network-state.h"
36 #include "network-statistics.h"
37 #include "netsupplicant.h"
38 #include "wifi-indicator.h"
39
40 #define VCONFKEY_WIFI_SNR_MIN   -89
41
42 #if !defined TIZEN_WEARABLE
43 #define WIFI_INDICATOR_INTERVAL 1
44 #else
45 #define WIFI_INDICATOR_INTERVAL 10
46 #endif
47
48 #if defined TIZEN_WEARABLE
49 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1     (19200 * 1024)
50 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2     (2560 * 1024)
51 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3     (1536 * 1024)
52 #else
53 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1     (19200 * 1024)
54 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2     (7680 * 1024)
55 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3     (3840 * 1024)
56 #endif
57 #define NETCONFIG_PROCWIRELESS                                  "/proc/net/wireless"
58
59 static int netconfig_wifi_rssi = VCONFKEY_WIFI_SNR_MIN;
60 static guint netconfig_wifi_indicator_timer = 0;
61
62 int netconfig_wifi_get_rssi(void)
63 {
64         return netconfig_wifi_rssi;
65 }
66
67 static int __netconfig_wifi_update_and_get_rssi(void)
68 {
69         char *if_path = NULL;
70         GVariant *message = NULL;
71         GVariant *value = NULL;
72         gchar *key;
73         GVariantIter *iter;
74         GVariant *variant;
75         gint32 key_value;
76         int rssi_dbm = VCONFKEY_WIFI_SNR_MIN;
77
78         if_path = netconfig_wifi_get_supplicant_interface();
79         if (if_path == NULL) {
80                 ERR("Fail to get wpa_supplicant DBus path");
81                 return 0;
82         }
83
84         message = netconfig_invoke_dbus_method(SUPPLICANT_SERVICE, if_path,
85                                 SUPPLICANT_INTERFACE ".Interface", "SignalPoll", NULL);
86
87         g_free(if_path);
88         if (message == NULL) {
89                 ERR("Fail to get SignalPoll from wpa_supplicant");
90                 return 0;
91         }
92
93         g_variant_get(message, "(v)", &value);
94
95         g_variant_get(value, "a{sv}", &iter);
96         if (iter == NULL) {
97                 ERR("Fail to get list from SignalPoll");
98                 return 0;
99         }
100
101         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
102                 key_value = g_variant_get_int32(variant);
103
104                 if (g_strcmp0(key, "rssi") == 0) {
105                         rssi_dbm = (int)key_value;
106                         DBG("Currently signal dbm value [%d]", rssi_dbm);
107                         g_variant_unref(variant);
108                         g_free(key);
109                         break;
110                 }
111         }
112
113         g_variant_iter_free(iter);
114
115         if (value)
116                 g_variant_unref(value);
117
118         netconfig_wifi_rssi = rssi_dbm;
119
120         return rssi_dbm;
121 }
122
123 int netconfig_wifi_rssi_level(const int rssi_dbm)
124 {
125         int snr_level = 0;
126
127         /* Wi-Fi Signal Strength Display
128          *
129          * Excellent :  -63 ~
130          * Good:                -74 ~ -64
131          * Weak:                -82 ~ -75
132          * Very weak:           ~ -83
133          */
134         if (rssi_dbm >= -63)
135                 snr_level = 4;
136         else if (rssi_dbm >= -74)
137                 snr_level = 3;
138         else if (rssi_dbm >= -82)
139                 snr_level = 2;
140         else
141                 snr_level = 1;
142
143         return snr_level;
144 }
145
146 static void __netconfig_wifi_set_rssi_level(const int snr_level)
147 {
148         static int last_snr_level = 0;
149
150         if (snr_level != last_snr_level) {
151                 netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, snr_level);
152                 last_snr_level = snr_level;
153         }
154 }
155
156 static void __netconfig_wifi_data_activity_booster(int level)
157 {
158         gboolean reply = FALSE;
159         GVariant *params = NULL;
160         int level1 = 1;
161         int level2 = 2;
162         int level3 = 3;
163
164         int lock = 2000;
165         int unlock = 0;
166
167         static int old_level = 0;
168
169         if (level < 0)
170                 return;
171
172         if (level > 0) {
173                 /* enable booster */
174                 switch (level) {
175                 case 1:
176                         params = g_variant_new("(ii)", level1, lock);
177                         break;
178                 case 2:
179                         params = g_variant_new("(ii)", level2, lock);
180                         break;
181                 case 3:
182                         params = g_variant_new("(ii)", level3, lock);
183                         break;
184                 default:
185                         ERR("Invalid level");
186                         return;
187                 }
188
189                 reply = netconfig_invoke_dbus_method_nonblock(
190                                 "org.tizen.system.deviced",
191                                 "/Org/Tizen/System/DeviceD/PmQos",
192                                 "org.tizen.system.deviced.PmQos",
193                                 "WifiThroughput",
194                                 params,
195                                 NULL);
196                 if (reply != TRUE)
197                         return;
198         }
199
200         /* disable previous booster */
201         if (old_level == 0 || old_level == level)
202                 return;
203
204         switch (old_level) {
205         case 1:
206                 params = g_variant_new("(ii)", level1, unlock);
207                 break;
208         case 2:
209                 params = g_variant_new("(ii)", level2, unlock);
210                 break;
211         case 3:
212                 params = g_variant_new("(ii)", level3, unlock);
213                 break;
214         default:
215                 ERR("Invalid level");
216                 return;
217         }
218
219         reply = netconfig_invoke_dbus_method_nonblock(
220                         "org.tizen.system.deviced",
221                         "/Org/Tizen/System/DeviceD/PmQos",
222                         "org.tizen.system.deviced.PmQos",
223                         "WifiThroughput",
224                         params,
225                         NULL);
226         if (reply != TRUE)
227                 return;
228
229         old_level = level;
230 }
231
232 static void __netconfig_wifi_update_indicator(void)
233 {
234         static int last_transfer_state = 0;
235         static guint64 netconfig_wifi_tx_bytes = 0;
236         static guint64 netconfig_wifi_rx_bytes = 0;
237         static int booster_tic = 0;
238         static int old_level = 0;
239         int booster_level = 0;
240         guint64 tx, rx, tx_diff, rx_diff;
241         int transfer_state;
242
243         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE) {
244                 tx_diff = tx - netconfig_wifi_tx_bytes;
245                 rx_diff = rx - netconfig_wifi_rx_bytes;
246
247                 if (tx_diff > 0) {
248                         if (rx_diff > 0)
249                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TXRX;
250                         else
251                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TX;
252                 } else {
253                         if (rx_diff > 0)
254                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_RX;
255                         else
256                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_NONE;
257                 }
258
259                 if (transfer_state != last_transfer_state) {
260                         netconfig_set_vconf_int(VCONFKEY_WIFI_TRANSFER_STATE, transfer_state);
261                         last_transfer_state = transfer_state;
262                 }
263
264                 /* NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER */
265                 if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 ||
266                         rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1)
267                         booster_level = 1;
268                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 ||
269                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2)
270                         booster_level = 2;
271                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 ||
272                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3)
273                         booster_level = 3;
274
275                 if (old_level == booster_level) {
276                         if (--booster_tic <= 0) {
277                                 __netconfig_wifi_data_activity_booster(booster_level);
278
279                                 booster_tic = 2;
280                         }
281                 } else {
282                         __netconfig_wifi_data_activity_booster(booster_level);
283
284                         if (booster_level > 0)
285                                 booster_tic = 2;
286                         else
287                                 booster_tic = 0;
288                 }
289
290                 old_level = booster_level;
291
292                 netconfig_wifi_tx_bytes = tx;
293                 netconfig_wifi_rx_bytes = rx;
294         }
295 }
296
297 static gboolean __wifi_indicator_monitor(gpointer data)
298 {
299         int rssi_dbm = 0;
300         int snr_level = 0;
301         int pm_state = VCONFKEY_PM_STATE_NORMAL;
302
303         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
304                 return FALSE;
305
306         /* In case of LCD off, we don't need to update Wi-Fi indicator */
307         netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
308         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
309                 return TRUE;
310
311         rssi_dbm = __netconfig_wifi_update_and_get_rssi();
312         /* INFO("%d dbm", rssi_dbm); */
313         snr_level = netconfig_wifi_rssi_level(rssi_dbm);
314         __netconfig_wifi_set_rssi_level(snr_level);
315
316         __netconfig_wifi_update_indicator();
317
318         return TRUE;
319 }
320
321 void netconfig_wifi_indicator_start(void)
322 {
323         INFO("Start Wi-Fi indicator");
324
325         netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
326         netconfig_start_timer_seconds(WIFI_INDICATOR_INTERVAL, __wifi_indicator_monitor, NULL, &netconfig_wifi_indicator_timer);
327 }
328
329 void netconfig_wifi_indicator_stop(void)
330 {
331         INFO("Stop Wi-Fi indicator");
332
333         netconfig_stop_timer(&netconfig_wifi_indicator_timer);
334
335         netconfig_wifi_rssi = VCONFKEY_WIFI_SNR_MIN;
336 }