Timeout(Auto disconnection) feature is implemented
authorSeungyoun Ju <sy39.ju@samsung.com>
Thu, 6 Dec 2012 11:30:27 +0000 (20:30 +0900)
committerSeungyoun Ju <sy39.ju@samsung.com>
Fri, 7 Dec 2012 04:47:10 +0000 (13:47 +0900)
- Issues
  Because battery consumption, Wi-Fi / Bluetooth tethering should
  be turned off when there is no connection during specific duration.

- Fix description
  Wi-Fi / Bluetooth tethering will be turned off automatically
  when there is no connection during 20 Minutes.

- Known issue
  Ticker notification should be implemented

Change-Id: I826461fce0a6517785900399403047b0c027a980

include/mobileap.h
include/mobileap_agent.h
include/mobileap_common.h
include/mobileap_handler.h
src/mobileap_agent.c
src/mobileap_bluetooth.c
src/mobileap_common.c
src/mobileap_handler.c
src/mobileap_main.c
src/mobileap_wifi.c

index 84bb29b..18cce14 100644 (file)
@@ -64,6 +64,7 @@ extern "C" {
 #define SIGNAL_NAME_DHCP_STATUS                "dhcp_status"
 
 #define SIGNAL_MSG_NOT_AVAIL_INTERFACE "Interface is not available"
+#define SIGNAL_MSG_TIMEOUT             "There is no connection for a while"
 
 #define DNSMASQ_LEASES_FILE            "/var/lib/misc/dnsmasq.leases"
 #define IP_USB_SUBNET                  "192.168.129"
index b67ecd4..fd86779 100644 (file)
 
 #define DNSMASQ_DBUS_INTERFACE "uk.org.thekelleys.dnsmasq"
 
-#define PROC_NET_DEV           "/proc/net/dev"
-#define MAX_TRANSFER_CHECK_COUNT       180     /* 30 minutes */
+#define PROC_NET_DEV                   "/proc/net/dev"
+#define TETHERING_CONN_TIMEOUT         (1200000)       /* 20 Mins */
 #define CHECK_NET_STATE_RETRY_COUNT    5
 #define PSK_ITERATION_COUNT            4096
 
index 04aecc4..c7e432e 100644 (file)
@@ -45,7 +45,7 @@ int _remove_station_info(gconstpointer data, GCompareFunc func);
 int _remove_station_info_all(mobile_ap_type_e type);
 int _get_station_info(gconstpointer data, GCompareFunc func,
                mobile_ap_station_info_t **si);
-int _get_station_count(int *count);
+int _get_station_count(gconstpointer data, GCompareFunc func, int *count);
 int _station_info_foreach(GFunc func, void *user_data);
 int _add_data_usage_rule(const char *src, const char *dest);
 int _del_data_usage_rule(const char *src, const char *dest);
index 13375ef..4ed5640 100644 (file)
 #ifndef __MOBILEAP_HANDLER_H__
 #define __MOBILEAP_HANDLER_H__
 
-
 void _register_vconf_cb(void *user_data);
 void _unregister_vconf_cb(void *user_data);
 
+void _init_timeout_cb(mobile_ap_type_e type, void *user_data);
+void _start_timeout_cb(mobile_ap_type_e type);
+void _stop_timeout_cb(mobile_ap_type_e type);
+void _deinit_timeout_cb(mobile_ap_type_e type);
 
 #endif
index 1e0eae8..340282d 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "mobileap_common.h"
 #include "mobileap_agent.h"
+#include "mobileap_handler.h"
 
 static pid_t dnsmasq_pid = 0;
 static pid_t hostapd_pid = 0;
@@ -472,6 +473,7 @@ static gboolean __hostapd_monitor_cb(GIOChannel *source)
        char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
        char *pbuf = NULL;
        gsize read = 0;
+       int n_station = 0;
 
 #if !GLIB_CHECK_VERSION(2, 31, 0)
        int ret = 0;
@@ -518,6 +520,11 @@ static gboolean __hostapd_monitor_cb(GIOChannel *source)
                DBG("Disconnected station MAC : %s\n", pbuf);
                _remove_station_info(pbuf, _slist_find_station_by_mac);
 
+               _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
+                               _slist_find_station_by_interface, &n_station);
+               if (n_station == 0)
+                       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
                return TRUE;
        } else {
                DBG("Event is not handled\n");
index 7e0edd8..be63223 100644 (file)
@@ -31,6 +31,7 @@
 #include "mobileap_agent.h"
 #include "mobileap_common.h"
 #include "mobileap_bluetooth.h"
+#include "mobileap_handler.h"
 
 typedef struct {
        bt_device_info_s *info;
@@ -147,11 +148,13 @@ static void __bt_nap_connection_changed(bool connected, const char *remote_addre
        __bt_remote_device_s *remote;
        bt_device_info_s *info;
        int ret;
+       int n_station = 0;
 
        DBG("Remote address : %s, Interface : %s, %s\n",
                        remote_address, interface_name,
                        connected ? "Connected" : "Disconnected");
 
+
        if (connected) {
                ret = bt_adapter_get_bonded_device_info(remote_address, &info);
                if (ret != BT_ERROR_NONE) {
@@ -172,8 +175,14 @@ static void __bt_nap_connection_changed(bool connected, const char *remote_addre
                }
        } else {
                _remove_station_info(remote_address, _slist_find_station_by_mac);
-               if (__del_bt_remote(remote_address) == FALSE)
+               if (__del_bt_remote(remote_address) == FALSE) {
                        ERR("__del_bt_remote is failed\n");
+               }
+
+               _get_station_count((gconstpointer)MOBILE_AP_TYPE_BT,
+                               _slist_find_station_by_interface, &n_station);
+               if (n_station == 0)
+                       _start_timeout_cb(MOBILE_AP_TYPE_BT);
        }
 
        return;
@@ -310,6 +319,7 @@ mobile_ap_error_code_e _disable_bt_tethering(MobileAPObject *obj)
 
        _remove_station_info_all(MOBILE_AP_TYPE_BT);
        __del_bt_remote_all();
+       _deinit_timeout_cb(MOBILE_AP_TYPE_BT);
 
        _deinit_tethering(obj);
        _mobileap_clear_state(MOBILE_AP_STATE_BT);
@@ -406,6 +416,9 @@ gboolean mobileap_enable_bt_tethering(MobileAPObject *obj,
                goto FAIL;
        }
 
+       _init_timeout_cb(MOBILE_AP_TYPE_BT, (void *)obj);
+       _start_timeout_cb(MOBILE_AP_TYPE_BT);
+
        _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
        dbus_g_method_return(context, MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
        return TRUE;
index 084f965..128008f 100644 (file)
@@ -45,7 +45,7 @@
 
 extern DBusConnection *mobileap_conn;
 
-static GSList *station_list = NULL;;
+static GSList *station_list = NULL;
 
 gint _slist_find_station_by_interface(gconstpointer a, gconstpointer b)
 {
@@ -281,14 +281,24 @@ int _get_station_info(gconstpointer data, GCompareFunc func,
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _get_station_count(int *count)
+int _get_station_count(gconstpointer data, GCompareFunc func, int *count)
 {
        if (count == NULL) {
                ERR("Invalid param\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       *count = g_slist_length(station_list);
+       GSList *l = station_list;
+       int _count = 0;
+
+       for (_count = 0; l != NULL; _count++, l = g_slist_next(l)) {
+               l = g_slist_find_custom(l, data, func);
+               if (l == NULL)
+                       break;
+       }
+
+       *count = _count;
+       DBG("Station count : %d\n", *count);
 
        return MOBILE_AP_ERROR_NONE;
 }
index 682f4e7..4ee8ab1 100644 (file)
 #include "mobileap_wifi.h"
 #include "mobileap_usb.h"
 
+typedef struct {
+       guint src_id;
+       GSourceFunc func;
+       void *user_data;
+} sp_timeout_handler_t;
+
+static gboolean __wifi_timeout_cb(gpointer user_data);
+static gboolean __bt_timeout_cb(gpointer user_data);
+
+static sp_timeout_handler_t sp_timeout_handler[MOBILE_AP_TYPE_MAX] = {
+       {0, __wifi_timeout_cb, NULL},
+       {0, NULL, NULL},
+       {0, __bt_timeout_cb, NULL}};
 
 static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
 {
@@ -179,3 +192,132 @@ void _unregister_vconf_cb(void *user_data)
        return;
 }
 
+static gboolean __wifi_timeout_cb(gpointer data)
+{
+       DBG("+\n");
+       if (data == NULL) {
+               ERR("data is NULL\n");
+               return FALSE;
+       }
+
+       MobileAPObject *obj = (MobileAPObject *)data;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI) == FALSE) {
+               ERR("There is no conn. via Wi-Fi tethernig. But nothing to do\n");
+               return FALSE;
+       }
+
+       _disable_wifi_tethering(obj);
+       _emit_mobileap_dbus_signal(obj,
+                       E_SIGNAL_WIFI_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
+
+       DBG("-\n");
+       return FALSE;
+}
+
+static gboolean __bt_timeout_cb(gpointer data)
+{
+       DBG("+\n");
+       if (data == NULL) {
+               ERR("data is NULL\n");
+               return FALSE;
+       }
+
+       MobileAPObject *obj = (MobileAPObject *)data;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_BT) == FALSE) {
+               ERR("There is no conn. via BT tethering. But nothing to do\n");
+               return FALSE;
+       }
+
+       _disable_bt_tethering(obj);
+       _emit_mobileap_dbus_signal(obj,
+                       E_SIGNAL_BT_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
+
+       DBG("-\n");
+       return FALSE;
+}
+
+void _init_timeout_cb(mobile_ap_type_e type, void *user_data)
+{
+       DBG("+\n");
+       if (sp_timeout_handler[type].func == NULL) {
+               DBG("Not supported timeout : type[%d]\n", type);
+               return;
+       }
+
+       if (user_data == NULL) {
+               ERR("Invalid param\n");
+               return;
+       }
+
+       if (sp_timeout_handler[type].src_id > 0) {
+               DBG("There is already registered timeout source\n");
+               g_source_remove(sp_timeout_handler[type].src_id);
+               sp_timeout_handler[type].src_id = 0;
+       }
+
+       sp_timeout_handler[type].user_data = user_data;
+
+       DBG("-\n");
+       return;
+}
+
+void _start_timeout_cb(mobile_ap_type_e type)
+{
+       DBG("+\n");
+       if (sp_timeout_handler[type].func == NULL) {
+               DBG("Not supported timeout : type[%d]\n", type);
+               return;
+       }
+
+       if (sp_timeout_handler[type].src_id > 0) {
+               ERR("It is not registered or stopped\n");
+               return;
+       }
+
+       sp_timeout_handler[type].src_id = g_timeout_add(TETHERING_CONN_TIMEOUT,
+                       sp_timeout_handler[type].func,
+                       sp_timeout_handler[type].user_data);
+
+       DBG("-\n");
+       return;
+}
+
+void _stop_timeout_cb(mobile_ap_type_e type)
+{
+       DBG("+\n");
+       if (sp_timeout_handler[type].func == NULL) {
+               DBG("Not supported timeout : type[%d]\n", type);
+               return;
+       }
+
+       if (sp_timeout_handler[type].src_id == 0) {
+               ERR("It is not started yet\n");
+               return;
+       }
+
+       g_source_remove(sp_timeout_handler[type].src_id);
+       sp_timeout_handler[type].src_id = 0;
+
+       DBG("-\n");
+       return;
+}
+
+void _deinit_timeout_cb(mobile_ap_type_e type) {
+       DBG("+\n");
+       if (sp_timeout_handler[type].func == NULL) {
+               DBG("Not supported timeout : type[%d]\n", type);
+               return;
+       }
+
+       if (sp_timeout_handler[type].src_id > 0) {
+               g_source_remove(sp_timeout_handler[type].src_id);
+               sp_timeout_handler[type].src_id = 0;
+       }
+
+       sp_timeout_handler[type].user_data = NULL;
+
+       DBG("-\n");
+       return;
+}
index ace1cce..1fa38b0 100644 (file)
@@ -373,77 +373,6 @@ gboolean mobileap_get_data_packet_usage(MobileAPObject *obj,
        return TRUE;
 }
 
-
-static void __reset_interface(MobileAPObject *obj)
-{
-       obj->rx_bytes = 0;
-       obj->tx_bytes = 0;
-       obj->transfer_check_count = 0;
-}
-
-
-static gboolean __check_data_transfer_cb(gpointer data)
-{
-       MobileAPObject *obj = (MobileAPObject *)data;
-       GIOChannel *io = NULL;
-       gchar *line = NULL;
-
-       char *if_name = NULL;
-       gchar iface[IF_BUF_LEN] = {0, };
-       unsigned long long rx_bytes = 0;
-       unsigned long long tx_bytes = 0;
-
-       if (_mobileap_is_disabled()) {
-               ERR("Nothing is to be done.\n");
-               return TRUE;
-       }
-
-       if (_get_network_interface_name(&if_name) == FALSE)
-               return TRUE;
-
-       io = g_io_channel_new_file(PROC_NET_DEV, "r", NULL);
-       if (!io) {
-               ERR("g_io_channel_new_file failed\n");
-               return TRUE;
-       }
-
-       while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
-
-               line = g_strdelimit(line, ":", ' ');
-               sscanf(line, "%29s %19lld %*s %*s %*s %*s %*s %*s %*s %19lld %*s %*s %*s %*s %*s",
-                                                               iface, &rx_bytes, &tx_bytes);
-
-               g_free(line);
-
-               if (g_ascii_strcasecmp(iface, if_name) == 0) {
-                       break;
-               }
-       }
-
-       g_io_channel_unref(io);
-       free(if_name);
-
-       /*DBG("rx:%lld tx:%lld\n", rx_bytes, tx_bytes);*/
-       if (obj->rx_bytes < rx_bytes || obj->tx_bytes < tx_bytes) {
-               obj->rx_bytes = rx_bytes;
-               obj->tx_bytes = tx_bytes;
-               obj->transfer_check_count = 0;
-       } else {
-               obj->transfer_check_count++;
-
-               /* 30 minutes */
-               if (obj->transfer_check_count == MAX_TRANSFER_CHECK_COUNT) {
-                       _emit_mobileap_dbus_signal(obj,
-                                       E_SIGNAL_NO_DATA_TIMEOUT, NULL);
-                       __reset_interface(obj);
-                       _disable_wifi_tethering(obj);
-               }
-       }
-
-       return TRUE;
-}
-
-
 static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
                DBusMessage *msg, void *user_data)
 {
@@ -460,6 +389,7 @@ static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
        mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
        MobileAPObject *obj = (MobileAPObject *)user_data;
        mobile_ap_station_info_t *info = NULL;
+       int n_station = 0;
 
        dbus_error_init(&error);
        if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
@@ -518,6 +448,11 @@ static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
                        return DBUS_HANDLER_RESULT_HANDLED;
                }
 
+               _get_station_count((gconstpointer)type,
+                               _slist_find_station_by_interface, &n_station);
+               if (n_station == 1)
+                       _stop_timeout_cb(type);
+
                _send_dbus_station_info("DhcpConnected", info);
 
                return DBUS_HANDLER_RESULT_HANDLED;
@@ -622,9 +557,6 @@ int main(int argc, char **argv)
        _register_wifi_station_handler();
        _register_vconf_cb((void *)mobileap_obj);
 
-       /* check tx/rx every 10 seconds */
-       g_timeout_add(10000, __check_data_transfer_cb, mobileap_obj);
-
        dbus_error_init(&dbus_error);
        dbus_bus_add_match(mobileap_conn, rule, &dbus_error);
        if (dbus_error_is_set(&dbus_error)) {
index 2a2ee31..4936719 100644 (file)
@@ -33,6 +33,7 @@
 #include "mobileap_agent.h"
 #include "mobileap_common.h"
 #include "mobileap_wifi.h"
+#include "mobileap_handler.h"
 
 static int __generate_initial_passphrase(char *passphrase_buf);
 static mobile_ap_error_code_e __get_hide_mode(int *hide_mode);
@@ -236,6 +237,7 @@ static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const uns
 static gboolean __send_station_event_cb(gpointer data)
 {
        int sig = GPOINTER_TO_INT(data);
+       int n_station = 0;
        mobile_ap_station_info_t *si = NULL;
 
        if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
@@ -256,6 +258,11 @@ static gboolean __send_station_event_cb(gpointer data)
                        return FALSE;
                }
                _remove_station_info(si->mac, _slist_find_station_by_mac);
+
+               _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
+                               _slist_find_station_by_interface, &n_station);
+               if (n_station == 0)
+                       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
        }
 
        return FALSE;
@@ -342,6 +349,8 @@ mobile_ap_error_code_e _disable_wifi_tethering(MobileAPObject *obj)
                return ret;
        }
 
+       _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
        if (_remove_station_info_all(MOBILE_AP_TYPE_WIFI) !=
                        MOBILE_AP_ERROR_NONE) {
                ERR("_remove_station_info_all is failed. Ignore it.\n");
@@ -443,6 +452,9 @@ gboolean mobileap_enable_wifi_tethering(MobileAPObject *obj, gchar *ssid,
                goto FAIL;
        }
 
+       _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
+       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
        _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
        dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);