From: Seungyoun Ju Date: Thu, 6 Dec 2012 11:30:27 +0000 (+0900) Subject: Timeout(Auto disconnection) feature is implemented X-Git-Tag: 2.1b_release~1^2~17 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b3f08b899435dcdbba40be35571352f19c844894;p=platform%2Fcore%2Fconnectivity%2Fmobileap-agent.git Timeout(Auto disconnection) feature is implemented - 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 --- diff --git a/include/mobileap.h b/include/mobileap.h index 84bb29b..18cce14 100644 --- a/include/mobileap.h +++ b/include/mobileap.h @@ -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" diff --git a/include/mobileap_agent.h b/include/mobileap_agent.h index b67ecd4..fd86779 100644 --- a/include/mobileap_agent.h +++ b/include/mobileap_agent.h @@ -136,8 +136,8 @@ #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 diff --git a/include/mobileap_common.h b/include/mobileap_common.h index 04aecc4..c7e432e 100644 --- a/include/mobileap_common.h +++ b/include/mobileap_common.h @@ -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); diff --git a/include/mobileap_handler.h b/include/mobileap_handler.h index 13375ef..4ed5640 100644 --- a/include/mobileap_handler.h +++ b/include/mobileap_handler.h @@ -24,9 +24,12 @@ #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 diff --git a/src/mobileap_agent.c b/src/mobileap_agent.c index 1e0eae8..340282d 100644 --- a/src/mobileap_agent.c +++ b/src/mobileap_agent.c @@ -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"); diff --git a/src/mobileap_bluetooth.c b/src/mobileap_bluetooth.c index 7e0edd8..be63223 100644 --- a/src/mobileap_bluetooth.c +++ b/src/mobileap_bluetooth.c @@ -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; diff --git a/src/mobileap_common.c b/src/mobileap_common.c index 084f965..128008f 100644 --- a/src/mobileap_common.c +++ b/src/mobileap_common.c @@ -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; } diff --git a/src/mobileap_handler.c b/src/mobileap_handler.c index 682f4e7..4ee8ab1 100644 --- a/src/mobileap_handler.c +++ b/src/mobileap_handler.c @@ -32,6 +32,19 @@ #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; +} diff --git a/src/mobileap_main.c b/src/mobileap_main.c index ace1cce..1fa38b0 100644 --- a/src/mobileap_main.c +++ b/src/mobileap_main.c @@ -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)) { diff --git a/src/mobileap_wifi.c b/src/mobileap_wifi.c index 2a2ee31..4936719 100644 --- a/src/mobileap_wifi.c +++ b/src/mobileap_wifi.c @@ -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);