2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <vconf-keys.h>
24 #include <bundle_internal.h>
25 #include <eventsystem.h>
30 #include "wifi-state.h"
31 #include "wifi-power.h"
32 #include "netsupplicant.h"
33 #include "network-state.h"
34 #include "wifi-indicator.h"
35 #include "network-statistics.h"
36 #include "wifi-background-scan.h"
38 #define NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT 15 * 1000
40 static gboolean new_bss_found = FALSE;
41 static guint network_noti_timer_id = 0;
43 static enum netconfig_wifi_service_state
44 wifi_service_state = NETCONFIG_WIFI_UNKNOWN;
45 static enum netconfig_wifi_tech_state
46 wifi_technology_state = NETCONFIG_WIFI_TECH_UNKNOWN;
48 static GSList *notifier_list = NULL;
51 static void __netconfig_pop_wifi_connected_poppup(const char *ssid)
60 bundle_add(b, "_SYSPOPUP_TITLE_", "Network connection popup");
61 bundle_add(b, "_SYSPOPUP_TYPE_", "notification");
62 bundle_add(b, "_SYSPOPUP_CONTENT_", "wifi connected");
63 bundle_add(b, "_AP_NAME_", ssid);
65 DBG("Launch Wi-Fi connected alert network popup");
66 aul_launch_app("net.netpopup", b);
71 static void __netconfig_wifi_state_connected_activation(void)
73 /* Add activation of services when Wi-Fi is connected */
77 aul_launch_app("com.samsung.keepit-service-standby", b);
81 static void __netconfig_wifi_set_essid(void)
83 const char *essid_name = NULL;
84 const char *wifi_profile = netconfig_get_default_profile();
86 if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
89 if (wifi_profile == NULL ||
90 netconfig_is_wifi_profile(wifi_profile) != TRUE) {
91 ERR("Can't get Wi-Fi profile");
95 essid_name = netconfig_wifi_get_connected_essid(wifi_profile);
96 if (essid_name == NULL) {
97 ERR("Can't get Wi-Fi name");
101 netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, essid_name);
103 __netconfig_pop_wifi_connected_poppup(essid_name);
106 static void __netconfig_wifi_unset_essid(void)
108 netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, "");
111 static gboolean __netconfig_is_wifi_profile_available(void)
113 GVariant *message = NULL;
114 GVariantIter *iter, *next;
117 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
118 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
119 "GetServices", NULL);
120 if (message == NULL) {
121 ERR("Failed to get service list");
125 g_variant_get(message, "(a(oa{sv}))", &iter);
126 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
127 if (obj == NULL || netconfig_is_wifi_profile((const gchar*)obj) == FALSE) {
131 g_variant_iter_free(next);
136 g_variant_unref(message);
138 g_variant_iter_free(iter);
143 static gboolean __netconfig_wifi_is_favorited(GVariantIter *array)
145 gboolean is_favorite = FALSE;
149 while (g_variant_iter_loop(array, "{sv}", &key, &var)) {
152 if (g_str_equal(key, "Favorite") != TRUE) {
156 value = g_variant_get_boolean(var);
160 g_variant_unref(var);
167 static char *__netconfig_wifi_get_connman_favorite_service(void)
169 char *favorite_service = NULL;
170 GVariant *message = NULL;
172 GVariantIter *iter, *next;
174 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
175 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
176 "GetServices", NULL);
177 if (message == NULL) {
178 ERR("Failed to get service list");
182 g_variant_get(message, "(a(oa{sv}))", &iter);
183 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
184 if (obj == NULL || netconfig_is_wifi_profile(obj) == FALSE) {
188 if (__netconfig_wifi_is_favorited(next) == TRUE) {
189 favorite_service = g_strdup(obj);
191 g_variant_iter_free(next);
196 g_variant_iter_free(iter);
197 g_variant_unref(message);
199 return favorite_service;
202 static void __netconfig_wifi_state_changed(
203 enum netconfig_wifi_service_state state)
207 for (list = notifier_list; list; list = list->next) {
208 struct netconfig_wifi_state_notifier *notifier = list->data;
210 if (notifier->netconfig_wifi_state_changed != NULL)
211 notifier->netconfig_wifi_state_changed(state, notifier->user_data);
215 void netconfig_wifi_set_bss_found(const gboolean found)
217 if (found != new_bss_found)
218 new_bss_found = found;
221 gboolean netconfig_wifi_is_bss_found(void)
223 return new_bss_found;
226 static void __netconfig_wifi_state_set_power_save(gboolean power_save)
230 GVariant *input_args = NULL;
231 static gboolean old_state = TRUE;
232 const gchar *args_disable = "POWERMODE 1";
233 const gchar *args_enable = "POWERMODE 0";
234 if (old_state == power_save)
237 if_path = netconfig_wifi_get_supplicant_interface();
238 if (if_path == NULL) {
239 ERR("Fail to get wpa_supplicant DBus path");
244 input_args = g_variant_new_string(args_enable);
246 input_args = g_variant_new_string(args_disable);
248 result = netconfig_supplicant_invoke_dbus_method_nonblock(
251 SUPPLICANT_INTERFACE ".Interface",
256 ERR("Fail to set power save mode POWERMODE %d", power_save);
258 old_state = power_save;
263 static void __netconfig_wifi_state_set_power_lock(gboolean power_lock)
268 char state[] = "lcdoff";
269 char flag[] = "staycurstate";
270 char standby[] = "NULL";
272 char sleepmargin[] = "sleepmargin";
274 const char *lockstate = "lockstate";
275 const char *unlockstate = "unlockstate";
276 static gboolean old_state = FALSE;
277 const char *lock_method;
279 if (old_state == power_lock)
282 if (power_lock == TRUE) {
283 /* deviced power lock enable */
284 params = g_variant_new("(sssi)", state, flag, standby, timeout);
286 lock_method = lockstate;
288 /* deviced power lock disable */
289 params = g_variant_new("(ss)", state, sleepmargin);
291 lock_method = unlockstate;
294 reply = netconfig_invoke_dbus_method(
295 "org.tizen.system.deviced",
296 "/Org/Tizen/System/DeviceD/Display",
297 "org.tizen.system.deviced.display",
301 ERR("Failed to set_power_lock");
305 ret = g_variant_get_int32(reply);
307 ERR("Failed to set power lock %s with ret %d",
308 power_lock == TRUE ? "enable" : "disable", ret);
310 old_state = power_lock;
315 void netconfig_wifi_state_set_service_state(
316 enum netconfig_wifi_service_state new_state)
318 static gboolean dhcp_stage = FALSE;
319 enum netconfig_wifi_service_state old_state = wifi_service_state;
321 if (old_state == new_state)
324 wifi_service_state = new_state;
325 DBG("Wi-Fi state %d ==> %d", old_state, new_state);
327 /* During DHCP, temporarily disable Wi-Fi power saving */
328 if ((old_state < NETCONFIG_WIFI_ASSOCIATION ||
329 old_state == NETCONFIG_WIFI_FAILURE) &&
330 new_state == NETCONFIG_WIFI_CONFIGURATION) {
331 __netconfig_wifi_state_set_power_lock(TRUE);
332 __netconfig_wifi_state_set_power_save(FALSE);
334 } else if (dhcp_stage == TRUE) {
335 __netconfig_wifi_state_set_power_lock(FALSE);
336 __netconfig_wifi_state_set_power_save(TRUE);
340 if (new_state == NETCONFIG_WIFI_CONNECTED) {
341 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
343 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_CONNECTED);
344 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE,
345 VCONFKEY_NETWORK_WIFI_CONNECTED);
347 netconfig_set_system_event(SYS_EVENT_WIFI_STATE, EVT_KEY_WIFI_STATE, EVT_VAL_WIFI_CONNECTED);
349 __netconfig_wifi_set_essid();
351 netconfig_wifi_indicator_start();
352 } else if (old_state == NETCONFIG_WIFI_CONNECTED) {
353 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
355 __netconfig_wifi_unset_essid();
357 netconfig_set_vconf_int (VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_UNCONNECTED);
358 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE,
359 VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
361 netconfig_set_system_event(SYS_EVENT_WIFI_STATE, EVT_KEY_WIFI_STATE, EVT_VAL_WIFI_ON);
363 netconfig_wifi_indicator_stop();
365 netconfig_wifi_set_bgscan_pause(FALSE);
367 netconfig_wifi_bgscan_stop();
368 netconfig_wifi_bgscan_start(TRUE);
369 } else if ( (old_state > NETCONFIG_WIFI_IDLE && old_state < NETCONFIG_WIFI_CONNECTED)
370 && new_state == NETCONFIG_WIFI_IDLE){
371 //in ipv6 case disconnect/association -> association
372 DBG("reset the bg scan period");
373 netconfig_wifi_set_bgscan_pause(FALSE);
375 netconfig_wifi_bgscan_stop();
376 netconfig_wifi_bgscan_start(TRUE);
379 __netconfig_wifi_state_changed(new_state);
381 if (new_state == NETCONFIG_WIFI_CONNECTED){
382 __netconfig_wifi_state_connected_activation();
383 #if defined TIZEN_WEARABLE
384 wc_launch_syspopup(WC_POPUP_TYPE_WIFI_CONNECTED);
389 enum netconfig_wifi_service_state
390 netconfig_wifi_state_get_service_state(void)
392 return wifi_service_state;
395 void netconfig_wifi_state_set_technology_state(
396 enum netconfig_wifi_tech_state new_state)
398 enum netconfig_wifi_tech_state old_state = wifi_technology_state;
400 if (old_state == new_state)
403 wifi_technology_state = new_state;
405 DBG("Wi-Fi technology state %d ==> %d", old_state, new_state);
408 enum netconfig_wifi_tech_state netconfig_wifi_state_get_technology_state(void)
410 GVariant *message = NULL, *variant;
411 GVariantIter *iter, *next;
412 enum netconfig_wifi_tech_state ret = NETCONFIG_WIFI_TECH_OFF;
413 gboolean wifi_tech_powered = FALSE;
414 gboolean wifi_tech_connected = FALSE;
418 if (wifi_technology_state > NETCONFIG_WIFI_TECH_UNKNOWN)
419 return wifi_technology_state;
421 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
422 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
423 "GetTechnologies", NULL);
424 if (message == NULL) {
425 ERR("Failed to get_technology_state");
426 return NETCONFIG_WIFI_TECH_UNKNOWN;
429 g_variant_get(message, "(a(oa{sv}))", &iter);
430 while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
431 if (path == NULL || g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) != 0) {
435 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
436 const gchar *sdata = NULL;
439 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
440 data = g_variant_get_boolean(variant);
441 DBG("key-[%s] - %s", key, data ? "True" : "False");
443 if (strcmp(key, "Powered") == 0 && data) {
444 wifi_tech_powered = TRUE;
445 } else if (strcmp(key, "Connected") == 0 && data) {
446 wifi_tech_connected = TRUE;
447 } else if (strcmp(key, "Tethering") == 0 && data) {
450 } else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
451 sdata = g_variant_get_string(variant, NULL);
455 g_variant_iter_free (next);
458 g_variant_unref(message);
460 g_variant_iter_free (iter);
462 if (wifi_tech_powered == TRUE)
463 ret = NETCONFIG_WIFI_TECH_POWERED;
465 if (wifi_tech_connected == TRUE)
466 ret = NETCONFIG_WIFI_TECH_CONNECTED;
468 wifi_technology_state = ret;
470 return wifi_technology_state;
473 void netconfig_wifi_notify_power_failed(void)
475 wifi_emit_power_operation_failed((Wifi *)get_netconfig_wifi_object());
477 DBG("Successfully sent signal [PowerOperationFailed]");
480 void netconfig_wifi_notify_power_completed(gboolean power_on)
483 wifi_emit_power_on_completed((Wifi *)get_netconfig_wifi_object());
485 wifi_emit_power_off_completed((Wifi *)get_netconfig_wifi_object());
487 DBG("Successfully sent signal [%s]",(power_on)?"powerOn":"powerOff");
490 static void __netconfig_notification_value_changed_cb(
491 keynode_t *node, void *user_data)
495 if (vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &value) < 0) {
499 if (value == VCONFKEY_WIFI_QS_DISABLE) {
500 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI,
505 static void __netconfig_register_network_notification(void)
507 #if defined TIZEN_WEARABLE
510 vconf_notify_key_changed(VCONFKEY_WIFI_ENABLE_QS,
511 __netconfig_notification_value_changed_cb, NULL);
514 static void __netconfig_deregister_network_notification(void)
516 #if defined TIZEN_WEARABLE
519 vconf_ignore_key_changed(VCONFKEY_WIFI_ENABLE_QS,
520 __netconfig_notification_value_changed_cb);
523 void netconfig_wifi_update_power_state(gboolean powered)
525 enum netconfig_wifi_tech_state wifi_tech_state;
527 /* It's automatically updated by signal-handler
528 * DO NOT update manually
529 * It includes Wi-Fi state configuration
531 wifi_tech_state = netconfig_wifi_state_get_technology_state();
533 if (powered == TRUE) {
534 if (wifi_tech_state < NETCONFIG_WIFI_TECH_POWERED &&
535 netconfig_is_wifi_tethering_on() != TRUE) {
536 DBG("Wi-Fi turned on or waken up from power-save mode");
538 netconfig_wifi_state_set_technology_state(
539 NETCONFIG_WIFI_TECH_POWERED);
541 netconfig_wifi_notify_power_completed(TRUE);
543 netconfig_wifi_device_picker_service_start();
545 netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE,
546 VCONFKEY_WIFI_UNCONNECTED);
547 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE,
548 VCONFKEY_WIFI_UNCONNECTED);
549 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE,
550 VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
552 netconfig_set_system_event(SYS_EVENT_WIFI_STATE, EVT_KEY_WIFI_STATE, EVT_VAL_WIFI_ON);
554 netconfig_wifi_bgscan_stop();
555 netconfig_wifi_bgscan_start(TRUE);
557 /* Add callback to track change in notification setting */
558 __netconfig_register_network_notification();
560 } else if (wifi_tech_state > NETCONFIG_WIFI_TECH_OFF) {
561 DBG("Wi-Fi turned off or in power-save mode");
563 netconfig_wifi_state_set_technology_state(
564 NETCONFIG_WIFI_TECH_WPS_ONLY);
566 netconfig_wifi_device_picker_service_stop();
568 netconfig_wifi_disable_technology_state_by_only_connman_signal();
569 netconfig_wifi_driver_and_supplicant(FALSE);
571 netconfig_wifi_notify_power_completed(FALSE);
573 netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE, VCONFKEY_WIFI_OFF);
574 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_OFF);
575 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE,
576 VCONFKEY_NETWORK_WIFI_OFF);
578 netconfig_set_system_event(SYS_EVENT_WIFI_STATE, EVT_KEY_WIFI_STATE, EVT_VAL_WIFI_OFF);
580 netconfig_wifi_set_bgscan_pause(FALSE);
581 netconfig_wifi_bgscan_stop();
583 netconfig_wifi_set_bss_found(FALSE);
585 /* Inform net-popup to remove the wifi found notification */
586 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
587 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
589 __netconfig_deregister_network_notification();
594 char *netconfig_wifi_get_favorite_service(void)
596 return __netconfig_wifi_get_connman_favorite_service();
599 static gboolean __netconfig_wifi_check_network_notification(gpointer data)
601 int qs_enable = 0, ug_state = 0;
602 static gboolean check_again = FALSE;
604 enum netconfig_wifi_tech_state wifi_tech_state;
605 enum netconfig_wifi_service_state wifi_service_state;
607 wifi_tech_state = netconfig_wifi_state_get_technology_state();
608 if (wifi_tech_state < NETCONFIG_WIFI_TECH_POWERED) {
609 DBG("Wi-Fi off or WPS only supported[%d]", wifi_tech_state);
613 wifi_service_state = netconfig_wifi_state_get_service_state();
614 if (wifi_service_state == NETCONFIG_WIFI_CONNECTED) {
615 DBG("Service state is connected");
617 } else if (wifi_service_state == NETCONFIG_WIFI_ASSOCIATION ||
618 wifi_service_state == NETCONFIG_WIFI_CONFIGURATION) {
619 DBG("Service state is connecting (check again : %d)", check_again);
627 if (__netconfig_is_wifi_profile_available() == FALSE) {
628 netconfig_send_notification_to_net_popup(
629 NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
633 vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &qs_enable);
634 if (qs_enable != VCONFKEY_WIFI_QS_ENABLE) {
635 DBG("qs_enable != VCONFKEY_WIFI_QS_ENABLE");
639 vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &ug_state);
640 if (ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND) {
644 netconfig_send_notification_to_net_popup(NETCONFIG_ADD_FOUND_AP_NOTI, NULL);
646 netconfig_wifi_set_bss_found(FALSE);
649 netconfig_stop_timer(&network_noti_timer_id);
653 void netconfig_wifi_start_timer_network_notification(void)
655 #if defined TIZEN_WEARABLE
656 /* In case of wearable device, no need to notify available Wi-Fi APs */
659 netconfig_start_timer(NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT,
660 __netconfig_wifi_check_network_notification, NULL, &network_noti_timer_id);
663 void netconfig_wifi_state_notifier_cleanup(void)
665 g_slist_free_full(notifier_list, NULL);
668 void netconfig_wifi_state_notifier_register(
669 struct netconfig_wifi_state_notifier *notifier)
671 DBG("register notifier");
673 notifier_list = g_slist_append(notifier_list, notifier);
676 void netconfig_wifi_state_notifier_unregister(
677 struct netconfig_wifi_state_notifier *notifier)
679 DBG("un-register notifier");
681 notifier_list = g_slist_remove_all(notifier_list, notifier);