Merge "Handling when supplicant returns InterfaceExists." into tizen
[platform/core/connectivity/net-config.git] / src / wifi-background-scan.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <glib.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23
24 #include "log.h"
25 #include "util.h"
26 #include "netdbus.h"
27 #include "wifi-state.h"
28 #include "wifi-background-scan.h"
29
30 #if defined TIZEN_WEARABLE
31 #define SCAN_PERIODIC_DELAY             15
32 #define SCAN_EXPONENTIAL_MIN    5
33 #define SCAN_EXPONENTIAL_MAX    320
34 #else
35 #define SCAN_PERIODIC_DELAY             10
36 #define SCAN_EXPONENTIAL_MIN    4
37 #define SCAN_EXPONENTIAL_MAX    128
38 #endif
39
40 enum {
41         WIFI_BGSCAN_MODE_EXPONENTIAL = 0x00,
42         WIFI_BGSCAN_MODE_PERIODIC,
43         WIFI_BGSCAN_MODE_MAX,
44 };
45
46 struct bgscan_timer_data {
47         guint time;
48         guint mode;
49         guint timer_id;
50 };
51
52 static gboolean netconfig_wifi_scanning = FALSE;
53 static gboolean netconfig_bgscan_paused = FALSE;
54
55 static struct bgscan_timer_data *__netconfig_wifi_bgscan_get_bgscan_data(void)
56 {
57         static struct bgscan_timer_data timer_data = {
58                                         SCAN_EXPONENTIAL_MIN, WIFI_BGSCAN_MODE_EXPONENTIAL, 0};
59
60         return &timer_data;
61 }
62
63 static guint __netconfig_wifi_bgscan_mode(gboolean is_set_mode, guint mode)
64 {
65         static guint bgscan_mode = WIFI_BGSCAN_MODE_EXPONENTIAL;
66
67         if (is_set_mode != TRUE)
68                 return bgscan_mode;
69
70         if (mode < WIFI_BGSCAN_MODE_MAX)
71                 bgscan_mode = mode;
72
73         DBG("Wi-Fi background scan mode set %d", bgscan_mode);
74
75         return bgscan_mode;
76 }
77
78 static void __netconfig_wifi_bgscan_set_mode(guint mode)
79 {
80         __netconfig_wifi_bgscan_mode(TRUE, mode);
81 }
82
83 static guint __netconfig_wifi_bgscan_get_mode(void)
84 {
85         return __netconfig_wifi_bgscan_mode(FALSE, -1);
86 }
87
88 static gboolean __netconfig_wifi_bgscan_request_connman_scan(int retries)
89 {
90         gboolean reply = FALSE;
91         guint state = wifi_state_get_service_state();
92
93         if (state == NETCONFIG_WIFI_CONNECTED)
94                 if (__netconfig_wifi_bgscan_get_mode() == WIFI_BGSCAN_MODE_EXPONENTIAL)
95                         return TRUE;
96
97         if (state == NETCONFIG_WIFI_ASSOCIATION || state == NETCONFIG_WIFI_CONFIGURATION) {
98                 /* During Wi-Fi connecting, Wi-Fi can be disappeared.
99                  * After 1 sec, try scan even if connecting state */
100                 if (retries < 2)
101                         return FALSE;
102         }
103
104         netconfig_wifi_set_scanning(TRUE);
105
106         reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
107                         CONNMAN_WIFI_TECHNOLOGY_PREFIX,
108                         CONNMAN_TECHNOLOGY_INTERFACE, "Scan", NULL, NULL);
109         if (reply != TRUE)
110                 netconfig_wifi_set_scanning(FALSE);
111
112         return reply;
113 }
114
115 static gboolean __netconfig_wifi_bgscan_next_scan(gpointer data);
116
117 static gboolean __netconfig_wifi_bgscan_immediate_scan(gpointer data)
118 {
119         static int retries = 0;
120
121 #if !defined TIZEN_WEARABLE
122         if (netconfig_wifi_is_bgscan_paused())
123                 return FALSE;
124 #endif
125
126         if (__netconfig_wifi_bgscan_request_connman_scan(retries) == TRUE) {
127                 retries = 0;
128                 return FALSE;
129         } else if (retries > 2) {
130                 retries = 0;
131                 return FALSE;
132         }
133
134         retries++;
135
136         return TRUE;
137 }
138
139 static void __netconfig_wifi_bgscan_start_timer(gboolean immediate_scan,
140                 struct bgscan_timer_data *data)
141 {
142         if (!data)
143                 return;
144
145         netconfig_stop_timer(&(data->timer_id));
146
147         data->mode = __netconfig_wifi_bgscan_get_mode();
148
149         if (data->time < SCAN_EXPONENTIAL_MIN)
150                 data->time = SCAN_EXPONENTIAL_MIN;
151
152         switch (data->mode) {
153         case WIFI_BGSCAN_MODE_EXPONENTIAL:
154                 if (immediate_scan == TRUE) {
155                         if ((data->time * 2) > SCAN_EXPONENTIAL_MAX)
156                                 data->time = SCAN_EXPONENTIAL_MAX;
157                         else
158                                 data->time = data->time * 2;
159                 }
160
161                 break;
162         case WIFI_BGSCAN_MODE_PERIODIC:
163                 if ((data->time * 2) > SCAN_PERIODIC_DELAY)
164                         data->time = SCAN_PERIODIC_DELAY;
165                 else
166                         data->time = data->time * 2;
167
168                 break;
169         default:
170                 DBG("Invalid Wi-Fi background scan mode[%d]", data->mode);
171                 return;
172         }
173
174         if (immediate_scan == TRUE)
175                 g_timeout_add(500, __netconfig_wifi_bgscan_immediate_scan, NULL);
176
177         DBG("Scan immediately[%d], mode[%d], next[%d]",
178                                 immediate_scan, data->mode, data->time);
179
180         netconfig_start_timer_seconds(data->time,
181                                 __netconfig_wifi_bgscan_next_scan, data, &(data->timer_id));
182 }
183
184 static void __netconfig_wifi_bgscan_stop_timer(struct bgscan_timer_data *data)
185 {
186         if (data == NULL)
187                 return;
188
189         netconfig_stop_timer(&(data->timer_id));
190 }
191
192 static gboolean __netconfig_wifi_bgscan_next_scan(gpointer data)
193 {
194         struct bgscan_timer_data *timer = (struct bgscan_timer_data *)data;
195         int pm_state = VCONFKEY_PM_STATE_NORMAL;
196
197         if (timer == NULL)
198                 return FALSE;
199
200         /* In case of LCD off, we don't need Wi-Fi scan */
201         vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
202         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
203                 return TRUE;
204
205         __netconfig_wifi_bgscan_start_timer(TRUE, timer);
206
207         return FALSE;
208 }
209
210 void netconfig_wifi_set_bgscan_pause(gboolean pause)
211 {
212         DBG("[%s] Wi-Fi background scan", pause ? "Pause" : "Resume");
213         netconfig_bgscan_paused = pause;
214 }
215
216 gboolean netconfig_wifi_is_bgscan_paused(void)
217 {
218         DBG("Wi-Fi background scan is [%s]", netconfig_bgscan_paused ? "Paused" : "Runnable");
219         return netconfig_bgscan_paused;
220 }
221
222 void netconfig_wifi_bgscan_start(gboolean immediate_scan)
223 {
224         wifi_tech_state_e wifi_tech_state;
225         struct bgscan_timer_data *timer_data =
226                         __netconfig_wifi_bgscan_get_bgscan_data();
227
228         if (timer_data == NULL)
229                 return;
230
231         wifi_tech_state = wifi_state_get_technology_state();
232         if (wifi_tech_state < NETCONFIG_WIFI_TECH_POWERED)
233                 return;
234
235         DBG("Wi-Fi background scan started or re-started(%d)", immediate_scan);
236
237         __netconfig_wifi_bgscan_start_timer(immediate_scan, timer_data);
238 }
239
240 void netconfig_wifi_bgscan_stop(void)
241 {
242         struct bgscan_timer_data *timer_data =
243                         __netconfig_wifi_bgscan_get_bgscan_data();
244
245         if (timer_data == NULL)
246                 return;
247
248         DBG("Wi-Fi background scan stop");
249
250         timer_data->time = SCAN_EXPONENTIAL_MIN;
251
252         __netconfig_wifi_bgscan_stop_timer(timer_data);
253 }
254
255 gboolean netconfig_wifi_get_bgscan_state(void)
256 {
257         struct bgscan_timer_data *timer_data =
258                         __netconfig_wifi_bgscan_get_bgscan_data();
259
260         return ((timer_data->timer_id > (guint)0) ? TRUE : FALSE);
261 }
262
263 gboolean netconfig_wifi_get_scanning(void)
264 {
265         return netconfig_wifi_scanning;
266 }
267
268 void netconfig_wifi_set_scanning(gboolean scanning)
269 {
270         if (netconfig_wifi_scanning != scanning)
271                 netconfig_wifi_scanning = scanning;
272 }
273
274 gboolean handle_set_bgscan(Wifi *wifi, GDBusMethodInvocation *context, guint scan_mode)
275 {
276         gint old_mode = 0;
277         int pm_state = VCONFKEY_PM_STATE_NORMAL;
278
279         old_mode = __netconfig_wifi_bgscan_get_mode();
280         if (old_mode == scan_mode) {
281                 wifi_complete_set_bgscan(wifi, context);
282                 return TRUE;
283         }
284
285         __netconfig_wifi_bgscan_set_mode(scan_mode);
286
287         netconfig_wifi_bgscan_stop();
288
289         /* In case of LCD off, we don't need Wi-Fi scan right now */
290         vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
291         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
292                 netconfig_wifi_bgscan_start(FALSE);
293         else
294                 netconfig_wifi_bgscan_start(TRUE);
295
296         wifi_complete_set_bgscan(wifi, context);
297         return TRUE;
298 }
299
300 gboolean handle_resume_bgscan(Wifi *wifi, GDBusMethodInvocation *context)
301 {
302         netconfig_wifi_set_bgscan_pause(FALSE);
303
304         wifi_complete_resume_bgscan(wifi, context);
305         return TRUE;
306 }
307
308 gboolean handle_pause_bgscan(Wifi *wifi, GDBusMethodInvocation *context)
309 {
310         netconfig_wifi_set_bgscan_pause(TRUE);
311
312         wifi_complete_pause_bgscan(wifi, context);
313         return TRUE;
314 }
315