Check SSID when loading wifi configuration file
[platform/core/connectivity/net-config.git] / src / wifi-indicator.c
old mode 100644 (file)
new mode 100755 (executable)
index 5d7d03a..06ac9da
@@ -1,7 +1,7 @@
 /*
  * Network Configuration Module
  *
- * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,9 @@
  *
  */
 
+#include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>
 #include "log.h"
 #include "util.h"
 #include "netdbus.h"
+#include "wifi-state.h"
+#include "network-state.h"
+#include "network-statistics.h"
 #include "netsupplicant.h"
 #include "wifi-indicator.h"
 
 #define VCONFKEY_WIFI_SNR_MIN  -89
 
-#define NETCONFIG_WIFI_INDICATOR_INTERVAL      3
+#if !defined TIZEN_WEARABLE
+#define WIFI_INDICATOR_INTERVAL        2
+#else
+#define WIFI_INDICATOR_INTERVAL        10
+#endif
+
+#if defined TIZEN_WEARABLE
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1    (19200 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2    (2560 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3    (1536 * 1024)
+#else
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1    (19200 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2    (7680 * 1024)
+#define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3    (3840 * 1024)
+#endif
+#define NETCONFIG_PROCWIRELESS                                 "/proc/net/wireless"
+
+typedef struct {
+       char *interface_name;
+       char *default_path;
+       int last_snr_level;
+} rssi_data_s;
 
-static guint netconfig_wifi_indicator_timer = 0;
+static GSList *g_rssi_list = NULL;
+static guint netconfig_wifi_statistics_timer = 0;
 
-#if defined NL80211
-static int __netconfig_wifi_get_signal(const char *object_path)
+static rssi_data_s *__create_rssi_data(const char *interface_name)
 {
-       DBusConnection *connection = NULL;
-       DBusMessage *message = NULL;
-       DBusMessageIter iter;
-       int rssi_dbm = 0;
-       int MessageType = 0;
-
-       if (object_path == NULL) {
-               ERR("Error!!! path is NULL");
-               goto error;
+       rssi_data_s *rssi_data = g_try_malloc0(sizeof(rssi_data_s));
+       if (!rssi_data) {
+               ERR("Memory allocation failed");
+               return NULL;
        }
 
-       connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-       if (connection == NULL) {
-               ERR("Error!!! Failed to get system DBus");
-               goto error;
-       }
+       rssi_data->interface_name = g_strdup(interface_name);
 
-       message = netconfig_supplicant_invoke_dbus_method(
-                       SUPPLICANT_SERVICE, connection, object_path,
-                       SUPPLICANT_INTERFACE ".Interface", "GetLinkSignal",
-                       NULL);
+       g_rssi_list = g_slist_append(g_rssi_list, rssi_data);
 
-       if (message == NULL) {
-               ERR("Error!!! Failed to get service properties");
-               goto error;
-       }
+       return rssi_data;
+}
 
-       MessageType = dbus_message_get_type(message);
+static rssi_data_s *__get_rssi_data(const char *interface_name)
+{
+       GSList *list;
+       rssi_data_s *rssi_data = NULL;
 
-       if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
-               const char *err_msg = dbus_message_get_error_name(message);
-               ERR("Error!!! Error message received [%s]", err_msg);
-               goto error;
+       for (list = g_rssi_list; list; list = list->next) {
+               rssi_data = list->data;
+               if (g_strcmp0(rssi_data->interface_name, interface_name) == 0)
+                       return rssi_data;
        }
 
-       dbus_message_iter_init(message, &iter);
-
-       if ((MessageType = dbus_message_iter_get_arg_type(&iter)) == DBUS_TYPE_INT32)
-               dbus_message_iter_get_basic(&iter, &rssi_dbm);
-       else
-               goto error;
+       return rssi_data;
+}
 
-       dbus_message_unref(message);
-       dbus_connection_unref(connection);
+static void __set_rssi_data_default_path(const char *interface_name,
+               const char *path)
+{
+       rssi_data_s *rssi_data = __get_rssi_data(interface_name);
+       if (rssi_data == NULL)
+               return;
 
-       return rssi_dbm;
+       rssi_data->default_path = g_strdup(path);
+}
 
-error:
-       if (message != NULL)
-               dbus_message_unref(message);
+static void __destroy_rssi_data(const char *interface_name)
+{
+       rssi_data_s *rssi_data = __get_rssi_data(interface_name);
 
-       if (connection != NULL)
-               dbus_connection_unref(connection);
+       if (!rssi_data)
+               return;
 
-       return VCONFKEY_WIFI_SNR_MIN;
+       g_rssi_list = g_slist_remove(g_rssi_list, rssi_data);
+       g_free(rssi_data->interface_name);
+       g_free(rssi_data->default_path);
+       g_free(rssi_data);
 }
 
-static int __netconfig_wifi_get_rssi_from_supplicant(void)
+static int __netconfig_wifi_convert_dbm_to_level_24(int rssi_dbm)
 {
-       int rssi_dbm =0;
+       int rssi_level = 0;
 
-       char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
-       char *path_ptr = &object_path[0];
-
-       if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
-               DBG("Fail to get wpa_supplicant DBus path");
-               return VCONFKEY_WIFI_SNR_MIN;
-       }
+       /* Wi-Fi Signal Strength Display (for 2.4G (dB))
+        *
+        * Excellent :     ~ -63
+        * Good      : -64 ~ -74
+        * Weak      : -75 ~ -82
+        * Very weak : -83 ~ -88
+        * No signal : -89 ~
+        */
 
-       rssi_dbm = __netconfig_wifi_get_signal((const char *)path_ptr);
+       if (rssi_dbm >= -63)
+               rssi_level = 4;
+       else if (rssi_dbm >= -74)
+               rssi_level = 3;
+       else if (rssi_dbm >= -82)
+               rssi_level = 2;
+       else if (rssi_dbm >= -88)
+               rssi_level = 1;
+       else
+               rssi_level = 0;
 
-       return rssi_dbm;
+       return rssi_level;
 }
-#endif /* #if defined NL80211 */
 
-#if !defined NL80211
-static int __netconfig_wifi_get_rssi_from_system(void)
+static int __netconfig_wifi_convert_dbm_to_level_50(int rssi_dbm)
 {
-       int rssi_dbm = 0;
-       char ifname[16] = { 0, };
-       char *ifname_ptr = &ifname[0];
-
-       int fd = -1;
-       struct iwreq wifi_req;
-       struct iw_statistics stats;
-       unsigned int iw_stats_len = sizeof(struct iw_statistics);
-
-       if (netconfig_wifi_get_ifname(&ifname_ptr) != TRUE) {
-               DBG("Fail to get Wi-Fi ifname from wpa_supplicant: %s", ifname_ptr);
-               return VCONFKEY_WIFI_SNR_MIN;
-       }
-
-       /* Set device name */
-       memset(wifi_req.ifr_name, 0, sizeof(wifi_req.ifr_name));
-       strncpy(wifi_req.ifr_name, ifname, sizeof(wifi_req.ifr_name) - 1);
-       wifi_req.ifr_name[sizeof(wifi_req.ifr_name) - 1] = '\0';
+       int rssi_level = 0;
 
-       wifi_req.u.data.pointer = (caddr_t) &stats;
-       wifi_req.u.data.length = iw_stats_len;
-       wifi_req.u.data.flags = 1;      /* Clear updated flag */
+       /* Wi-Fi Signal Strength Display (for 5G (dB))
+        *
+        * Excellent :     ~ -67
+        * Good      : -68 ~ -76
+        * Weak      : -77 ~ -82
+        * Very weak : -83 ~ -88
+        * No signal : -89 ~
+        */
 
-       if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
-               DBG("Fail to open socket to get rssi");
-               return VCONFKEY_WIFI_SNR_MIN;
-       }
+       if (rssi_dbm >= -67)
+               rssi_level = 4;
+       else if (rssi_dbm >= -76)
+               rssi_level = 3;
+       else if (rssi_dbm >= -82)
+               rssi_level = 2;
+       else if (rssi_dbm >= -88)
+               rssi_level = 1;
+       else
+               rssi_level = 0;
 
-       memset(&stats, 0, iw_stats_len);
+       return rssi_level;
+}
 
-       if (ioctl(fd, SIOCGIWSTATS, &wifi_req) < 0) {
-               DBG("Fail to execute ioctl for SIOCGIWSTATS");
-               close(fd);
+static int __netconfig_wifi_get_rssi_level(const int rssi_dbm)
+{
+       int snr_level = 0;
+       int freq = 0;
+       int ret = 0;
 
-               return VCONFKEY_WIFI_SNR_MIN;
-       }
-       close(fd);
+       ret = netconfig_vconf_get_int("memory/private/wifi/frequency", &freq);
 
-       rssi_dbm = stats.qual.level - 255; /** signed integer, so 255 */
+       if (!ret && freq > 4900)
+               snr_level = __netconfig_wifi_convert_dbm_to_level_50(rssi_dbm);
+       else
+               snr_level = __netconfig_wifi_convert_dbm_to_level_24(rssi_dbm);
 
-       return rssi_dbm;
+       return snr_level;
 }
-#endif /* #if !defined NL80211 */
 
-int netconfig_wifi_get_rssi(void)
+static void __netconfig_wifi_set_rssi_level(const char *interface_name,
+               const char *path, const int snr_level)
 {
-       int rssi_dbm = 0;
-
-       /* There are two ways to get Wi-Fi RSSI:
-        *  - WEXT interface, get DBus path of wpa_supplicant,
-        *  and get Wi-Fi interface name e.g. wlan0 from wpa_supplicant.
-        *  IOCTL with ifname will return RSSI dB.
-        *  - NL80211 interface, get DBus path of wpa_supplicant,
-        *  and get RSSI from wpa_supplicant directly.
-        *  However, in this case wpa_supplicant needs some modification
-        *  to get RSSI from DBus interface. */
-
-#if defined NL80211
-       rssi_dbm = __netconfig_wifi_get_rssi_from_supplicant();
-#else
-       rssi_dbm = __netconfig_wifi_get_rssi_from_system();
-#endif
+       rssi_data_s *rssi_data = NULL;
+       const char *default_ifname = NULL;
+
+       rssi_data = __get_rssi_data(interface_name);
+       if (rssi_data == NULL)
+               return;
+
+       if (snr_level != rssi_data->last_snr_level) {
+               default_ifname = netconfig_get_default_ifname();
+               if (g_strcmp0(default_ifname, interface_name) == 0)
+                       netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, snr_level, FALSE);
+
+               if (g_strcmp0(rssi_data->default_path, path) == 0) {
+                       wifi_emit_rssi_changed((Wifi *)get_wifi_object(), interface_name, snr_level);
+
+                       netconfig_battery_update_wifi_rssi(snr_level);
 
-       return rssi_dbm;
+                       rssi_data->last_snr_level = snr_level;
+               }
+       }
 }
 
-static void __netconfig_wifi_set_rssi_level(int rssi_dbm)
+static void __netconfig_wifi_data_activity_booster(int level)
 {
-       int snr_level = 0;
-       static int last_snr_level = 0;
+       gboolean reply = FALSE;
+       GVariant *params = NULL;
+       int level1 = 1;
+       int level2 = 2;
+       int level3 = 3;
+
+       int lock = 2000;
+       int unlock = 0;
+
+       static int old_level = 0;
+
+       if (level < 0)
+               return;
+
+       if (level > 0) {
+               /* enable booster */
+               switch (level) {
+               case 1:
+                       params = g_variant_new("(ii)", level1, lock);
+                       break;
+               case 2:
+                       params = g_variant_new("(ii)", level2, lock);
+                       break;
+               case 3:
+                       params = g_variant_new("(ii)", level3, lock);
+                       break;
+               default:
+                       ERR("Invalid level");
+                       return;
+               }
+
+               reply = netconfig_invoke_dbus_method_nonblock(
+                               "org.tizen.system.deviced",
+                               "/Org/Tizen/System/DeviceD/PmQos",
+                               "org.tizen.system.deviced.PmQos",
+                               "WifiThroughput",
+                               params,
+                               NULL,
+                               NULL);
+               if (reply != TRUE)
+                       return;
+       }
 
-       /* Wi-Fi Signal Strength Display
-        *
-        * Excellent :  -63 ~
-        * Good:                -74 ~ -64
-        * Weak:                -82 ~ -75
-        * Very weak:           ~ -83
-        */
-       if (rssi_dbm >= -63)
-               snr_level = 4;
-       else if (rssi_dbm >= -74)
-               snr_level = 3;
-       else if (rssi_dbm >= -82)
-               snr_level = 2;
-       else
-               snr_level = 1;
+       /* disable previous booster */
+       if (old_level == 0 || old_level == level)
+               return;
+
+       switch (old_level) {
+       case 1:
+               params = g_variant_new("(ii)", level1, unlock);
+               break;
+       case 2:
+               params = g_variant_new("(ii)", level2, unlock);
+               break;
+       case 3:
+               params = g_variant_new("(ii)", level3, unlock);
+               break;
+       default:
+               ERR("Invalid level");
+               return;
+       }
 
-       if (snr_level != last_snr_level) {
-               INFO("Wi-Fi RSSI: %d dB, %d level", rssi_dbm, snr_level);
+       reply = netconfig_invoke_dbus_method_nonblock(
+                       "org.tizen.system.deviced",
+                       "/Org/Tizen/System/DeviceD/PmQos",
+                       "org.tizen.system.deviced.PmQos",
+                       "WifiThroughput",
+                       params,
+                       NULL,
+                       NULL);
+       if (reply != TRUE)
+               return;
+
+       old_level = level;
+}
+
+static void __netconfig_wifi_get_statistics(void)
+{
+       static int last_transfer_state = 0;
+       static int booster_tic = 0;
+       static int old_level = 0;
+       int booster_level = 0;
+       guint64 tx, rx;
+       int transfer_state;
+
+       if (netconfig_wifi_get_bytes_statistics(&tx, &rx, TRUE))
+               netconfig_wifi_set_bytes_pkt_vconf(tx, rx, FALSE);
+
+       netconfig_wifi_get_bytes_default_iface(&tx, &rx);
+
+       if (tx > 0) {
+               if (rx > 0)
+                       transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TXRX;
+               else
+                       transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TX;
+       } else {
+               if (rx > 0)
+                       transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_RX;
+               else
+                       transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_NONE;
+       }
 
-               vconf_set_int(VCONFKEY_WIFI_STRENGTH, snr_level);
+       if (transfer_state != last_transfer_state) {
+               netconfig_set_vconf_int(VCONFKEY_WIFI_TRANSFER_STATE, transfer_state, FALSE);
+               last_transfer_state = transfer_state;
+       }
 
-               last_snr_level = snr_level;
+       /* NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER */
+       if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 ||
+               rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1)
+               booster_level = 1;
+       else if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 ||
+                       rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2)
+               booster_level = 2;
+       else if (tx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 ||
+                       rx >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3)
+               booster_level = 3;
+
+       if (old_level == booster_level) {
+               if (--booster_tic <= 0) {
+                       __netconfig_wifi_data_activity_booster(booster_level);
+
+                       booster_tic = 2;
+               }
+       } else {
+               __netconfig_wifi_data_activity_booster(booster_level);
+
+               if (booster_level > 0)
+                       booster_tic = 2;
+               else
+                       booster_tic = 0;
        }
+
+       old_level = booster_level;
 }
 
