Tethering: Do not trigger scan event when turning on Wi-Fi tethering
[platform/core/connectivity/net-config.git] / src / wifi-background-scan.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 "wifi.h"
27 #include "netdbus.h"
28 #include "wifi-state.h"
29 #include "wifi-background-scan.h"
30
31 #define SCAN_PERIODIC_DELAY             10
32 #define SCAN_EXPONENTIAL_MIN    4
33 #define SCAN_EXPONENTIAL_MAX    128
34
35 enum {
36         WIFI_BGSCAN_MODE_EXPONENTIAL = 0x00,
37         WIFI_BGSCAN_MODE_PERIODIC,
38         WIFI_BGSCAN_MODE_MAX,
39 };
40
41 struct bgscan_timer_data {
42         guint time;
43         guint mode;
44         guint timer_id;
45 };
46
47 static gboolean netconfig_wifi_scanning = FALSE;
48
49 static struct bgscan_timer_data *__netconfig_wifi_bgscan_get_bgscan_data(void)
50 {
51         static struct bgscan_timer_data timer_data = {SCAN_EXPONENTIAL_MIN, WIFI_BGSCAN_MODE_EXPONENTIAL, 0};
52
53         return &timer_data;
54 }
55
56 static guint __netconfig_wifi_bgscan_mode(gboolean is_set_mode, guint mode)
57 {
58         static guint bgscan_mode = WIFI_BGSCAN_MODE_EXPONENTIAL;
59
60         if (is_set_mode != TRUE)
61                 return bgscan_mode;
62
63         if (mode < WIFI_BGSCAN_MODE_MAX)
64                 bgscan_mode = mode;
65
66         DBG("Wi-Fi background scan mode set %d", bgscan_mode);
67
68         return bgscan_mode;
69 }
70
71 static void __netconfig_wifi_bgscan_set_mode(guint mode)
72 {
73         __netconfig_wifi_bgscan_mode(TRUE, mode);
74 }
75
76 static guint __netconfig_wifi_bgscan_get_mode(void)
77 {
78         return __netconfig_wifi_bgscan_mode(FALSE, -1);
79 }
80
81 static gboolean __netconfig_wifi_bgscan_request_connman_scan(void)
82 {
83         DBusMessage *reply = NULL;
84
85         if (netconfig_wifi_state_get_service_state() == NETCONFIG_WIFI_CONNECTED)
86                 if (__netconfig_wifi_bgscan_get_mode() == WIFI_BGSCAN_MODE_EXPONENTIAL)
87                         return FALSE;
88
89         if (netconfig_wifi_state_get_service_state() == NETCONFIG_WIFI_CONNECTING)
90                 return FALSE;
91
92         netconfig_wifi_set_scanning(TRUE);
93
94                 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE, CONNMAN_WIFI_TECHNOLOGY_PREFIX,
95                         CONNMAN_TECHNOLOGY_INTERFACE, "Scan", NULL);
96
97         if (reply == NULL) {
98                 ERR("Error! Request failed");
99                 return FALSE;
100         }
101
102         dbus_message_unref(reply);
103
104         return TRUE;
105 }
106
107 static gboolean __netconfig_wifi_bgscan_request_scan(gpointer data);
108
109 static void __netconfig_wifi_bgscan_start_timer(struct bgscan_timer_data *data)
110 {
111         if (data == NULL)
112                 return;
113
114         netconfig_stop_timer(&(data->timer_id));
115
116         data->mode = __netconfig_wifi_bgscan_get_mode();
117
118         switch (data->mode) {
119         case WIFI_BGSCAN_MODE_EXPONENTIAL:
120                 if (data->time == 0)
121                         data->time = SCAN_EXPONENTIAL_MIN;
122                 else if ((data->time >= SCAN_EXPONENTIAL_MAX) ||
123                                 (data->time > SCAN_EXPONENTIAL_MAX / 2))
124                         data->time = SCAN_EXPONENTIAL_MAX;
125                 else
126                         data->time = data->time * 2;
127
128                 break;
129         case WIFI_BGSCAN_MODE_PERIODIC:
130                 data->time = SCAN_PERIODIC_DELAY;
131
132                 break;
133         default:
134                 DBG("Error! Wi-Fi background scan mode [%d]", data->mode);
135                 return;
136         }
137
138         DBG("Register background scan timer with %d seconds", data->time);
139
140         netconfig_start_timer_seconds(data->time,
141                         __netconfig_wifi_bgscan_request_scan, data, &(data->timer_id));
142 }
143
144 static void __netconfig_wifi_bgscan_stop_timer(struct bgscan_timer_data *data)
145 {
146         if (data == NULL)
147                 return;
148
149         netconfig_stop_timer(&(data->timer_id));
150 }
151
152 static gboolean __netconfig_wifi_bgscan_request_scan(gpointer data)
153 {
154         struct bgscan_timer_data *timer = (struct bgscan_timer_data *)data;
155         int pm_state = VCONFKEY_PM_STATE_NORMAL;
156         int hotspot_wifi_state = VCONFKEY_MOBILE_HOTSPOT_WIFI_OFF;
157
158         if (timer == NULL)
159                 return FALSE;
160
161         /* If Wi-Fi tethering is pending on, don't trigger scan event*/
162         vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_WIFI_STATE, &hotspot_wifi_state);
163         if (hotspot_wifi_state == VCONFKEY_MOBILE_HOTSPOT_WIFI_PENDING_ON) {
164                 DBG("hotspot_wifi_state %d", hotspot_wifi_state);
165                 return TRUE;
166         }
167
168         /* In case of LCD off, we don't need Wi-Fi scan */
169         vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
170         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
171                 return TRUE;
172
173         __netconfig_wifi_bgscan_stop_timer(timer);
174
175         DBG("Request Wi-Fi scan to ConnMan");
176         __netconfig_wifi_bgscan_request_connman_scan();
177
178         __netconfig_wifi_bgscan_start_timer(timer);
179
180         return FALSE;
181 }
182
183 static void __netconfig_wifi_bgscan_mode_cb(keynode_t* node, void* user_data)
184 {
185         int value;
186         int wifi_state;
187
188         if (vconf_get_int(VCONFKEY_WIFI_BGSCAN_MODE, &value) < 0) {
189                 ERR("VCONFKEY_WIFI_BGSCAN_MODE get failed");
190                 return;
191         }
192
193         DBG("Background scanning mode is changed : %d", value);
194
195         __netconfig_wifi_bgscan_set_mode((guint)value);
196
197         if (vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state) < 0) {
198                 ERR("VCONFKEY_WIFI_STATE get failed");
199                 return;
200         }
201
202         if (wifi_state == VCONFKEY_WIFI_OFF)
203                 return;
204
205         struct bgscan_timer_data *timer_data = __netconfig_wifi_bgscan_get_bgscan_data();
206
207         if (timer_data->timer_id != 0)
208                 netconfig_wifi_bgscan_stop();
209
210         netconfig_wifi_bgscan_start();
211 }
212
213 void netconfig_wifi_bgscan_start(void)
214 {
215         struct bgscan_timer_data *timer_data =
216                         __netconfig_wifi_bgscan_get_bgscan_data();
217
218         if (timer_data == NULL)
219                 return;
220
221         DBG("Wi-Fi background scan start");
222
223         __netconfig_wifi_bgscan_start_timer(timer_data);
224 }
225
226 void netconfig_wifi_bgscan_stop(void)
227 {
228         struct bgscan_timer_data *timer_data =
229                         __netconfig_wifi_bgscan_get_bgscan_data();
230
231         if (timer_data == NULL)
232                 return;
233
234         DBG("Wi-Fi background scan stop");
235
236         timer_data->time = SCAN_EXPONENTIAL_MIN;
237
238         __netconfig_wifi_bgscan_stop_timer(timer_data);
239 }
240
241 gboolean netconfig_wifi_get_bgscan_state(void)
242 {
243         struct bgscan_timer_data *timer_data =
244                         __netconfig_wifi_bgscan_get_bgscan_data();
245
246         return ((timer_data->timer_id > (guint)0) ? TRUE : FALSE);
247 }
248
249 gboolean netconfig_wifi_get_scanning(void)
250 {
251         return netconfig_wifi_scanning;
252 }
253
254 void netconfig_wifi_set_scanning(gboolean scanning)
255 {
256         if (netconfig_wifi_scanning != scanning)
257                 netconfig_wifi_scanning = scanning;
258 }
259
260 gboolean netconfig_iface_wifi_set_bgscan(NetconfigWifi *wifi, guint scan_mode, GError **error)
261 {
262         struct bgscan_timer_data *timer_data = __netconfig_wifi_bgscan_get_bgscan_data();
263
264         __netconfig_wifi_bgscan_set_mode(scan_mode);
265
266         if (timer_data->timer_id != 0)
267                 netconfig_wifi_bgscan_stop();
268
269         netconfig_wifi_bgscan_start();
270
271         return TRUE;
272 }
273
274 void netconfig_wifi_init_bgscan()
275 {
276         guint scan_mode = __netconfig_wifi_bgscan_get_mode();
277
278         if (scan_mode == WIFI_BGSCAN_MODE_PERIODIC)
279                 vconf_set_int(VCONFKEY_WIFI_BGSCAN_MODE, VCONFKEY_WIFI_BGSCAN_MODE_PERIODIC);
280         else
281                 vconf_set_int(VCONFKEY_WIFI_BGSCAN_MODE, VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL);
282
283         if (vconf_notify_key_changed(VCONFKEY_WIFI_BGSCAN_MODE,
284                         __netconfig_wifi_bgscan_mode_cb, NULL))
285                 DBG("Failed to set notify callback");
286 }
287
288 void netconfig_wifi_deinit_bgscan()
289 {
290         if (vconf_ignore_key_changed(VCONFKEY_WIFI_BGSCAN_MODE,
291                         __netconfig_wifi_bgscan_mode_cb))
292                 DBG("Failed to unset notify callback");
293 }
294