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.
21 #include <vconf-keys.h>
26 #include "wifi-state.h"
27 #include "wifi-power.h"
28 #include "netsupplicant.h"
29 #include "network-state.h"
30 #include "wifi-indicator.h"
31 #include "network-statistics.h"
32 #include "wifi-background-scan.h"
34 #define NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT 15 * 1000
36 static gboolean new_bss_found = FALSE;
37 static guint network_noti_timer_id = 0;
39 static wifi_service_state_e g_service_state = NETCONFIG_WIFI_UNKNOWN;
40 static wifi_tech_state_e g_tech_state = NETCONFIG_WIFI_TECH_UNKNOWN;
42 static GSList *notifier_list = NULL;
44 static guint network_connected_popup_timer_id = 0;
45 static gboolean block_network_connected_popup = FALSE;
47 char *_convert_wifi_service_state_to_string(wifi_service_state_e wifi_service_state_type)
49 switch (wifi_service_state_type) {
50 case NETCONFIG_WIFI_UNKNOWN:
52 case NETCONFIG_WIFI_IDLE:
54 case NETCONFIG_WIFI_ASSOCIATION:
56 case NETCONFIG_WIFI_CONFIGURATION:
57 return "configuration";
58 case NETCONFIG_WIFI_CONNECTED:
60 case NETCONFIG_WIFI_FAILURE:
63 ERR("Invalid wifi_service_state_e parameter");
67 return "Invalid parameter";
70 char *_convert_wifi_technology_state_to_string(wifi_tech_state_e wifi_tech_state_type)
72 switch (wifi_tech_state_type) {
73 case NETCONFIG_WIFI_TECH_UNKNOWN:
75 case NETCONFIG_WIFI_TECH_OFF:
77 case NETCONFIG_WIFI_TECH_WPS_ONLY:
79 case NETCONFIG_WIFI_TECH_POWERED:
81 case NETCONFIG_WIFI_TECH_CONNECTED:
83 case NETCONFIG_WIFI_TECH_TETHERED:
86 ERR("Invalid wifi_tech_state_e parameter");
90 return "Invalid parameter";
93 static gboolean _block_network_connection_popup(gpointer data)
95 block_network_connected_popup = FALSE;
96 netconfig_stop_timer(&network_connected_popup_timer_id);
100 static void __set_wifi_connected_essid(void)
102 const char *essid_name = NULL;
103 const char *wifi_profile = netconfig_get_default_profile();
105 if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
108 if (wifi_profile == NULL ||
109 netconfig_is_wifi_profile(wifi_profile) != TRUE) {
110 ERR("Can't get Wi-Fi profile");
114 essid_name = netconfig_wifi_get_connected_essid(wifi_profile);
115 if (essid_name == NULL) {
116 ERR("Can't get Wi-Fi name");
120 netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, essid_name);
122 /* Block Network Connected popup for 3sec
123 * to avoid multiple popup's due to ready signals */
124 if (block_network_connected_popup == FALSE) {
125 block_network_connected_popup = TRUE;
126 netconfig_start_timer(3000, _block_network_connection_popup,
127 NULL, &network_connected_popup_timer_id);
128 __netconfig_pop_wifi_connected_poppup(essid_name);
132 static void __unset_wifi_connected_essid(void)
134 netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, "");
137 static const char *__get_wifi_connected_essid(void)
139 const char *essid_name = NULL;
140 const char *wifi_profile = NULL;
142 if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
145 wifi_profile = netconfig_get_default_profile();
147 if (wifi_profile == NULL || netconfig_is_wifi_profile(wifi_profile) != TRUE) {
148 ERR("Can't get Wi-Fi profile");
152 essid_name = netconfig_wifi_get_connected_essid(wifi_profile);
153 if (essid_name == NULL) {
154 ERR("Can't get Wi-Fi name");
161 static gboolean __is_wifi_profile_available(void)
163 GVariant *message = NULL;
164 GVariantIter *iter, *next;
167 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
168 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
169 "GetServices", NULL);
170 if (message == NULL) {
171 ERR("Failed to get service list");
175 g_variant_get(message, "(a(oa{sv}))", &iter);
176 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
177 if (obj == NULL || netconfig_is_wifi_profile((const gchar*)obj) == FALSE)
180 g_variant_iter_free(next);
185 g_variant_unref(message);
187 g_variant_iter_free(iter);
192 static gboolean __is_favorited(GVariantIter *array)
194 gboolean is_favorite = FALSE;
198 while (g_variant_iter_loop(array, "{sv}", &key, &var)) {
201 if (g_str_equal(key, "Favorite") != TRUE)
204 value = g_variant_get_boolean(var);
208 g_variant_unref(var);
215 static void _wifi_state_connected_activation(void)
217 /* Add activation of services when Wi-Fi is connected */
220 static void _wifi_state_changed(wifi_service_state_e state)
224 for (list = notifier_list; list; list = list->next) {
225 wifi_state_notifier *notifier = list->data;
227 if (notifier->wifi_state_changed != NULL)
228 notifier->wifi_state_changed(state, notifier->user_data);
232 static void _set_bss_found(gboolean found)
234 if (found != new_bss_found)
235 new_bss_found = found;
238 static gboolean _check_network_notification(gpointer data)
240 int qs_enable = 0, ug_state = 0;
241 static gboolean check_again = FALSE;
243 wifi_tech_state_e tech_state;
244 wifi_service_state_e service_state;
246 tech_state = wifi_state_get_technology_state();
247 if (tech_state < NETCONFIG_WIFI_TECH_POWERED) {
248 DBG("Wi-Fi off or WPS only supported[%d]", tech_state);
252 service_state = wifi_state_get_service_state();
253 if (service_state == NETCONFIG_WIFI_CONNECTED) {
254 DBG("Service state is connected");
256 } else if (service_state == NETCONFIG_WIFI_ASSOCIATION ||
257 service_state == NETCONFIG_WIFI_CONFIGURATION) {
258 DBG("Service state is connecting (check again : %d)", check_again);
266 if (__is_wifi_profile_available() == FALSE) {
267 netconfig_send_notification_to_net_popup(
268 NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
272 netconfig_vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &qs_enable);
273 if (qs_enable != VCONFKEY_WIFI_QS_ENABLE) {
274 DBG("qs_enable != VCONFKEY_WIFI_QS_ENABLE");
278 netconfig_vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &ug_state);
279 if (ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
282 netconfig_send_notification_to_net_popup(NETCONFIG_ADD_FOUND_AP_NOTI, NULL);
284 _set_bss_found(FALSE);
287 netconfig_stop_timer(&network_noti_timer_id);
291 static char *_get_connman_favorite_service(void)
293 char *favorite_service = NULL;
294 GVariant *message = NULL;
296 GVariantIter *iter, *next;
298 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
299 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
300 "GetServices", NULL);
301 if (message == NULL) {
302 ERR("Failed to get service list");
306 g_variant_get(message, "(a(oa{sv}))", &iter);
307 while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
308 if (obj == NULL || netconfig_is_wifi_profile(obj) == FALSE)
311 if (__is_favorited(next) == TRUE) {
312 favorite_service = g_strdup(obj);
314 g_variant_iter_free(next);
319 g_variant_iter_free(iter);
320 g_variant_unref(message);
322 return favorite_service;
325 static void __notification_value_changed_cb(keynode_t *node, void *user_data)
329 if (netconfig_vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &value) < 0)
332 if (value == VCONFKEY_WIFI_QS_DISABLE)
333 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
336 static void _register_network_notification(void)
338 #if defined TIZEN_WEARABLE
341 vconf_notify_key_changed(VCONFKEY_WIFI_ENABLE_QS, __notification_value_changed_cb, NULL);
344 static void _deregister_network_notification(void)
346 #if defined TIZEN_WEARABLE
349 vconf_ignore_key_changed(VCONFKEY_WIFI_ENABLE_QS, __notification_value_changed_cb);
352 static void _set_power_lock(gboolean power_lock)
357 char state[] = "lcdoff";
358 char flag[] = "staycurstate";
359 char standby[] = "NULL";
361 char sleepmargin[] = "sleepmargin";
363 const char *lockstate = "lockstate";
364 const char *unlockstate = "unlockstate";
365 static gboolean old_state = FALSE;
366 const char *lock_method;
368 if (old_state == power_lock)
371 if (power_lock == TRUE) {
372 /* deviced power lock enable */
373 params = g_variant_new("(sssi)", state, flag, standby, timeout);
375 lock_method = lockstate;
377 /* deviced power lock disable */
378 params = g_variant_new("(ss)", state, sleepmargin);
380 lock_method = unlockstate;
383 reply = netconfig_invoke_dbus_method(
384 "org.tizen.system.deviced",
385 "/Org/Tizen/System/DeviceD/Display",
386 "org.tizen.system.deviced.display",
390 ERR("Failed to set_power_lock");
394 if (g_variant_is_of_type(reply, G_VARIANT_TYPE_INT32)) {
395 ret = g_variant_get_int32(reply);
397 ERR("Failed to set power lock %s with ret %d",
398 power_lock == TRUE ? "enable" : "disable", ret);
400 old_state = power_lock;
403 g_variant_unref(reply);
408 void wifi_state_emit_power_completed(gboolean power_on)
411 wifi_emit_power_on_completed((Wifi *)get_wifi_object());
413 wifi_emit_power_off_completed((Wifi *)get_wifi_object());
415 DBG("Successfully sent signal [%s]", (power_on) ? "powerOn" : "powerOff");
418 void wifi_state_emit_power_failed(void)
420 wifi_emit_power_operation_failed((Wifi *)get_wifi_object());
422 DBG("Successfully sent signal [PowerOperationFailed]");
425 void wifi_state_update_power_state(gboolean powered)
427 wifi_tech_state_e tech_state;
429 /* It's automatically updated by signal-handler
430 * DO NOT update manually
431 * It includes Wi-Fi state configuration
433 tech_state = wifi_state_get_technology_state();
435 if (powered == TRUE) {
436 if (tech_state < NETCONFIG_WIFI_TECH_POWERED && netconfig_is_wifi_tethering_on() != TRUE) {
437 DBG("Wi-Fi turned on or waken up from power-save mode");
439 wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_POWERED);
441 wifi_state_emit_power_completed(TRUE);
443 netconfig_wifi_device_picker_service_start();
445 netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE, VCONFKEY_WIFI_UNCONNECTED);
446 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_UNCONNECTED);
447 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
449 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
451 netconfig_wifi_bgscan_stop();
452 netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN);
453 netconfig_wifi_bgscan_start(TRUE);
455 /* Add callback to track change in notification setting */
456 _register_network_notification();
458 } else if (tech_state > NETCONFIG_WIFI_TECH_OFF) {
459 DBG("Wi-Fi turned off or in power-save mode");
461 wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_WPS_ONLY);
463 netconfig_wifi_device_picker_service_stop();
465 wifi_power_disable_technology_state_by_only_connman_signal();
466 wifi_power_driver_and_supplicant(FALSE);
468 wifi_state_emit_power_completed(FALSE);
470 netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE, VCONFKEY_WIFI_OFF);
471 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_OFF);
472 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_OFF);
474 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_OFF);
476 netconfig_wifi_bgscan_stop();
478 _set_bss_found(FALSE);
480 /* Inform net-popup to remove the wifi found notification */
481 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
482 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
483 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_IP_CONFLICT_NOTI, NULL);
485 _deregister_network_notification();
489 char *wifi_get_favorite_service(void)
491 return _get_connman_favorite_service();
494 void wifi_start_timer_network_notification(void)
496 #if defined TIZEN_WEARABLE
497 /* In case of wearable device, no need to notify available Wi-Fi APs */
500 netconfig_start_timer(NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT, _check_network_notification, NULL, &network_noti_timer_id);
503 void wifi_state_notifier_register(wifi_state_notifier *notifier)
505 DBG("register notifier");
507 notifier_list = g_slist_append(notifier_list, notifier);
510 void wifi_state_notifier_unregister(wifi_state_notifier *notifier)
512 DBG("un-register notifier");
514 notifier_list = g_slist_remove_all(notifier_list, notifier);
517 void wifi_state_notifier_cleanup(void)
519 g_slist_free_full(notifier_list, NULL);
522 void wifi_state_set_bss_found(gboolean found)
524 _set_bss_found(found);
527 gboolean wifi_state_is_bss_found(void)
529 return new_bss_found;
532 void wifi_state_set_service_state(wifi_service_state_e new_state)
534 static gboolean dhcp_stage = FALSE;
535 wifi_service_state_e old_state = g_service_state;
537 if (old_state == new_state)
540 g_service_state = new_state;
541 DBG("Wi-Fi service state, old state[%s] ==> new state[%s]",
542 _convert_wifi_service_state_to_string(old_state), _convert_wifi_service_state_to_string(new_state));
544 /* From association, temporarily disable Wi-Fi power saving */
545 if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_ASSOCIATION) {
546 _set_power_lock(TRUE);
547 wifi_set_early_suspend(FALSE);
549 } else if (dhcp_stage == TRUE && new_state != NETCONFIG_WIFI_CONFIGURATION) {
550 _set_power_lock(FALSE);
551 wifi_set_early_suspend(TRUE);
555 if (new_state == NETCONFIG_WIFI_CONNECTED) {
556 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
558 netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_CONNECTED);
559 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_CONNECTED);
561 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_CONNECTED);
563 __set_wifi_connected_essid();
565 netconfig_wifi_indicator_start();
566 } else if (old_state == NETCONFIG_WIFI_CONNECTED) {
567 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
569 __unset_wifi_connected_essid();
571 netconfig_set_vconf_int (VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_UNCONNECTED);
572 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
574 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
576 netconfig_wifi_indicator_stop();
578 netconfig_wifi_bgscan_stop();
579 netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN);
580 netconfig_wifi_bgscan_start(TRUE);
581 } else if ((old_state > NETCONFIG_WIFI_IDLE && old_state < NETCONFIG_WIFI_CONNECTED) && new_state == NETCONFIG_WIFI_IDLE) {
582 /* in ipv6 case disconnect/association -> association */
583 DBG("reset the bg scan period");
585 netconfig_wifi_bgscan_stop();
586 netconfig_wifi_bgscan_start(TRUE);
589 _wifi_state_changed(new_state);
591 if (new_state == NETCONFIG_WIFI_CONNECTED)
592 _wifi_state_connected_activation();
595 wifi_service_state_e wifi_state_get_service_state(void)
597 return g_service_state;
600 void wifi_state_set_tech_state(wifi_tech_state_e new_state)
602 wifi_tech_state_e old_state = g_tech_state;
604 if (old_state == new_state)
607 g_tech_state = new_state;
609 DBG("Wi-Fi technology state, old state[%s] ==> new state[%s]",
610 _convert_wifi_technology_state_to_string(old_state), _convert_wifi_technology_state_to_string(new_state));
613 wifi_tech_state_e wifi_state_get_technology_state(void)
615 GVariant *message = NULL, *variant;
616 GVariantIter *iter, *next;
617 wifi_tech_state_e ret = NETCONFIG_WIFI_TECH_OFF;
618 gboolean wifi_tech_powered = FALSE;
619 gboolean wifi_tech_connected = FALSE;
623 if (g_tech_state > NETCONFIG_WIFI_TECH_UNKNOWN)
626 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
627 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
628 "GetTechnologies", NULL);
629 if (message == NULL) {
630 ERR("Failed to get_technology_state");
631 return NETCONFIG_WIFI_TECH_UNKNOWN;
634 g_variant_get(message, "(a(oa{sv}))", &iter);
635 while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
636 if (path == NULL || g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) != 0)
639 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
640 const gchar *sdata = NULL;
643 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
644 data = g_variant_get_boolean(variant);
645 DBG("key-[%s] - %s", key, data ? "True" : "False");
647 if (strcmp(key, "Powered") == 0 && data)
648 wifi_tech_powered = TRUE;
649 else if (strcmp(key, "Connected") == 0 && data)
650 wifi_tech_connected = TRUE;
652 else if (strcmp(key, "Tethering") == 0 && data) {
654 } else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
655 sdata = g_variant_get_string(variant, NULL);
661 g_variant_unref(message);
663 g_variant_iter_free(iter);
665 if (wifi_tech_powered == TRUE)
666 ret = NETCONFIG_WIFI_TECH_POWERED;
668 if (wifi_tech_connected == TRUE)
669 ret = NETCONFIG_WIFI_TECH_CONNECTED;
676 gboolean wifi_state_is_technology_available(void)
678 GVariant *message = NULL;
679 GVariantIter *iter, *next;
681 gboolean ret = FALSE;
683 message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
684 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
685 "GetTechnologies", NULL);
686 if (message == NULL) {
687 ERR("Failed to get_technology_state");
691 g_variant_get(message, "(a(oa{sv}))", &iter);
692 while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
693 if (path != NULL && g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == 0)
697 g_variant_unref(message);
698 g_variant_iter_free(iter);
700 DBG("Wi-Fi technology is %s", ret ? "available" : "unavailable");
704 void wifi_state_set_connected_essid(void)
706 __set_wifi_connected_essid();
709 void wifi_state_get_connected_essid(gchar **essid)
711 *essid = g_strdup(__get_wifi_connected_essid());
714 /* wifi_connection_state_e in CAPI
716 * WIFI_CONNECTION_STATE_FAILURE = -1
717 * WIFI_CONNECTION_STATE_DISCONNECTED = 0
718 * WIFI_CONNECTION_STATE_ASSOCIATION = 1
719 * WIFI_CONNECTION_STATE_CONFIGURATION = 2
720 * WIFI_CONNECTION_STATE_CONNECTED = 3
722 /* connection_wifi_state_e in CAPI
724 * CONNECTION_WIFI_STATE_DEACTIVATED = 0
725 * CONNECTION_WIFI_STATE_DISCONNECTED = 1
726 * CONNECTION_WIFI_STATE_CONNECTED = 2
728 gboolean handle_get_wifi_state(Wifi *wifi, GDBusMethodInvocation *context)
730 g_return_val_if_fail(wifi != NULL, TRUE);
731 GVariant *param = NULL;
732 wifi_tech_state_e tech_state = NETCONFIG_WIFI_TECH_UNKNOWN;
733 wifi_service_state_e service_state = NETCONFIG_WIFI_UNKNOWN;
734 tech_state = wifi_state_get_technology_state();
735 service_state = wifi_state_get_service_state();
737 if (tech_state == NETCONFIG_WIFI_TECH_UNKNOWN)
738 param = g_variant_new("(s)", "unknown");
739 else if (tech_state == NETCONFIG_WIFI_TECH_OFF ||
740 tech_state == NETCONFIG_WIFI_TECH_WPS_ONLY)
741 param = g_variant_new("(s)", "deactivated");
742 else if (tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
743 param = g_variant_new("(s)", "connected");
745 switch (service_state) {
746 case NETCONFIG_WIFI_FAILURE:
747 param = g_variant_new("(s)", "failure");
749 case NETCONFIG_WIFI_ASSOCIATION:
750 param = g_variant_new("(s)", "association");
752 case NETCONFIG_WIFI_CONFIGURATION:
753 param = g_variant_new("(s)", "configuration");
755 case NETCONFIG_WIFI_CONNECTED:
756 param = g_variant_new("(s)", "connected");
758 case NETCONFIG_WIFI_UNKNOWN:
759 case NETCONFIG_WIFI_IDLE:
761 param = g_variant_new("(s)", "disconnected");
765 g_dbus_method_invocation_return_value(context, param);