-static gboolean __netconfig_wifi_indicator_monitor(gpointer data)
+static gboolean __netconfig_wifi_update_statistics(gpointer data)
 {
-       int rssi_dbm = 0;
        int pm_state = VCONFKEY_PM_STATE_NORMAL;
+       char *interface_name = data;
+
+       if (wifi_state_get_service_state(interface_name) != NETCONFIG_WIFI_CONNECTED) {
+               g_free(interface_name);
+               return FALSE;
+       }
 
        /* In case of LCD off, we don't need to update Wi-Fi indicator */
-       vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
+       netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
        if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
                return TRUE;
 
-       rssi_dbm = netconfig_wifi_get_rssi();
-
-       __netconfig_wifi_set_rssi_level(rssi_dbm);
+       __netconfig_wifi_get_statistics();
 
        return TRUE;
 }
 
-void netconfig_wifi_indicator_start(void)
+void netconfig_wifi_indicator_update(const char *interface_name,
+               const char *path, int rssi_dbm)
 {
+       int pm_state = VCONFKEY_PM_STATE_NORMAL;
+       int snr_level = 0;
+
+       /* In case of LCD off, we don't need to update Wi-Fi indicator */
+       netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
+       if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
+               return;
+
+       snr_level = __netconfig_wifi_get_rssi_level(rssi_dbm);
+       __netconfig_wifi_set_rssi_level(interface_name, path, snr_level);
+}
+
+void netconfig_wifi_indicator_start(const char *interface_name,
+               const char *profile_path)
+{
+       const char *default_ifname = NULL;
+
        INFO("Start Wi-Fi indicator");
 
-       vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
+       __create_rssi_data(interface_name);
 
-       netconfig_start_timer_seconds(
-                       NETCONFIG_WIFI_INDICATOR_INTERVAL,
-                       __netconfig_wifi_indicator_monitor,
-                       NULL,
-                       &netconfig_wifi_indicator_timer);
+       if (profile_path)
+               __set_rssi_data_default_path(interface_name, profile_path);
+
+       default_ifname = netconfig_get_default_ifname();
+       if (g_strcmp0(default_ifname, interface_name) == 0)
+               netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX, FALSE);
+
+       wifi_emit_rssi_changed((Wifi *)get_wifi_object(),
+               interface_name, VCONFKEY_WIFI_STRENGTH_MAX);
+
+       if (netconfig_wifi_statistics_timer == 0) {
+               netconfig_wifi_reset_last_bytes();
+               netconfig_start_timer_seconds(WIFI_INDICATOR_INTERVAL,
+                       __netconfig_wifi_update_statistics, g_strdup(interface_name),
+                       &netconfig_wifi_statistics_timer);
+       }
+
+       netconfig_battery_update_wifi_rssi(VCONFKEY_WIFI_STRENGTH_MAX);
 }
 
-void netconfig_wifi_indicator_stop(void)
+void netconfig_wifi_indicator_stop(const char *interface_name)
 {
+       int wifi_state = 0;
+       guint64 tx, rx;
+
        INFO("Stop Wi-Fi indicator");
 
-       vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
+       netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
+
+       if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
+               if (netconfig_wifi_get_bytes_statistics(&tx, &rx, TRUE))
+                       netconfig_wifi_set_bytes_pkt_vconf(tx, rx, FALSE);
+
+               netconfig_stop_timer(&netconfig_wifi_statistics_timer);
+       }
 
-       netconfig_stop_timer(&netconfig_wifi_indicator_timer);
+       __destroy_rssi_data(interface_name);
 }